定时器的API

定时器的API都能去官网上查询到解释。

xTimerCreate
xTimerCreateStatic
xTimerIsTimerActive
pvTimerGetTimerID
pcTimerGetName
vTimerSetReloadMode
xTimerStart
xTimerStop
xTimerChangePeriod
xTimerDelete
xTimerReset
xTimerStartFromISR
xTimerStopFromISR
xTimerChangePeriodFromISR
xTimerResetFromISR
pvTimerGetTimerID
vTimerSetTimerID
xTimerGetTimerDaemonTaskHandle
xTimerPendFunctionCall
xTimerPendFunctionCallFromISR
pcTimerGetName
xTimerGetPeriod
xTimerGetExpiryTime

链接: Timer.
定时器的使用就不说了,API都有介绍,提一下注意事项。

定时器注意事项

切不可在定时器回调函数中调用任何将定时器任务挂起的函数,比如vTaskDelay(),vTaskDelayUntil()以及非零延迟的消息队列和信号量相关的函数。将定时器任务挂起,会导致定时器任务负责的相关功能都不能正确执行了。就比如那种获取信号量是阻塞等待,串口的发送是阻塞发送,都可能会造成定时器任务的挂起,一旦挂起,定时器就相当于完了。定时器是由定时器任务来维护的 可以在源码里面找到它的创建。

xReturn = xTaskCreate(prvTimerTask, "Tmr Svc", (uint16_t)256, NULL, ((UBaseType_t)configTIMER_TASK_PRIORITY) | portPRIVILEGE_BIT, NULL);
//prvTimerTask回调
//"Tmr Svc"是名称
//256堆栈大小
//NULL 参数,现在参数为空
//configTIMER_TASK_PRIORITY优先级
//NULL句柄

需要注意

  • 定时器 堆栈大小其实是一个字,不是字节,大小是参数*4
  • 定时器的优先级最好是设置为最高优先级,不会被其他任务打断。
  • 定时器的回调函数里不要被阻塞,因为可能会造成定时器任务的挂起。

我遇到的问题

我建了两个循环定时器

void Init_task()
{

   heartbeat_wchdog = xTimerCreate("watchdog", (TickType_t)1000, (UBaseType_t)pdTRUE, (void *)2, (timer_callback_t)heartbeat_Callback);
   if (heartbeat_wchdog != NULL)
   {
       xTimerStart(heartbeat_wchdog, 0);
   }
   //app_heart_callback
   app_heart = xTimerCreate("app_heart", (TickType_t)8000, (UBaseType_t)pdTRUE, (void *)3, (timer_callback_t)app_heart_callback);
   if (app_heart != NULL)
   {
       xTimerStart(app_heart, 0);
   }
   vTaskDelete(NULL);
}

一个是1s回调一次,一个是8s回调一次,程序运行后watchdog每隔一秒回调一次,到了第八秒,app_heart运行后,定时器就死掉了,其他的任务还在正常运行,就"Tmr Svc"被刮了起来,挂起状态。

最后的原因

找了很久,在我的定时器回调里面,很角落的地方,两个回调都去操作了同一个硬件资源,并且我设置的是阻塞式的操作,一定要到操作完成才会释放,于是就产生了任务的阻塞与挂起,定时器就挂了。
最后将定时器回调里面的操作都改为非阻塞方式,问题解决。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐