使用HAL库在stm32中实现中断控制流水灯
HAL库中断控制LED流水灯
一、实现流水灯
1、CubeMX设置
设置PA4,PB8,PC14模式为推挽输出
2、代码思路
代码思路:主循环中三个IO口依次每一个引脚置低电平(LED另一端引脚接面包板负极),相应的另外两个IO口置高电平。
主函数
int main(void)
{
SystemClock_Config();//系统时钟初始化
MX_GPIO_Init();//gpio初始化
while (1)
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);//PA4亮灯
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//PB9熄灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC15熄灯
HAL_Delay(1000);//延时1s
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);//PB9亮灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC15熄灯
HAL_Delay(1000);//延时1s
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//PB9熄灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);//PC15亮灯
HAL_Delay(1000);//延时1s
}
}
HAL基本流水灯
3、最终效果
二、使用外部中断,按键控制流水灯
1、CubeMX设置
PB1端口设置默认高电平,上升沿触发
PA1,PB8,PC14端口设置为推挽输出
2、尝试用HAL_Delay函数失败
发现在外部中断中使用HAL_Delay函数会卡死,只能触发一次中断,然后后面无法触发
原因
查看HAL_Delay函数
/** * @brief This function provides minimum delay (in milliseconds) based * on variable incremented. * @note In the default implementation , SysTick timer is the source of time base. * It is used to generate interrupts at regular time intervals where uwTick * is incremented. * @note This function is declared as __weak to be overwritten in case of other * implementations in user file. * @param Delay specifies the delay time length, in milliseconds. * @retval None */
__weak void HAL_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
while((HAL_GetTick() - tickstart) < wait)
{
}
}
注意事项说到,计时器的时基来自SysTick定时器,且在固定时间间隔产生(interrupt)中断
系统滴答定时器(System tick timer)的优先级默认为最低,外部中断处理的优先级比系统滴答定时器优先级高,具体流程如下
按键触发中断处理程序 –> HAL_Delay() –> 系统滴答定时器(未执行)–>外部中断处理 –> HAL_Delay() (卡死)
所以如果HAL_Delay()需要被外部中断处理程序调用,系统滴答定时器必须比外部中断要高,否则调用者的中断处理程序将被阻塞。
解决方法
(1)通过while循环延时代替HAL_Delay函数
(2)通过更改中断和系统滴答定时器的优先级
设置中断优先级,更改系统滴答定时器和外部中断的优先级,将系统滴答定时器的优先级设置的比外部中断要高
3、用while循环延时代码实现
中断
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Prevent unused argument(s) compilation warning */
//HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4); //翻转电平
if(flag)flag=0;
else flag=1;
uint16_t t=(uint16_t)312700;
while(t--);
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
}
主函数
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1)
{ if(flag){
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);//PA4亮灯
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//PB9熄灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC15熄灯
HAL_Delay(100);//延时1s
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET);//PB9亮灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC15熄灯
HAL_Delay(100);//延时1s
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//PB9熄灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);//PC15亮灯
HAL_Delay(100);//延时1s
}
else{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);//PA4熄灯
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET);//PB9熄灯
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);//PC15熄灯
}
}
/* USER CODE END 3 */
}
4、最终效果
HAL按键中断流水灯
三、软件仿真逻辑分析仪功能观察串口输出波形
相差两秒,main函数中设置的也是两秒一亮,比较精准
https://blog.csdn.net/weixin_56102526/article/details/120877293
https://blog.csdn.net/weixin_46129506/article/details/120780184
https://blog.csdn.net/qq_44918248/article/details/114579472
https://blog.csdn.net/qq_46380537/article/details/121510324
https://blog.csdn.net/Dir_x/article/details/128899621
作者:Xkccsdn147