Chr*_*oph 10 interrupt stm32 interrupt-handling
我已经购买了STM32F411核板,现在我正在尝试了解HAL的各种零碎.从外部中断开始似乎是一个好主意,因为电路板有一个连接到PC13的按钮.所以我设置了一个简单的切换频率闪烁.下面的代码有点简化:
#define LED_PIN GPIO_PIN_5
#define BTN_PIN GPIO_PIN_13
static uint32_t blink_period = 250;
int main(void)
{
HAL_Init();
SystemClock_Config();
__GPIOA_CLK_ENABLE();
GPIO_InitTypeDef pinConfig;
pinConfig.Pin = (LED_PIN);
pinConfig.Pull = GPIO_NOPULL;
pinConfig.Mode = GPIO_MODE_OUTPUT_PP;
pinConfig.Speed = GPIO_SPEED_FAST;
HAL_GPIO_Init(GPIOA, &pinConfig);
__GPIOC_CLK_ENABLE();
pinConfig.Pin = (BTN_PIN);
pinConfig.Pull = GPIO_NOPULL;
pinConfig.Mode = GPIO_MODE_IT_FALLING;
pinConfig.Speed = GPIO_SPEED_LOW;
HAL_GPIO_Init(GPIOC, &pinConfig);
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0x0F, 0x00);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
while (1)
{
HAL_GPIO_TogglePin(GPIOA, LED_PIN);
HAL_Delay(blink_period);
}
}
void EXTI15_10_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(BTN_PIN);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == BTN_PIN)
{
if (blink_period == 500)
{
blink_period = 250;
}
else
{
blink_period = 500;
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我按下按钮时,会产生一个中断,闪烁的频率从1到2 Hz变化(反之亦然).这是按预期工作的,但为什么呢?我忘了清除挂起的中断标志,所以应该一遍又一遍地调用ISR.数据表清楚地说明了这一点
当外部中断线上出现所选边沿时,会产生中断请求.还设置对应于中断线的待定位.通过在挂起的寄存器中写入'1'来重置该请求.
进一步阅读可以发现事件有点不同:
当在事件行上出现所选边缘时,将生成事件脉冲.未设置与事件行对应的挂起位.
但是,我没有将按钮引脚模式设置为任何GPIO_MODE_EVT_...模式,所以我没有使用事件机制(说实话我还不知道那是什么 - 我只是认为我没有使用它任何提示都是受欢迎的).
所以在某个地方我应该打电话void HAL_NVIC_ClearPendingIRQ (IRQn_Type IRQn),不应该吗?似乎不需要通过软件清除标志,因为每个下降沿不会多次调用ISR.我添加了一个断点HAL_GPIO_EXTI_Callback来验证这一点.
正如评论中所提到的,标志清除代码是ST的GPIO中断处理程序的实现:
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
Run Code Online (Sandbox Code Playgroud)
这个处理程序需要由实际的ISR(在我的代码中完成)调用,并清除对应于GPIO_Pin参数的pending标志.因此,我必须编写一个ISR,它会对哪些标志进行排序,然后HAL_GPIO_EXTI_IRQHandler为每个标志调用HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin),然后再将该引脚作为参数调用my .对于每个外部中断,引脚号将被检查约3次(在ISR中,在处理程序中和回调中)!
如果这是解决方案,我想回到我的问题.
小智 7
您无需拨打电话,HAL_NVIC_ClearPendingIRQ (IRQn_Type IRQn)因为NVIC中的待处理位将在进入时自动清除HAL_GPIO_EXTI_IRQHandler.
该HAL_GPIO_EXTI_IRQHandler()实现清除了外设中的挂起位,而不是NVIC中的挂起位.如果它没有通过调用清除挂起位__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin),那么将一次又一次地调用该处理程序.关键是您必须区分外设中的中断挂起位和NVIC中的挂起位.