使用外部中断的方式检测按钮。
为中断分配GPIO管脚
我的野火开发板,PC13已经接有按钮,将PC13设置为外部中断GPIO_EXTI13, 模式为上升沿检测,板子上已有下拉电阻,所以选择无上拉无下拉。
设置中断优先级并使能中断
EXTI13,对应中断向量是 EXTI15_10_IRQn,所以在设置优先级的时候选择EXTI line[15:10] interrupts。
生成中断代码
黄齿轮,生成代码:
打开main.c,在MX_GPIO_Init()的函数定义中可以看到定义中断的代码:
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 0); /*优先级*/
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); /*使能中断请求*/
解释:
HAL_NVIC_EnableIRQ()
是 HAL 库提供的中断使能函数,用于向嵌套向量中断控制器(NVIC)发送指令,允许指定的中断源产生中断。EXTI15_10_IRQn
是中断源的标识,代表外部中断线 10 到 15 共用的中断通道。在 STM32 中,外部中断线 10-15 共享一个中断服务程序,调用该函数后,这几个中断线触发时将能够产生中断并执行对应的处理程序。编写中断程序
打开文件stm32f1xx_it.c
可以看到中断服务函数EXTI15_10_IRQHandler(),它用于处理外部中断线(EXTI)10 到 15 的中断请求。当 EXTI10 至 EXTI15 中的任何一条中断线触发中断时,系统会自动跳转到执行该函数。
可以看到,在EXTI15_10_IRQHandler()函数中,调用了HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13),按住ctrl键点击这个调用,跳转到它的定义,程序自动打开了stm32f1xx_hal_gpio.c:
HAL_GPIO_EXTI_IRQHandler()的两行代码,含义为:
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); /*清楚中断标志*/
HAL_GPIO_EXTI_Callback(GPIO_Pin); /*回调中断函数*/
然后,按住ctrl点击HAL_GPIO_EXTI_Callback,跳转到它的定义:
可以看到,这是一个弱定义函数,需要重写同名函数来覆盖它。总结以上的过程,就是:
触发外部中断EXTI13-->调用共用的中断服务函数EXTI15_10_IRQHandler()-->调用服务函数HAL_GPIO_EXTI_IRQHandler()-->调用中断回调函数HAL_GPIO_EXTI_Callback()。
中断回调函数HAL_GPIO_EXTI_Callback()一般定义在stm32f1xx_it.c里面,需要自己写代码:
/* USER CODE BEGIN 1 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
HAL_Delay(10); /* 延时消抖 */
switch(GPIO_Pin)
{
case GPIO_PIN_13 :
if(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) == GPIO_PIN_SET)/* 按下按钮 */
{
HAL_GPIO_TogglePin(GPIOA, LED_G_Pin); /* LED翻转 */
break;
}
}
}
/* USER CODE END 1 */
第一次创建了这个外部中断回调函数,以后直接打开stm32f1xx_it.c文件在这里修改就好了。这个外部中断回调函数是共用的,如果需要定义其他的外部中断,在下面添加case即可。