FreeRTOS的vTaskDelay()和vTaskDelayUntil()

本文通过对比分析FreeRTOS中的vTaskDelay和vTaskDelayUntil两个延时函数,解释了它们在任务调度中的不同应用。vTaskDelay提供相对延时,任务执行周期随主体执行时间变化;而vTaskDelayUntil实现绝对延时,确保任务周期固定。测试程序展示了两者在实际应用中的效果,对于周期性任务如心跳包发送等,vTaskDelayUntil更具优势。

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)内

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_43175613

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值