force edge-triggered behaviour of EXTI interrupt

Hi Wiznet Developers,
I want to use the EXTI interrupt on W7500p to set a flag, when a button is pressed. However, the EXTI is implemented as level-triggered interrupt. This means as long as the button is pressed, the interrupt becomes pending again, and the processor must execute its ISR again. The program keeps executing the ISR again and again and will only return to main after the button was released.
Now, I want only one execution of the ISR when the button is pressed and then immediate return to main. In other words I would like to force an edge-triggered behaviour on EXTI. Has anyone else tried this?

I wrote the following EXTI ISR:

    void EXTI_Handler(void)
    {
    	//read current state of EXTI Source PC14
    	uint8_t PC14_state = GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_14);
    	if (PC14_state==0) //if EXTI source PC14 is low (button pressed)
    	{
    		preset = 1;//set Preset-1-Flag
    		EXTI_Polarity_Set(PAD_PC,GPIO_Pin_14,EXTI_Trigger_Rising); // invert Polarity	
    		NVIC_ClearPendingIRQ(EXTI_IRQn); //clear pending interrupts
    	}
    	else //if EXTI source PC14 is high (button released)
    	{
    		EXTI_Polarity_Set(PAD_PC,GPIO_Pin_14,EXTI_Trigger_Falling); //invert Polarity again
    	}
    }

I thought, if I change the polarity of the EXTI Trigger in the ISR this would prevent the EXTI from becoming pending again. Unfortunately, this does not work. I observed that the EXTI does indeed trigger once when the button is pressed and once again when it is released. However, as long as I held the button pressed, the execution still keeps returning to the instructions of the if-statement. I don’t really understand why this happens.

Does anyone have any idea, how I could do this correctly?

First, we apologize that the provided Define name is a misleading name.

If you look at the data sheet of W7500P, you can see the following figure related to EXTI.

Interruption occurs only for Low and High values in this logic structure.

Therefore, if you continuously press a specific button that has set EXTI, it is normal that interrupt occurs continuously even if Pending is cleared.

This is caused by the EXTI_Handler you created.

This is caused by changing the polarity.
This is because when you press the button, the polarity changes to Trigger_HIGH, and an interrupt occurs again when you release the button.


The conclusion is that in case of W7500P, you need to use GPIO interrupt to use falling rising edge.

Please refer to the GPIO/Interrupt example below.

Hi,

I recommend using the interrupt function of the GPIO register.
This interrupt is capable of rising and falling detect.

 void main() {
     /* .............................. */
     GPIO_INT_Configuration(GPIOC, GPIO_Pin_14, Rising); //or falling
     NVIC_ClearPendingIRQ(PORT2_IRQn); // Pending bit Clear
     NVIC_EnableIRQ(PORT2_IRQn);       //PORT2 Interrupt Enable
     /*.........................*/
}

void PORT2_Handler(void)
{
    preset = 1;
    GPIO_INT_Clear(GPIOC);
    NVIC_ClearPendingIRQ(PORT2_IRQn);
}

I think that this code will work the way you want it.
If not, please reply.

Thank you

Hey guys,
@becky: Your code works fine! thank you.

Now I want to add a post to this thread, because in the course of my coding process I noticed 2 things:

  1. GPIO interrupts require the programmer to clear the interrupt with GPIO_INT_Clear() at the end of the ISR while EXTI Interrupt automatically leaves the ISR as soon as the interrupt condition becomes false. That’s a nice little fact to know.
  2. GPIO_INT_Configuration() already calls NVIC_EnableIRQ(). If the function GPIO_INT_Configuration() is called multiple times, then also NVIC_EnableIRQ() is called multiple times. This can cause problems.
    Example:
    		GPIO_INT_Configuration(GPIOC, GPIO_Pin_14, Falling);
    		GPIO_INT_Configuration(GPIOC, GPIO_Pin_13, Falling);
    		GPIO_INT_Configuration(GPIOC, GPIO_Pin_12, Falling);
    		GPIO_INT_Configuration(GPIOC, GPIO_Pin_9, Falling);
    		NVIC_EnableIRQ(PORT2_IRQn);

This code won’t work. Why?