MCU不用定时器实现非阻塞延时
简介
我们在日常MCU开发中经常会遇到需要按照一定时间间隔轮询的任务比如:Work灯、心跳包等等,所对应最常见的实现方法就是通过(软/硬)定时器来实现。接下来就给大家推荐一种不使用定时器来实现非阻塞延时轮询任务的一种方法,话不多说直接上代码。
就拿一个在RTOS中Work灯的实现方法来举例子,我们在空闲线程中使用钩子函数一行代码实现让Work灯每隔一秒闪烁一次。
/* 全局变量 */
rt_tick_t timeout = 0;
/* 函数声明 */
static void work_led_init(void);
static void work_led_hook(void);
/* 主函数 */
int main(void)
{
work_led_init();
rt_kprintf("=== [work_led] init success! ===\n");
/* 设置空闲线程回调函数 */
if (rt_thread_idle_sethook(work_led_hook) != RT_EOK)
{
rt_kprintf("=== [set work_led_hook] failed! ===\n");
}else
{
rt_kprintf("=== [set work_led_hook] success! ===\n");
}
while(1)
{
rt_thread_delay(5000);
}
}
/**********************************************************************
* @brief work灯初始化函数
* @author Dev_XH
* @date 2022-10-19
**********************************************************************/
static void work_led_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure = {0};
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_ResetBits(GPIOE,GPIO_Pin_12);
}
/**********************************************************************
* @brief work灯钩子函数
* @author Dev_XH
* @date 2022-10-24
**********************************************************************/
static void work_led_hook(void)
{
static u8 i = 0;
/* 在空闲线程的回调函数里执行work灯闪烁 1S */
rt_tick_t tick = rt_tick_get();
if (tick - timeout >= 1000) // 1S定时
{
timeout = tick;
GPIO_WriteBit(GPIOE, GPIO_Pin_12, (i == 0) ? (i = Bit_SET) : (i = Bit_RESET));
}
}
我的系统计数时间周期是1ms,如上所述我们就可以按照以下结构,实现各种时间段的延时触发任务。
rt_tick_t tick = rt_tick_get();
if (tick - timeout >= ???) // 轮询自定义间隔
{
timeout = tick;
/* To do something */
}