5.11 EXTI Guide
This chapter covers the files of the EXTI driver in the N32H49x standard peripheral library, its 9 public functions, and the KeyInterrupt example. Read it together with the “EXTI” chapter of the user manual for the hardware details of interrupt lines, event lines, and the GPIO-line to EXTI-line mapping.
5.11.1 Related files
| Relative path | Purpose |
|---|---|
firmware/n32h49x_std_periph_driver/inc/n32h49x_exti.h |
Defines the EXTI mode and trigger-edge enumerations, the EXTI_InitType structure, and the EXTI line and timestamp line selection macros;declares the 9 public functions in five sections (initialization, software trigger, status flags, interrupts, timestamp) |
firmware/n32h49x_std_periph_driver/src/n32h49x_exti.c |
Implements the 9 functions: register reset, writing the mask and trigger edges, software interrupt generation, status flag and interrupt pending bit access, and timestamp input selection |
projects/n32h49x_EVAL/examples/EXTI/ |
EXTI example root, containing the KeyInterrupt example |
projects/n32h49x_EVAL/examples/EXTI/KeyInterrupt/ |
Project layout of that example: MDK-ARM/, EWARM/, inc/, src/, readme.txt |
projects/n32h49x_EVAL/bsp/ |
Board support files used by the example: log initialization and print UART remapping |
5.11.2 API reference
The 9 public functions below follow the declaration order of n32h49x_exti.h and fall into 5 groups; each entry gives a summary and the original comment directly above the function in n32h49x_exti.c.
Initialization
EXTI_DeInit, EXTI_InitPeripheral, EXTI_InitStruct
Software trigger
EXTI_TriggerSWInt
Status flags
EXTI_GetStatusFlag, EXTI_ClrStatusFlag
Interrupts
EXTI_GetITStatus, EXTI_ClrITPendBit
Timestamp
EXTI_RTCTimeStampSel
void EXTI_DeInit(void)Reset the EXTI registers.
name EXTI_DeInit.
fun Reset the EXTI registers.
return none
void EXTI_InitPeripheral(EXTI_InitType* EXTI_InitStruct)Initializes the EXTI according to EXTI_InitStruct.
name EXTI_InitPeripheral.
fun Initializes the EXTI according to EXTI_InitStruct.
param EXTI_InitStruct(The input parameters must be the following values) :
- EXTI_Line
- EXTI_LINE0
- EXTI_LINE1
- EXTI_LINE2
- EXTI_LINE3
- EXTI_LINE4
- EXTI_LINE5
- EXTI_LINE6
- EXTI_LINE7
- EXTI_LINE8
- EXTI_LINE9
- EXTI_LINE10
- EXTI_LINE11
- EXTI_LINE12
- EXTI_LINE13
- EXTI_LINE14
- EXTI_LINE15
- EXTI_LINE16
- EXTI_LINE17
- EXTI_LINE18
- EXTI_LINE19
- EXTI_LINE20
- EXTI_LINE21
- EXTI_LINE22
- EXTI_LINE23
- EXTI_LINE24
- EXTI_Mode
- EXTI_Mode_Event
- EXTI_Mode_Interrupt
- EXTI_Trigger
- EXTI_Trigger_Falling
- EXTI_Trigger_Rising
- EXTI_Trigger_Rising_Falling
- EXTI_LineCmd:
- ENABLE
- DISABLE
return none
void EXTI_InitStruct(EXTI_InitType* EXTI_InitStruct)Fills each EXTI_InitStruct member with its default value.
name EXTI_InitStruct.
fun Fills each EXTI_InitStruct member with its default value.
param InitStruct :
- Pointer to the EXTI_InitType structure which will be initialized.
return none
void EXTI_TriggerSWInt(uint32_t EXTI_Line)Generates a Software interrupt.
name EXTI_TriggerSWInt.
fun Generates a Software interrupt.
param EXTI_Line(The input parameters must be the following values) :
- EXTI_LINE0
- EXTI_LINE1
- EXTI_LINE2
- EXTI_LINE3
- EXTI_LINE4
- EXTI_LINE5
- EXTI_LINE6
- EXTI_LINE7
- EXTI_LINE8
- EXTI_LINE9
- EXTI_LINE10
- EXTI_LINE11
- EXTI_LINE12
- EXTI_LINE13
- EXTI_LINE14
- EXTI_LINE15
- EXTI_LINE16
- EXTI_LINE17
- EXTI_LINE18
- EXTI_LINE19
- EXTI_LINE20
- EXTI_LINE21
- EXTI_LINE22
- EXTI_LINE23
- EXTI_LINE24
return none
FlagStatus EXTI_GetStatusFlag(uint32_t EXTI_Line)Get EXTI line flag status.
name EXTI_GetStatusFlag.
fun Get EXTI line flag status.
param EXTI_Line(The input parameters must be the following values) :
- EXTI_LINE0
- EXTI_LINE1
- EXTI_LINE2
- EXTI_LINE3
- EXTI_LINE4
- EXTI_LINE5
- EXTI_LINE6
- EXTI_LINE7
- EXTI_LINE8
- EXTI_LINE9
- EXTI_LINE10
- EXTI_LINE11
- EXTI_LINE12
- EXTI_LINE13
- EXTI_LINE14
- EXTI_LINE15
- EXTI_LINE16
- EXTI_LINE17
- EXTI_LINE18
- EXTI_LINE19
- EXTI_LINE20
- EXTI_LINE21
- EXTI_LINE22
- EXTI_LINE23
- EXTI_LINE24
return SET or RESET
void EXTI_ClrStatusFlag(uint32_t EXTI_Line)Clear EXTI line flag status.
name EXTI_ClrStatusFlag.
fun Clear EXTI line flag status.
param EXTI_Line :
- EXTI_LINE0
- EXTI_LINE1
- EXTI_LINE2
- EXTI_LINE3
- EXTI_LINE4
- EXTI_LINE5
- EXTI_LINE6
- EXTI_LINE7
- EXTI_LINE8
- EXTI_LINE9
- EXTI_LINE10
- EXTI_LINE11
- EXTI_LINE12
- EXTI_LINE13
- EXTI_LINE14
- EXTI_LINE15
- EXTI_LINE16
- EXTI_LINE17
- EXTI_LINE18
- EXTI_LINE19
- EXTI_LINE20
- EXTI_LINE21
- EXTI_LINE22
- EXTI_LINE23
- EXTI_LINE24
return none
INTStatus EXTI_GetITStatus(uint32_t EXTI_Line)GET EXTI line interrupt status.
name EXTI_GetITStatus.
fun GET EXTI line interrupt status.
param exti_line :
- EXTI_LINE0
- EXTI_LINE1
- EXTI_LINE2
- EXTI_LINE3
- EXTI_LINE4
- EXTI_LINE5
- EXTI_LINE6
- EXTI_LINE7
- EXTI_LINE8
- EXTI_LINE9
- EXTI_LINE10
- EXTI_LINE11
- EXTI_LINE12
- EXTI_LINE13
- EXTI_LINE14
- EXTI_LINE15
- EXTI_LINE16
- EXTI_LINE17
- EXTI_LINE18
- EXTI_LINE19
- EXTI_LINE20
- EXTI_LINE21
- EXTI_LINE22
- EXTI_LINE23
- EXTI_LINE24
return SET or RESET
void EXTI_ClrITPendBit(uint32_t EXTI_Line)Clear EXTI line interrupt pend bit.
name EXTI_ClrITPendBit.
fun Clear EXTI line interrupt pend bit.
param exti_line :
- EXTI_LINE0
- EXTI_LINE1
- EXTI_LINE2
- EXTI_LINE3
- EXTI_LINE4
- EXTI_LINE5
- EXTI_LINE6
- EXTI_LINE7
- EXTI_LINE8
- EXTI_LINE9
- EXTI_LINE10
- EXTI_LINE11
- EXTI_LINE12
- EXTI_LINE13
- EXTI_LINE14
- EXTI_LINE15
- EXTI_LINE16
- EXTI_LINE17
- EXTI_LINE18
- EXTI_LINE19
- EXTI_LINE20
- EXTI_LINE21
- EXTI_LINE22
- EXTI_LINE23
- EXTI_LINE24
return none
void EXTI_RTCTimeStampSel(uint32_t EXTI_TSSEL_Line)Select the input of TimeStamp event.
name EXTI_RTCTimeStampSel.
fun Select the input of TimeStamp event.
param EXTI_TSSEL_Line :
- EXTI_TSSEL_LINE0
- EXTI_TSSEL_LINE1
- EXTI_TSSEL_LINE2
- EXTI_TSSEL_LINE3
- EXTI_TSSEL_LINE4
- EXTI_TSSEL_LINE5
- EXTI_TSSEL_LINE6
- EXTI_TSSEL_LINE7
- EXTI_TSSEL_LINE8
- EXTI_TSSEL_LINE9
- EXTI_TSSEL_LINE10
- EXTI_TSSEL_LINE11
- EXTI_TSSEL_LINE12
- EXTI_TSSEL_LINE13
- EXTI_TSSEL_LINE14
- EXTI_TSSEL_LINE15
return none
5.11.3 Demo descriptions
This section covers the single EXTI example: KeyInterrupt uses one external interrupt line to rotate its input source between two key pins, and reports the current source through an LED and the UART.
5.11.3.1 KeyInterrupt Key external interrupt
Example directory: projects/n32h49x_EVAL/examples/EXTI/KeyInterrupt/
Initialize the log UART, two LEDs, and two keys→Configure external interrupt 0 for falling-edge triggering and enable its interrupt vector→A falling edge on PC13 or PA15 enters the handler→In the handler, turn off the current LED and switch the interrupt input source to the other key→The main loop blinks the LED that matches the current input source→The UART prints the current input source, cycling alternately
| Item | Source analysis |
|---|---|
| Function | Demonstrates the GPIO external interrupt with EXTI0: by default the falling edge of KEY1 (PC13) triggers the EXTI0 interrupt; each entry into the handler switches the EXTI0 input source between KEY1 and KEY2, the UART prints the current source, and the blinking LED follows the source. |
| Source files | src/main.c: main, the LED and key LED_Init and KEY_Init, and EXTI0_Init;src/n32h49x_it.c: the EXTI0_IRQHandler interrupt handler;inc/main.h: the LED and key port, pin, and clock macros and the function declarations;readme.txt: function, environment, and usage;MDK-ARM/ and EWARM/: Keil and IAR projects. |
| Key configuration | LED1 is PA3 and LED2 is PB3, both push-pull outputs; KEY1 is PC13 and KEY2 is PA15, both inputs with pull-up; EXTI0 uses EXTI_Mode_Interrupt and EXTI_Trigger_Falling;the EXTI0 input source is switched between PC13 and PA15 by GPIO_ConfigEXTILine. The system clock is HSI+PLL at 240 MHz. |
| Program and data path | main calls log_init, prints EXTI key interrupt demo!, initializes the two LEDs and two keys, then calls EXTI0_Init to bind the EXTI0 input source to KEY1;in the loop, when exti_int is set it prints Current EXTI0 input source is:%s and blinks the LED selected by key_cnt at an interval of SystemCoreClock/8. |
| Main APIs | EXTI_InitStruct, EXTI_InitPeripheral, GPIO_ConfigEXTILine, EXTI_GetStatusFlag, EXTI_ClrStatusFlag |
| Verification | After reset the UART prints EXTI key interrupt demo!;pressing KEY1 triggers the EXTI0 interrupt by default, after which the source switches to KEY2 and only KEY2 can trigger again; after each trigger the blinking LED switches between LED1 and LED2, and the UART reports the current source. |
| Use note | The handler first reads EXTI_GetStatusFlag and then clears the pending bit with EXTI_ClrStatusFlag;after switching the source the previous pin no longer triggers, and GPIO_ConfigEXTILine must be called again to use the new pin.Toolchains are KEIL MDK-ARM V5.34 and IAR EWARM 8.50.1. |
Core-code walkthrough and porting
The example uses one interrupt handler to rotate the EXTI0 input source between two key pins and lets an LED follow the current source.
Data path: falling edge of KEY1 (PC13) or KEY2 (PA15) → GPIO_ConfigEXTILine selects the EXTI0 input source → EXTI_InitPeripheral enables the EXTI0 falling-edge interrupt → the EXTI0_IRQHandler runs → EXTI_GetStatusFlag checks and EXTI_ClrStatusFlag clears → the source is switched to the next key → the main loop blinks the LED selected by key_cnt and prints the source
1. Macros and arrays define the LEDs and keys. The pins and ports are defined in inc/main.h, and the example accesses them through LEDx_PORT, LEDx_PIN, KEYx_PORT, and KEYx_PIN; the key port and pin sources are also registered in arrays so the handler can switch between them.
/* User LED define */
#define LED1_PORT GPIOA
#define LED1_PIN GPIO_PIN_3
#define LED1_CLOCK RCC_AHB_PERIPHEN_GPIOA
#define LED2_PORT GPIOB
#define LED2_PIN GPIO_PIN_3
#define LED2_CLOCK RCC_AHB_PERIPHEN_GPIOB
/* User KEY define */
#define KEY1_PORT GPIOC
#define KEY1_PIN GPIO_PIN_13
#define KEY1_CLOCK RCC_AHB_PERIPHEN_GPIOC
#define KEY2_PORT GPIOA
#define KEY2_PIN GPIO_PIN_15
#define KEY2_CLOCK RCC_AHB_PERIPHEN_GPIOA
When porting to another board, only this macro set and the KeyPortSrc and KeyPinSrc arrays in src/main.c need changes; the example logic stays the same.
2. Configure EXTI0 as a falling-edge interrupt and bind the input source. EXTI0_Init fills EXTI_InitType and enables the EXTI0 falling-edge interrupt, configures the EXTI0 channel in the NVIC, and finally maps the GPIO pin to EXTI0.
EXTI_Struct.EXTI_Line = EXTI_LINE0;
EXTI_Struct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_Struct.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Struct.EXTI_LineCmd = ENABLE;
EXTI_InitPeripheral(&EXTI_Struct);
NVIC_Struct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_Struct.NVIC_IRQChannelSubPriority = NVIC_SUB_PRIORITY_0;
NVIC_Struct.NVIC_IRQChannelPreemptionPriority = NVIC_PRE_PRIORITY_0;
NVIC_Struct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_Struct);
GPIO_ConfigEXTILine(EXTI_LINE_SOURCE0,KeyPortSrc[0],KeyPinSrc[0]);
EXTI_Trigger_Falling makes the line trigger on falling edges only; GPIO_ConfigEXTILine connects the selected port and pin sources to EXTI0, matching the GPIO mapping of the EXTI line selection register in the user manual.
3. The handler switches the input source. EXTI0_IRQHandler checks the EXTI0 status, turns off the current LED, cycles key_cnt between 0 and 1, remaps the input source, and finally clears the pending bit.
if(EXTI_GetStatusFlag(EXTI_LINE0) == SET)
{
LED_Off(LedPort[key_cnt], LedPin[key_cnt]);
if(key_cnt >= (MAX_LED_KEY_CNT-1))
{
key_cnt = 0;
}
else
{
key_cnt++;
}
GPIO_ConfigEXTILine(EXTI_LINE_SOURCE0,KeyPortSrc[key_cnt],KeyPinSrc[key_cnt]);
exti_int = 1;
}
EXTI_ClrStatusFlag(EXTI_LINE0);
Each interrupt first confirms the source with EXTI_GetStatusFlag and then moves EXTI0 to the next key with GPIO_ConfigEXTILine; the trailing EXTI_ClrStatusFlag clears the pending bit so the handler does not re-enter continuously.
4. The main loop prints and blinks by input source. main checks exti_int, prints the current source and clears the flag when it is set, and otherwise keeps blinking the LED selected by key_cnt.
while (1)
{
if(exti_int != 0)
{
printf("Current EXTI0 input source is:%s\r\n",str[key_cnt]);
exti_int = 0;
}
LED_Blink(LedPort[key_cnt], LedPin[key_cnt]);
Delay(SystemCoreClock/8);
}
The blink rate is set by Delay(SystemCoreClock/8); the str[] array supplies the pin names printed on the UART and matches KeyPortSrc and KeyPinSrc one to one.
Corresponding source files: src/main.c, inc/main.h, src/n32h49x_it.c
5.11.4 Notes and troubleshooting
| Scenario | Check & action | Source |
|---|---|---|
| Interrupt enabling | Before using an EXTI interrupt, enable the matching channel in the NVIC and set the line mask bit in the EXTI interrupt mask register correctly; without either one, an edge does not reach the interrupt handler. |
User manual |
| Clearing the pending bit | After an edge is detected the line pending bit is set and must be cleared by writing 1 to it in the handler; changing the edge polarity of the line also clears the pending bit. |
User manual |
| Event versus interrupt | Event lines are configured through the event mask register and only output a pulse on an event, without setting the pending bit; when only the event is configured and the interrupt is not, the CPU does not enter the handler. |
User manual |
| Edge restriction for specific peripherals | For the PVD, USB FS, USB HS, LPTIM1, and LPTIM2 interrupts, the associated EXTI line can only be configured for rising-edge triggering. | User manual |
| GPIO line mapping and the AFIO clock | The AFIO clock must be enabled before a GPIO pin is mapped to an EXTI line through AFIO_EXTI_CFGy;one EXTI line can be mapped to only one GPIO pin at a time. |
User manual |