[uCOS/RTOS]FreeRTOS操作系统——时间管理系统延时(八)

# 前言
FreeRTOS操作系统时间管理主要分为三部分:

一、FreeRTOS系统延时函数

二、滴答定时器

三、FreeRTOS系统时钟节拍

这一节主要学习系统延时

# 一、系统延时函数


![<font color=#999AAA >示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。](?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5oiR5LiObmFubw==,size_17,color_FFFFFF,t_70,g_se,x_16)
```c
vTaskDelay();     //相对延时
vTaskDelayUntil();  //绝对延时
```
相对延时与绝对延时的区别
相对延时:vTaskDelay():
相对延时是指每次延时都是从任务执行函数vTaskDelay()开始,延时指定的时间结束

绝对延时:vTaskDelayUntil():
绝对延时是指调用vTaskDelayUntil()的任务每隔x时间运行一次。也就是任务周期运行。

# 二、延时函数详解
![在这里插入图片描述](?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5oiR5LiObmFubw==,size_14,color_FFFFFF,t_70,g_se,x_16)

## 1.相对延时函数vTaskDelay()
在学习vTaskDelay()函数过程中,会使用这个函数很简单。

```c
vTaskDelay(500);//延时500ms
```
相对延时vTaskDelay()是从调用vTaskDelay()这个函数的时候开始延时,但是任务执行的时候,可能发生了中断,导致任务执行时间变长了,但是整个任务的延时时间还是1000个tick,这就不是周期性了

```c
void vTaskA( void * pvParameters )  
{  
        while(1)
     {  
         //  ...
         //  这里为任务主体代码
         //  ...

         /* 调用相对延时函数,阻塞1000个tick */
         vTaskDelay( 1000 );  
     }  
}
```
![在这里插入图片描述](?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5oiR5LiObmFubw==,size_20,color_FFFFFF,t_70,g_se,x_16)
当任务运行的时候,假设被某个高级任务或者是中断打断了,那么任务的执行时间就更长了,然而延时还是延时1000个tick这样子,整个系统的时间就混乱了。

函数 prvAddCurrentTaskToDelayedList()用于将当前任务添加到等待列表中

```c
void vTaskDelay( const TickType_t xTicksToDelay )
{
BaseType_t xAlreadyYielded = pdFALSE;
    /* 如果延时时间为0,则不会将当前任务加入延时列表 */
    if( xTicksToDelay > ( TickType_t ) 0U )
    {
        vTaskSuspendAll();
        {
            /* 将当前任务从就绪列表中移除,并根据当前系统节拍计数器值计算唤醒时间,然后将任务加入延时列表 */
            prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );
        }
        xAlreadyYielded = xTaskResumeAll();
    }
    /* 强制执行一次上下文切换*/
    if( xAlreadyYielded == pdFALSE )
    {
        portYIELD_WITHIN_API();
    }
}
```

## 2绝对延时函数vTaskDelayUntil()

调用vTaskDelayUntil()是希望任务以固定频率定期执行,而不受外部的影响,任务从上一次运行开始到下一次运行开始的时间间隔是绝对的,而不是相对的。假设主体任务被打断0.3s,不会影响这个周期性,只是会缩短其它任务的执行时间!

![在这里插入图片描述](?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5oiR5LiObmFubw==,size_16,color_FFFFFF,t_70,g_se,x_16)

```c
void vTaskA( void * pvParameters )  
{  
    /* 用于保存上次时间。调用后系统自动更新 */
    static portTickType PreviousWakeTime;
    /* 设置延时时间,将时间转为节拍数 */
    const portTickType TimeIncrement = pdMS_TO_TICKS(1000);
    /* 获取当前系统时间 */
    PreviousWakeTime = xTaskGetTickCount();
    while(1)
     {  

         /* 调用绝对延时函数,任务时间间隔为1000个tick */
         vTaskDelayUntil( &PreviousWakeTime,TimeIncrement );  

         //  ...
         //  这里为任务主体代码
         //  ...

     }  
}
```
实例
```c
void vTask3(void *pvParam)
{
  while(1)
    {
        /*
        任务主体
       */
        vTaskDelay(1000);
    }
}

void vTask2(void *pvParam)
{
   TickType_t lasttick = xTaskGetTickCount();
  while(1)
    {
        vTaskDelayUntil(&lasttick, 1000);
        /*
          任务主体
      */

}


```

![在这里插入图片描述](?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5oiR5LiObmFubw==,size_20,color_FFFFFF,t_70,g_se,x_16)
在使用的时候要将延时时间转化为系统节拍,在任务主体之前要调用延时函数。任务会先调用vTaskDelayUntil()使任务进入阻塞态,等到时间到了就从阻塞中解除,然后执行主体代码,任务主体代码执行完毕。会继续调用vTaskDelayUntil()使任务进入阻塞态,然后循环执行。即使任务在执行过程中发生中断,那么也不会影响这个任务的运行周期,仅仅是缩短了阻塞的时间而已。

与相对延时函数vTaskDelay不同,本函数增加了一个参数pxPreviousWakeTime用于指向一个变量,变量保存上次任务解除阻塞的时间,此后函数vTaskDelayUntil()在内部自动更新这个变量。由于变量xTickCount可能会溢出,所以程序必须检测各种溢出情况,并且要保证延时周期不得小于任务主体代码执行时间。

```c
xTimeIncrement():任务周期时间
pxPreviousWakeTime():上一次唤醒的时间点
xTimeToWake():下一次唤醒的系统时间点
xConstTickCount():进入延时的时间点
```

# 总结
如果任务调用相对延时,其运行周期完全是不可测的,如果任务的优先级不是最高的话,其误差更大,就好比一个必须要在5ms内相应的任务,假如使用了相对延时1ms,那么很有可能在该任务执行的时候被更高优先级的任务打断,从而错过5ms内的相应,但是调用绝对延时,则任务会周期性将该任务在阻塞列表中解除,但是,任务能不能运行,还得取决于任务的优先级,如果优先级最高的话,任务周期还是比较精确的(相对vTaskDelay来说)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值