STM32F030 GPIO中断
STM32F030 GPIO interrupt
试图在 A3 上获得中断,将 cpu 从 rx 字符上的睡眠中唤醒,但它没有触发。
定义 GPIO 引脚将触发哪个中断的是什么?在参考手册里找不到
static void EXTI0_1_IRQHandler_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOA clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = GPIO_PIN_3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable and set EXTI line 0 Interrupt to the lowest priority */
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
}
第 11 章中断和事件,第 11.1.3 节中断和异常向量中(简要地)描述了中断函数。
所以,中断号是EXTI2_3_IRQn
,你应该定义EXTI2_3_IRQHandler()
来调用HAL_GPIO_EXTI_IRQHandler()
。
一些背景
在发生中断请求时调用回调函数涉及几个步骤。
每个中断请求都有一个分配给它的中断号,参见上面table中的位置条目。数字由硬件定义,符号名称分配在机器头的某处。
typedef enum {
[...]
EXTI0_1_IRQn = 5, /*!< EXTI Line 0 and 1 Interrupt */
EXTI2_3_IRQn = 6, /*!< EXTI Line 2 and 3 Interrupt */
[...]
} IRQn_Type;
vector中有对应的函数指针table,里面应该是handler函数的地址。这个向量 table 在启动模块中填写,称为 startup_stm32f030x8.s
或类似的东西,链接器配置文件确保 table 在编程时以正确的物理地址结束闪光.
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word 0
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word WWDG_IRQHandler /* Window WatchDog */
.word 0 /* Reserved */
.word RTC_IRQHandler /* RTC through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */
.word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */
...
条目是固定顺序的,因为硬件只关心数字地址。每当 EXTI2
或 EXTI3
事件发生,并且启用 IRQ6
时,它会跳转到 0x00000058
处的地址。上面的 table 确保 EXTI2_3_IRQHandler()
的地址进入 0x00000058
处的向量 table。
在启动模块中进一步挖掘,我们发现了这个
.weak EXTI0_1_IRQHandler
.thumb_set EXTI0_1_IRQHandler,Default_Handler
.weak EXTI2_3_IRQHandler
.thumb_set EXTI2_3_IRQHandler,Default_Handler
还有这个
Default_Handler:
Infinite_Loop:
b Infinite_Loop
这意味着如果 EXTI0_1_IRQHandler()
或 EXTI2_3_IRQHandler()
没有定义,那么它们将调用一个无限循环,这对调试很有用,但除此之外别无他法。为了实际使用它,您必须在您的程序中覆盖该符号。如果您查看 GPIO_EXTI
示例,它有这个处理程序
void EXTI0_1_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(USER_BUTTON_PIN);
}
在stm32f0xx_it.c
中定义,当EXTI0
中断发生时调用HAL_GPIO_EXTI_IRQHandler()
。如果你想对EXTI3
采取行动,那么你应该有一个类似的功能
void EXTI2_3_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(3);
}
打电话给HAL_GPIO_EXTI_IRQHandler()
.
试图在 A3 上获得中断,将 cpu 从 rx 字符上的睡眠中唤醒,但它没有触发。
定义 GPIO 引脚将触发哪个中断的是什么?在参考手册里找不到
static void EXTI0_1_IRQHandler_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOA clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = GPIO_PIN_3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable and set EXTI line 0 Interrupt to the lowest priority */
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
}
第 11 章中断和事件,第 11.1.3 节中断和异常向量中(简要地)描述了中断函数。
所以,中断号是EXTI2_3_IRQn
,你应该定义EXTI2_3_IRQHandler()
来调用HAL_GPIO_EXTI_IRQHandler()
。
一些背景
在发生中断请求时调用回调函数涉及几个步骤。
每个中断请求都有一个分配给它的中断号,参见上面table中的位置条目。数字由硬件定义,符号名称分配在机器头的某处。
typedef enum {
[...]
EXTI0_1_IRQn = 5, /*!< EXTI Line 0 and 1 Interrupt */
EXTI2_3_IRQn = 6, /*!< EXTI Line 2 and 3 Interrupt */
[...]
} IRQn_Type;
vector中有对应的函数指针table,里面应该是handler函数的地址。这个向量 table 在启动模块中填写,称为 startup_stm32f030x8.s
或类似的东西,链接器配置文件确保 table 在编程时以正确的物理地址结束闪光.
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word 0
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word WWDG_IRQHandler /* Window WatchDog */
.word 0 /* Reserved */
.word RTC_IRQHandler /* RTC through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */
.word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */
...
条目是固定顺序的,因为硬件只关心数字地址。每当 EXTI2
或 EXTI3
事件发生,并且启用 IRQ6
时,它会跳转到 0x00000058
处的地址。上面的 table 确保 EXTI2_3_IRQHandler()
的地址进入 0x00000058
处的向量 table。
在启动模块中进一步挖掘,我们发现了这个
.weak EXTI0_1_IRQHandler
.thumb_set EXTI0_1_IRQHandler,Default_Handler
.weak EXTI2_3_IRQHandler
.thumb_set EXTI2_3_IRQHandler,Default_Handler
还有这个
Default_Handler:
Infinite_Loop:
b Infinite_Loop
这意味着如果 EXTI0_1_IRQHandler()
或 EXTI2_3_IRQHandler()
没有定义,那么它们将调用一个无限循环,这对调试很有用,但除此之外别无他法。为了实际使用它,您必须在您的程序中覆盖该符号。如果您查看 GPIO_EXTI
示例,它有这个处理程序
void EXTI0_1_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(USER_BUTTON_PIN);
}
在stm32f0xx_it.c
中定义,当EXTI0
中断发生时调用HAL_GPIO_EXTI_IRQHandler()
。如果你想对EXTI3
采取行动,那么你应该有一个类似的功能
void EXTI2_3_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(3);
}
打电话给HAL_GPIO_EXTI_IRQHandler()
.