目标:点击一下按键(KEY2),LED1灯亮。
概念解析:抢占优先级与响应优先级的概念分析
抢占优先级(Preemption Priority):抢占优先级高的先响应,低的后相应。
响应优先级(Sub Priority):当抢占优先级相同时,响应优先级高的先响应。
另:若抢占优先级与响应优先级相同,则看中断发生的先后顺序。
步骤
第一步
先通过CubeMX配置SYS、RCC、时钟树。
第二步
重写中断服务函数。
//重写中断服务函数,如果检测到EXTI1中断请求,则进入此函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
//一根中断线上有多个中断源,判断中断源是否来自PA4
if(GPIO_Pin == GPIO_PIN_1)
{
//如果检测到PA1被拉低
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET)
{
//则点亮LED1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
}
else
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
}
}
小结
此时将程序写入单片机,摁下按键二,即可点亮LED1,但LED1不会灭。
增加任务
当LED1亮灯3s后,LED1熄灭。
步骤三
增加延时函数,其代码如下:
//重写中断服务函数,如果检测到EXTI1中断请求,则进入此函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
//一根中断线上有多个中断源,判断中断源是否来自PA4
if(GPIO_Pin == GPIO_PIN_1)
{
//如果检测到PA1被拉低
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == GPIO_PIN_RESET)
{
//则点亮LED1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_Delay(3000);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
}
else
{
//否则关闭LED1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);
}
}
}
BUG
将程序写入单片机,摁下KEY2,LED1只亮不灭。
原因
程序初始化时默认将滴答定时器的中断优先级设置为最低,其他中断源很容易打断它,导致卡死。
解决办法
1. 在main函数中使用以下函数提高滴答定时器的中断优先级(提升至0)。
HAL_NVIC_SetPriority(SysTick_IRQn,0,0);
2. 在CubeMX中修改KEY2的抢占优先级。