cancel
Showing results for 
Search instead for 
Did you mean: 

How to detect what level digital input caused interupt

SSmit.13
Associate III

Hi

  I have pin PA6 setup to interupt on high and low levels. I have done the following:

GPIOA->MODER &= ~GPIO_MODER_MODE6; //PA6 as input

SYSCFG->EXTICR[1] &= ~SYSCFG_EXTICR2_EXTI6; //PA6

EXTI->RTSR1 |= EXTI_RTSR1_RT6; //enable rising edge

EXTI->FTSR1 |= EXTI_FTSR1_FT6; //enable falling edge...

EXTI->IMR1 |= EXTI_IMR1_IM6;

NVIC_SetPriority(EXTI9_5_IRQn,1);

NVIC_EnableIRQ(EXTI9_5_IRQn);

In the interupt routine, I  simply set a variable when interupt is because of low/high (just for testing).

volatile char ExtLow=0;

volatile char ExtHigh=0;

void EXTI9_5_IRQHandler(void)

{

if((EXTI->PR1 & EXTI_PR1_PIF6)==EXTI_PR1_PIF6)

{

EXTI->PR1 |= EXTI_PR1_PIF6;

if(! (GPIOA->IDR & GPIO_ODR_OD6))

ExtLow=1;

else

ExtHigh=1;

}

}

The pulse with is for about 100ms, not fast (processor at 80MHz). If I put a break point on ExtLow=1; line, it never breaks here. But the interupt does get called, which I have checked. Even when I simply set for low level interupt (not high), it doesnt break, and again, the interupt does get called. Anyone any idea how I can check if its a low edge or high edge that caused the interupt?

 

Many Thanks

Scott

 

11 REPLIES 11

Which STM32? What hardware?

Sounds like mystery. Code is OK, tried on Disco'L476 (PA5 as that's available) and works as expected.

Instead of breakpoint, try toggling a pin, and observe using oscilloscope/LA.

Or, maybe as a starter, try a simple loop (no interrupt) in which you copy bit 6 of GPIOA->IDR onto some output pin.

JW

TDK
Guru

What you're doing should work. Instead of an input, set it as an output and toggle in the main loop. You should get an interrupt on every toggle and IDR should show the appropriate value (high or low). Even as an output, IDR is still connected/accurate.

If whatever is toggling the signal does a very short pulse, you will only get one interrupt if you don't clear the flag before the second edge.

If you feel a post has answered your question, please click "Accept as Solution".
Pavel A.
Evangelist

Anyone any idea how I can check if its a low edge or high edge that caused the interupt?

Easy. Just set the trigger condition to Falling edge only and repeat your test. Can you catch the fall condition correctly?

Then repeat with Rising edge only. Can you catch the rise condition correctly?

Once both conditions work separately, enable both. If not able to understand the reason of interrupt - it was a glitch (very short change or series of such changes that cannot be adequately captured by your hardware).

Hi

  I put a logic analyser on the pin, and you can see the step , about 100ms. So strange, the interrupt gets called so it must be detected. So strange

 

Scott

I did try this, and both carried out an interupt on only rising and falling. When sampling the pin in the IDR, always high. So strange. I have a logic analyser on the pin, and can see the pulse no problem.

Pavel A.
Evangelist

Is GPIOA clock enabled in RCC?  If yes... bring some holy water, spray on the board.

Ads TDK hinted above, your LA may be not fast enough to catch a glitch at the edge of the pulse. Or, the edge rises/falls too slowly and has enough noise to generate both rising and falling event in the EXTI unit.

Do what he suggested in the post, generate the pulse with the same pin you are detecting.

JW

I have set an interrupt to be generated from High to Low, and also after tried from Low to High. Both times the interrupt routing is called and read the input pin. Both times , it is the same value. The clock is running at 80MHz , and the pulse width is approx 100ms, so shouldnt be too fast. Input looks clean on the scope.

As the pin is setup as input, how can I generate a pulse from the same pin?

> As the pin is setup as input, how can I generate a pulse from the same pin?

You set it up as output instead (and disconnect it from whatever is driving it externally).

If you feel a post has answered your question, please click "Accept as Solution".