/*出处:【keysking的stm32教程】 第6集 狂飙STM32中断_哔哩哔哩_bilibili*/
今天先是改了个一直以来的认知错误,跑马灯不用电平反转需要两次delay,不然第二次翻转就出现问题了。。。算是白学了,哈哈哈哈。
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
HAL_Delay(500);
为了及时处理高优先级事件stm32引入了中断机制,这里我们做一个实验,按下按键之后让PC13小灯熄灭,平时保持常亮。
①PC13设置普通输出(我这个灯IO口输出低电平点亮)
②按键对应的PB14设置GPIO_EXIT
③选择合适的中断触发模式
从上往下依次是:上升沿触发中断、下降沿触发中断、电平上升下降都触发中断;
我手上这块板子按下按键PB14捕获低电平,所以选择下降沿触发。
④设置NVIC中断控制器,勾选开启中断向量EXIT[15:10]
⑤再次生成代码打开ide发现CubeMX帮我们自动生成了这个中断处理函数
增加翻转PC13电平的代码
基本功能实现了,但是还没按键消抖,从原理图上看我这个板子根本没滤波电容。直接在中断里面使用阻塞式延时是个危险动作!所以这里调整一下滴答计时器中断和按键触发中断优先级顺序。
最终代码:
/**
* @brief This function handles EXTI line[15:10] interrupts.
*/
void EXTI15_10_IRQHandler(void)
{
/* USER CODE BEGIN EXTI15_10_IRQn 0 */
HAL_Delay(10);
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14)==GPIO_PIN_RESET)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}
/* USER CODE END EXTI15_10_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14);
/* USER CODE BEGIN EXTI15_10_IRQn 1 */
/* USER CODE END EXTI15_10_IRQn 1 */
}
深入讨论中断机制:
①从单片机引脚进入的高低电平信号首先由输入驱动器处理。
②经过输入驱动器处理过的高低电平信号会进入到边缘检测电路,当它捕获到我们设置的边沿信号后,就会向请求挂起寄存器输出一个高电平信号,请求挂起寄存器对应的位置会置1。
③只要我们提前开启了对应中断,请求挂起寄存器的信号就可以进入到NVIC(嵌套向量中断控制器),NVIC会找到此中断线对应的中断向量(可以理解为中断向量中存放着指针,这些指针中存放着处理事件函数的地址),并且执行相应的中断处理函数,中断处理函数会清除请求挂起寄存器(CubeMX自动处理了这个部分),以防止中断重复触发。
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
HAL_GPIO_EXTI_Callback(GPIO_Pin);
}
}
④中断优先级规定多中断的执行次序,中断优先级又分为抢占优先级与响应优先级,优先级的数字越小则代表优先级越高。Priority Group选项可以选定这两者的位数。
两中断同时发生时,先比较抢占优先级;若抢占优先级相同,在比较响应优先级;
某中断正在执行中,另一中断突然发生,则只比较两者抢占优先级。一般情况下建议使用抢占优先级即可。