This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Both edges interrupt from GPIO

Hello,

I'm looking for a solution for my task (LM4F120)

I have pin setup for reaction and trigger interrupt on both edges.

Different operations must be made depending what was source of interrupt - rising edge or falling.

Is there a register/way to distinguish inside interrupt handler code which edge was source of interrupt ?

Thanks in advance :)

  • Unless your trigger signal is very, very fast - suspect that your "read" of that trigger pin's state (high or low) very early w/in your interrupt handler - will work. 

    Should this read w/in the interrupt handler reveal signal as "high" - your edge was rising. 

    We've measured the response of such GPIO interrupts at < 1uS - so this method should work for all but the highest frequencies input...

    Should your requirement exceed this method's frequency limitation - simple solution would see your input signal routed to 2 different GPIO inputs (on different ports) with each pin triggering on opposite edges.  Entry into the respective interrupt handler (again - different ports) confirms the signal's edge...  The GPIOIEV Register enables selection of the specific edge.  It may be possible to employ 2 GPIO from the same Port (setting GPIOIEV uniquely (i.e. opposite) for each of the 2 pins) although we've not yet attempted this "single port" method...

  • Hi,

    On LM4F120 Port P and Port Q have dedicated interrupt handlers for each pin - so it may be easier to implement the requirement.

    Petrei

  • Thanks for so simple solution :)

    Minimum pulse time is 25 uS so ~1uS read time is not a problem.

    I will try both solution and share which method works better :)

    Thanks.

  • Petrei said:
    LM4F120 Port P and Q have dedicated interrupt handlers for each pin

    Believe this a bit "non-standard" - but very good get.

    Wonder if the expected - "extra silicon" adds any delay to the interrupt's responsiveness.  If yes - the ability to singularly resolve comes with some cost.

    All in all - suspect that the more "general" solution supplied earlier (in 2 flavors) will be more valuable due to wider range of support and freedom from new/added limitations...

  • I've tested first solution and it works ok however results I'm getting are  "weird".

    What I'm trying to get is to measure  length of impulse from ultrasonic distance meter. Distance is proportional to pulse length. I can't use Period Time mode for timer since measure is on user request so no period measure.

    All trigerring and other stuff is workin as expected. Problem is with measure timer. (TIMER3)

    I've setup timer to work with 1MHz clock and max period of 40ms(max from sensor is 25ms):

    TimerConfigure(TIMER2_BASE,TIMER_CFG_16_BIT_PAIR|TIMER_CFG_A_PERIODIC_UP);
    TimerDisable(TIMER2_BASE,TIMER_A);
    // timer clock 80MHz/80 -1 MHz
    TimerPrescaleSet(TIMER2_BASE,TIMER_A,80);
    // overflow every 40 ms - should never happend.
    TimerLoadSet(TIMER2_BASE,TIMER_A,65000);

    What I'm doing is waiting for rising edge on one of pins and then this  fire GPIO interrupts where I'm reading pin state and if it is high -> starting this timer.

    Falling edge next GPIO ISR  -  if state is low , timer stop, read timer value, zero it and calculate distance based on number in timer counter.

    I'm getting very weird data like timer is not working with 1 MHz clock. I've checked distance meter with oscilloscope - it's OK

    Here is GPIO Interrupt:

    void HC_ISR(void) {
    GPIOPinIntClear(HC_PORT,HC_ECHO);
    trigger = GPIOPinRead(HC_PORT,HC_ECHO);
    if (trigger == 1 ) {
    TIMER2_TAV_R = 0x0;
    //enable timer
    //TimerEnable(TIMER2_BASE,TIMER_A);
    TIMER2_CTL_R |= TIMER_CTL_TAEN;
    } else {
    TIMER2_CTL_R &= ~TIMER_CTL_TAEN;
    // //TIMER2_TAV_R = 0x0;
    count = TimerValueGet(TIMER2_BASE,TIMER_A);
    distance = count / 58;
    log("Distance: ");
    sprintf(s_count,"(%d us) %d cm",count,distance);
    log(s_count);
    log("\n\r");
    }
    }

    And result ..:

    Distance: (21799 us) 375 cm

    Should be ~ 18cm (timer value in register should be  ~ 1050) not 21k.. :(

    Small update - if I switch to 32-bit timer withour prescaler and make calculations manually - everything is working like a charm :)

    What is wrong in my setup of 16-bit timer ?? :)

  • This new post is wildly outside the range of your initial post - thus no one searching for Timer assistance would have a reasonable chance of landing here.  Vendor monitors do not like this - and we should comply...

    Suggest that you launch a new post - subject/titled as well as you did on your initial post here.   And may be "fair play" to Verify Answer my quick/complete initial response...

  • Hi,

    @cb1-: I know your 2 solutions are OK, but not knowing how will be used I just added the mention of per-pin interrupt od the two ports. But it seems the solution is not good for this case..

    @Marcin: I think your calculation could be wrong - if the clock is 1 us, then an overflow should be at 65.535 ms, not 40. Use a GPIO pin as output to spy what you have done - set it hi when rising edge and lo when falling edge and compare with the input signal. Some other observations: counting down is more efficient in terms of generated code, and the calculations are easier to do. Second, in your case you can use the timer directly in capture mode (input edge timer mode) - no GPIO interrupt needed - the timer is started by a rising edge, the level can be checked by reading the pin as GPIO pin. You are in a fortunate situation when the response from the sensor start always with a rising edge. Next, do not use sprintf/printf from interrupts - just remember the calculation result in a variable and print it from main. What is the distance between the two measurements? (around 20 ms?) 

    Using a GPIO as you have done you loose some time until you start the timer - take into consideration also the smallest distance you need to measure and then choose the clock duration to satisfy the accuracy needed for the measurement at this distance.

    Petrei

  • Guys,

    Thanks for very usefull information.

    I have working solution on 32-bit timer, and since I'm not using all of them that is ok currently.

    @Petrei

    1uS timer resolution is ok and it is not importand whether timer period is 40 ms or 65 ms. Sensor never returns more than 38 ms which is infinity from sensor side.

    What was important is uS resolution. On 16-bit timer I gor bogus results. With 32 - all is OK.

    Thanks for information about avoiding sprintf. I know about capture mode however I was unable to set it properly. 

    Measure period is 100ms so timing is not so critical, and I'm already working with aquarium and water as a reflection surface. 

    Purpose of device is to measure water level in aquarium and inform if it is below or above some levels.

    Now some math to calculate since water is always moving surface, and I have to avoid false positives :)

    Again thanks for knowledge you shared.

    I believe we can close this topic.

    Regards,