Hello,
I'm developing on a LPCXpresso LPC1769 (OM13085) board using LPCOpen's chip specific drivers ("lpc_chip_175x_6x").
According to the manual, chapter 9:
- Port 0 and Port 2 can provide a single interrupt for any combination of port pins.
- Each port pin can be programmed to generate an interrupt on a rising edge, a falling edge, or both.
I'd like trigger an interrupt on both a rising edge and a falling edge on a GPIO pin signal.
However, when the ISR EINT3_IRQHandler() is called, GPIO interrupt status registers indicate a falling edge interrupt (register IO0IntStatF) and a rising edge interrupt (register IO0IntStatR).
Why is this?
This is my example code:
#include "chip.h"
#include <stdio.h>
/* use semi-hosting for printf() console output */
void EINT3_IRQHandler(void) {
printf("GPIO IRQ Status:%08x ENF:%08x ENR:%08x\n",
LPC_GPIOINT->STATUS,
LPC_GPIOINT->IO0.ENF,
LPC_GPIOINT->IO0.ENR);
Chip_GPIOINT_ClearIntStatus(LPC_GPIOINT, GPIOINT_PORT0, 1 << 19);
}
int main(void) {
SystemCoreClockUpdate();
printf("Start\n");
// configure Pin P0.19 for interrupt on input signal change
Chip_GPIOINT_ClearIntStatus(LPC_GPIOINT, GPIOINT_PORT0, 1 << 19);
Chip_GPIOINT_SetIntFalling( LPC_GPIOINT, GPIOINT_PORT0, 1 << 19);
Chip_GPIOINT_SetIntRising( LPC_GPIOINT, GPIOINT_PORT0, 1 << 19);
NVIC_ClearPendingIRQ(EINT3_IRQn); // avoid extraneous IRQ on restart
NVIC_EnableIRQ(EINT3_IRQn);
volatile static int i = 0 ;
Chip_GPIO_Init(LPC_GPIO);
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 17); // Pin P0.17
Chip_GPIO_SetPinDIROutput(LPC_GPIO, 0, 22); // red led on board
while(1) {
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 17);
Chip_GPIO_SetPinOutHigh(LPC_GPIO, 0, 22);
for (i = 0; i< 10000000; i++) { }
Chip_GPIO_SetPinOutLow(LPC_GPIO, 0, 17);
Chip_GPIO_SetPinOutLow(LPC_GPIO, 0, 22);
for (i = 0; i< 10000000; i++) { }
}
return 0 ;
}
I wired GPIO output P0.17 to P0.19.
This is the output I get:
[MCUXpresso Semihosting Telnet console for 'Test02-newlib LinkServer Debug' started on port 60095 @ 127.0.0.1]
Start
GPIO IRQ Status:00000001 ENF:00080000 ENR:00080000
GPIO IRQ Status:00000001 ENF:00080000 ENR:00080000
GPIO IRQ Status:00000001 ENF:00080000 ENR:00080000
Thanks for your comments.
Solved! Go to Solution.
Hello Daniel,
If you reference the user manual (UM10360.pdf) chapter 9 table 103. You will see that ENR and ENF represents if the GPIO Interrupt is enable for Rising and Falling edge respectively.
So, since you want to trigger the interrupt on both rising edge and a falling edge the values of ENR and ENF will always be 1. The values you need to look to know which interrupt was triggered are STATR and STATF, since these values represent the status for either rising edge and falling edge interrupt.
I made an example using the same characteristics that you mentioned, so you can see how the registers work. In the next image you can see that the values of ENR and ENF are static in 1 since I activate the interrupt in both edges. But, the value of STATF changed to 1 because the falling edge interrupt was triggered, STATR reminds low.
In the next interrupt you can see that the values of ENR and ENF are still the same. However, this time the STATF is 0 and STATR is 1 since now you detected a rising edge interrupt.
So, in your interrupt handler you should check these values. Here is the handler I declared for the example I made.
void GPIO_IRQ_HANDLER(void)
{
if(LPC_GPIOINT->IO0.STATR != 0){ //Rising edge detected
Board_LED_Set(0, true);//turns off the red led
Board_LED_Set(1, false);//turns on the blue led
}
else if(LPC_GPIOINT->IO0.STATF != 0){//Falling edge detected
Board_LED_Set(1, true);//turns off the red led
Board_LED_Set(0, false);//turns on the blue led
}
Chip_GPIOINT_ClearIntStatus(LPC_GPIOINT, GPIO_INTERRUPT_PORT, 1 << GPIO_INTERRUPT_PIN);
}
Calling a printf function inside the handler is not a really good practice. I changed a little bit the example. When I detect a rising edge I turn on the blue led of the evaluation board, and when I detect a falling edge I turn on the red led.
Hope it helps!
Victor.
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi, I'm Using LPC1754, where I have selected Port 1 for DI, so cant I enable it as interrupt? I saw PORT 0 and PORT 2 are selected as interrupt in datasheet. Is the interrupt option exclusively for PORT0 and PORT2?
I think so. The manual states:
9.2.2 Interrupt generating digital ports
• Port 0 and Port 2 can provide a single interrupt for any combination of port pins.
Hello Daniel,
If you reference the user manual (UM10360.pdf) chapter 9 table 103. You will see that ENR and ENF represents if the GPIO Interrupt is enable for Rising and Falling edge respectively.
So, since you want to trigger the interrupt on both rising edge and a falling edge the values of ENR and ENF will always be 1. The values you need to look to know which interrupt was triggered are STATR and STATF, since these values represent the status for either rising edge and falling edge interrupt.
I made an example using the same characteristics that you mentioned, so you can see how the registers work. In the next image you can see that the values of ENR and ENF are static in 1 since I activate the interrupt in both edges. But, the value of STATF changed to 1 because the falling edge interrupt was triggered, STATR reminds low.
In the next interrupt you can see that the values of ENR and ENF are still the same. However, this time the STATF is 0 and STATR is 1 since now you detected a rising edge interrupt.
So, in your interrupt handler you should check these values. Here is the handler I declared for the example I made.
void GPIO_IRQ_HANDLER(void)
{
if(LPC_GPIOINT->IO0.STATR != 0){ //Rising edge detected
Board_LED_Set(0, true);//turns off the red led
Board_LED_Set(1, false);//turns on the blue led
}
else if(LPC_GPIOINT->IO0.STATF != 0){//Falling edge detected
Board_LED_Set(1, true);//turns off the red led
Board_LED_Set(0, false);//turns on the blue led
}
Chip_GPIOINT_ClearIntStatus(LPC_GPIOINT, GPIO_INTERRUPT_PORT, 1 << GPIO_INTERRUPT_PIN);
}
Calling a printf function inside the handler is not a really good practice. I changed a little bit the example. When I detect a rising edge I turn on the blue led of the evaluation board, and when I detect a falling edge I turn on the red led.
Hope it helps!
Victor.
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Good catch, Victor. While I wrote in the text that one has to read, e.g., register IO0IntStatF, the code does not do that and instead reads the enable registers. Thanks.