I am writing code with the STM323 ide and using the STM32f303re nucleo board. I configured pin PA7 as an interrupt, however it does not have its own interrupt handler like previous development boards i've worked with.
As you can see, this one interrupt handler handles interrupts from pins 9-5, thus if any of these pins are triggered they will call the same interrupt. I need to be able to perform different functions depending on which pin is triggered. Is there a way to know which specific pin was causing the interrupt?
CodePudding user response:
You can use EXTI_GetITStatus, to check which line causing interrupt.
/* Handle PA7 interrupt */
void EXTI9_5_IRQHandler(void) {
/* Make sure that interrupt flag is set */
if (EXTI_GetITStatus(EXTI_Line7) != RESET) {
/* Do your stuff when PA7 is changed */
/* Clear interrupt flag */
EXTI_ClearITPendingBit(EXTI_Line7);
}
}
Do not forget to clear flag after.
CodePudding user response:
For the cases when multiple pins share an interrupt, when the interrupt fires, you need to check what pin specifically caused an interrupt. Unlike pin 1 interrupt, where the interrupt itself means it was pin 1 and you can process it right away, in this case an interrupt means "it's either pin 5, or 6, or 7, or 8, or 9", so in the ISR you need to check "was it pin 5? or 6?..."
I think it's a good opportunity to look directly into the registers of EXTI peripheral.
If you open the reference manual of your MCU on page 299, section 14.3.6, you can see this EXTI_PR1 register holds pending bits for lines 0..31. Those bits are marked as rc_w1, which from the start of the document means (reference manual, page 46):
read/clear (rc_w1)
Software can read as well as clear this bit by writing 1. Writing ‘0’ has no effect on the bit value.
So the logic is the following: if an interrupt of lines 5..9 occurred, you need to check what bit specifically in that register is set to 1, and then you write 1 there to reset it. This will clear the flag.
void EXTI9_5_IRQHandler(void)
{
if(EXTI_PR1 & (1U<<5U)) //check if it's line 5, returns 0 if PR5 is 0, otherwise returns non-zero, which is true
{
EXTI_PR1 |= (1U<<5U); //write 1 to that bit to clear it so interrupt doesn't fire again once ISR is finished
do_stuff_if_it's_pin5();
}
}
Alternatively, instead of 1U<<5U you should be able to use EXTI_PR1_PR5, so the code would look a little easier to read, like this:
void EXTI9_5_IRQHandler(void)
{
if(EXTI_PR1 & EXTI_PR1_PR5) //check if it's line 5, returns 0 if PR5 is 0, otherwise returns non-zero, which is true
{
EXTI_PR1 |= EXTI_PR1_PR5; //write 1 to that bit to clear it so interrupt doesn't fire again once ISR is finished
do_stuff_if_it's_pin5();
}
}
This is what the functions provided by @Lime7 do behind the scenes, I suspect (can't check, but it makes logical sense).
I don't have that microcontroller to test it, but it should work.