你还在使用HAL_Delay吗
HAL_Delay 是STM32HAL库提供的毫秒级延时函数, 相信所有STM32开发人员都对它非常的熟悉, 那么你曾经或者是现在是否还在频繁的使用HAL_Delay呢? 现在的你是否还记得自己点亮的第一颗Led灯呢?看下面代码:void Led_Flicker(void) { Led_On(); HAL_Delay(500); Led_Off(); HAL_Delay(500); return; }这段代码非常简单,就是实现一个Led灯的闪烁效果,频率是500ms。当你满心欢喜的把它放在while(1){}中,下载到板子上面, 看着不断闪烁的小灯泡激动不已, 这时的你可能不会去深究, 这个HAL_Delay实现了精确的延时, 但随之会带来那些问题呢。 刚开始只是简单的一个小实验, 并不会影响很大, 可是如果像下面这样呢?while(1) { Led_Flicker(); Key_Scan(); }循环中除了执行Led闪烁的代码外, 还有按键扫描的代码, 这时问题就来了, HAL_Delay是阻塞延时, 不到达设定的时间是不会往下执行的, 也就是说, 在Led闪烁的时候, 下面的按键扫描是在等待执行的, 不能够及时的检测到按键状态。最终会造成系统响应不及时。那么怎么解决这个问题呢, 下面给出其中一种解决方法:// 枚举Led的状态 typedef enum { LED_ON, // 亮 LED_OFF, // 灭 LED_KEEP_ON, // 保持亮 LED_KEEP_OFF // 保持灭 }LedState; void Led_Flicker(void) { static LedState state LED_ON; // 初始化Led的状态 static uint32_t start_time 0; // 记录开始时间 uint32_t now HAL_GetTick(); // 获取当前时间 switch(state){ case LED_ON: Led_On(); start_time now; // 记录亮灯开始的时间 state LED_KEEP_ON; // 切换状态 break; case LED_KEEP_ON: if(now - start_time 500){ // 查询亮灯的时间 state LED_OFF; } break; case LED_OFF: Led_Off(); start_time now; state LED_KEEP_OFF; break; case LED_KEEP_OFF: if(now - start_time 500){ state LED_ON; } break; } }HAL_GetTick() 返回的是当前系统时间uwTick,可以把它理解成一个一直在变化的时间戳, 它是系统启动后, 由SysTick中断回调不断更新的一个值,默认是1ms,每次会把uwTick1。没错, 这就是传说中的状态机, 通过状态机不断的查询时间来实现延时的效果, 实现非阻塞, 状态机是实现非阻塞的核心, 今天通过这个例子, 体现了状态机在延时方面的应用。现在通过状态机实现延时, 查询到延时时间没有到达, 就会立即返回, 不会阻塞整个系统的运行了 也不会占用有限的硬件资源, 状态机的应用非常的广泛, 实现延时只是其中的一种。