1、void vTaskDelay( const TickType_t xTicksToDelay )
2、void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime, const TickType_t xTimeIncrement )
从参数看 :
相对延时:void vTaskDelay只需要一个形参,就是要延时的毫秒数(我的系统节拍是1ms,为了好理解我就直接说多少毫秒了,其实这个数代表的是系统节拍数)。
绝对延时:vTaskDelayUntil需要一个TickType_t 类型的指针;一个要延时的毫秒数
实际延时原理
:
vTaskDelay是从调用延时函数开始算xTicksToDelay毫秒后完成延时,主体函数运行时间越长,延时开始时间越往后,整体任务周期就会变长。
vTaskDelayUntil是以pxPreviousWakeTime开始算xTimeIncrement 毫秒后完成延时,因为pxPreviousWakeTime是从任务第一次执行开始就记录的一个数值,所以整个任务执行周期就是绝对时间xTimeIncrement毫秒(这里要保证任务主体执行时间小于延时时间)
测试程序,这里仅黏贴测试任务代码
void task_lED2(void *pvParameters)
{ // 本系统采用滴答定时器的1ms节拍
TickType_t PreviousWakeTime,MaskTime=0; //定义任务第一次调用时间点
const TickType_t TimeIncrement =pdMS_TO_TICKS(1000); //将延时时间1000ms转为节拍数
PreviousWakeTime=xTaskGetTickCount(); //获取当前节拍数 用于vTaskDelayUntil
while(1) //主体循环函数开始
{
LED2_TOGGLE; //翻转LED灯
printf("PreviousWakeTime=%d MaskTime=%d \t\r\n",PreviousWakeTime,MaskTime);
MaskTime+=100;
if(MaskTime>900)
MaskTime=0;
HAL_Delay(MaskTime); //利用HAL库延时增加主任务执行时间
// vTaskDelay(TimeIncrement);
vTaskDelayUntil(&PreviousWakeTime,TimeIncrement);
}
}
结果如下
可以看出,主体时间变化但是任务执行周期未变化一直保持1秒,这就是所谓的绝对延时,这在一些通讯协议要求周期发送心跳包中很实用。
下面使用vTaskDelay测试
void task_lED2(void *pvParameters)
{ // 本系统采用滴答定时器的1ms节拍
TickType_t PreviousWakeTime,MaskTime=0; //定义任务第一次调用时间点
const TickType_t TimeIncrement =pdMS_TO_TICKS(1000); //将延时时间3000转为节拍数
while(1) //主体循环函数开始
{
PreviousWakeTime=xTaskGetTickCount(); //获取当前节拍数 用于vTaskDelayUntil
LED2_TOGGLE; //翻转LED灯
printf("PreviousWakeTime=%d MaskTime=%d \t\r\n",PreviousWakeTime,MaskTime);
MaskTime+=100;
if(MaskTime>900)
MaskTime=0;
HAL_Delay(MaskTime); //利用HAL库延时增加主任务执行时间
vTaskDelay(TimeIncrement);
// vTaskDelayUntil(&PreviousWakeTime,TimeIncrement);
}
}
结果如下
可以看出任务总体运行时间为主体运行时间+TimeIncrement延时时间,总的任务运行周期是根据任务主体执行时间变化的,这就是相对时间,相对于主体任务结束时候延时的时间,也可以理解为在任务执行后顺延的时间。
说明:vTaskDelayUntil()函数内部有一句代码 *pxPreviousWakeTime = xTimeToWake;每次循环会更新pxPreviousWakeTime值,所以只需要在进入死循环前只需要调用一次即可;但是vTaskDelay()没有,所以为了输出系统节拍时间将PreviousWakeTime=xTaskGetTickCount(); 移动到while(1)内