软件定时器
ESP8266软件定时器的描述如下:
由上面的描述可以知道,使用软件定时器有以下步骤:
1 调用os_timer_disarm,先取消定时器定时;
在初始化定时器前,要先定义 os_timer_t 变量,取消定时器定时;
2 注册定时器回调函数;
3 开启定时器,如果想使用 毫秒级 定时器,可以使用如下 API;
接下来,编写软件定时器的代码,其实非常简单:
1 初始化函数:
// 初始化软件定时器
void ICACHE_FLASH_ATTR
BSP_OS_Timer_Init(uint32_t ms, bool repeat_flag)
{
// 关闭定时器
// 参数一:要关闭的定时器
//--------------------------------------------------------
os_timer_disarm(&OS_Timer_1); // 关闭软件定时器
// 设置定时器
// 参数一:要设置的定时器;参数二:回调函数(需类型转换);参数三:回调函数的参数
//【注:os_timer_setfn必须在软件定时器未使能的情况下调用】
//------------------------------------------------------------------------------------------
os_timer_setfn(&OS_Timer_1,(os_timer_func_t *)OS_Timer_1_CallBack, NULL); // 设置回调函数
// 使能(启动)ms定时器
// 参数一:要使能的定时器;参数二:定时时间(单位:ms);参数三:1=重复/0=只一次
os_timer_arm(&OS_Timer_1, ms, repeat_flag); // 设置定时器参数并使能定时器
// 【如未调用system_timer_reinit,可支持范围:[5ms ~ 6,870,947ms]】
// 【如果调用system_timer_reinit,可支持范围:[100ms ~ 428,496 ms]】
}
2 定时器回调函数:
// 定时器回调函数
void ICACHE_FLASH_ATTR OS_Timer_1_CallBack(void)
{
F_LED = !F_LED;
GPIO_OUTPUT_SET(GPIO_ID_PIN(4), F_LED); // 翻转LED
os_printf("\r\n----OS_Timer_1_CallBack----\r\n"); // 进入回调函数标志
}
然后在主函数中进行调用(必须注释掉while死循环,否则无法执行):
user_init(void)
{
uart_init(115200,115200); // 初始化串口波特率
os_delay_us(10000); // 等待串口稳定
os_printf("\r\n=================================================\r\n");
os_printf("\t Project:\t%s\r\n", ProjectName);
os_printf("\t SDK version:\t%s", system_get_sdk_version());
os_printf("\r\n=================================================\r\n");
BSP_LED_Init(); // 初始化 LED
BSP_OS_Timer_Init(500, 1); // 初始化软件定时器
//while(1)
//{
// system_soft_wdt_feed(); // 喂狗,防止复位
//}
}
程序的执行结果如下,LED每0.5秒闪烁一次,串口正确打印调试信息:
如果还是在while中执行死循环+喂狗操作,程序不会被正确执行。因为软件定时器是在任务中执行的,而死循环会一直占用CPU,没有多余的空闲时间执行定时器的计时任务。所以,软件定时器,并不能保证精确执行。
硬件定时器
ESP8266的硬件定时器,如下图所示:
设置硬件定时器的步骤如下所示:
0 添加 driver_lib / driver / hw_timer.c 文件到 app / driver / 路径下;
1 调用 hw_timer_init 函数,初始化定时器;
2 设置定时器中断回调函数;
3 使能硬件定时器;
接下来是代码部分:
1 配置硬件定时器(注释掉死循环);
2 硬件定时器中断回调函数;
下载执行,LED每0.5秒闪烁,串口正确打印调试信息如下所示;
接下来,我们创建while 死循环,并不断喂狗。在这种操作下,按之前提到的,软件定时器是无法工作的,而硬件定时器依然能够正常工作,串口信息如下所示:
主函数:
user_init(void)
{
uart_init(115200,115200); // 初始化串口波特率
os_delay_us(10000); // 等待串口稳定
os_printf("\r\n=================================================\r\n");
os_printf("\t Project:\t%s\r\n", ProjectName);
os_printf("\t SDK version:\t%s", system_get_sdk_version());
os_printf("\r\n=================================================\r\n");
BSP_LED_Init(); // 初始化 LED
// 初始化硬件定时器,使用FRC1作为中断源
hw_timer_init(0, 1); // 【参数1:中断源】【参数2:是否重复】
hw_timer_set_func(HW_Timer_CallBack); // 注册定时器回调函数
hw_timer_arm(500000); // 使能定时器,定时时间为500 000us = 500ms
while(1)
{
system_soft_wdt_feed(); // 喂狗,防止复位
}
}
回调函数:
// 定时器回调函数
void HW_Timer_CallBack(void)
{
F_LED = !F_LED;
GPIO_OUTPUT_SET(GPIO_ID_PIN(4), F_LED); // 翻转LED
os_printf("\r\n----HW_Timer_CallBack----\r\n"); // 进入回调函数标志
os_printf("\r\n----Test dead loop----\r\n"); // 测试死循环
}
测试结果:LED每0.5秒闪烁,串口正确打印调试信息。