添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

FreeRTOS提供了两个系统延时函数:相对延时函数vTaskDelay()和绝对延时vTaskDelayUntil()。

这两个延时函数和自己实现的延时函数不同,这两个延时函数一旦被调用,当前任务会立马进入 阻塞状态 ,而自己写的延时函数(以for循环等形式实现的软件延时)会被当做有效任务而一直执行。

  • 相对延时是指每次延时都是从任务执行函数vTaskDelay()开始,延时指定的时间结束;
  • 绝对延时是指每隔指定的时间,执行一次调用vTaskDelayUntil()函数的任务。换句话说:任务以固定的频率执行。

二、vTaskDelay()

调用vTaskDelay()函数后,任务会进入 阻塞状态 ,vTaskDelay()函数的参数xTicksToDelay表示延时多少个系统节拍时钟周期。在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelay 必须设置成1,此函数才能有效。

const portTickType xDelay = pdMS_TO_TICKS(500);
vTaskDelay(xDelay); 
vTaskDelay(pdMS_TO_TICKS(500)); //延迟500ms

vTaskDelay()指定的延时时间是从调用vTaskDelay()后开始计算的相对时间。

比如vTaskDelay(100),那么从调用vTaskDelay()后,任务进入阻塞状态,经过100个系统时钟节拍周期,任务解除阻塞。因此,vTaskDelay()并不适用与周期性执行任务的场合。此外,其它任务和中断活动,会影响到vTaskDelay()的调用(比如调用前高优先级任务抢占了当前任务),因此会影响任务下一次执行的时间。

三、vTaskDelayUntil()

API函数vTaskDelayUntil()可用于固定频率的延时,它用来延时一个绝对时间。
在文件FreeRTOSConfig.h中,宏INCLUDE_vTaskDelayUntil 必须设置成1,此函数才有效。

这个函数不同于vTaskDelay()函数的一个重要之处在于:vTaskDelay()指定的延时时间是从调用vTaskDelay()之后(执行完该函数)开始算起的,而vTaskDelayUntil()指定一个绝对时间,每当时间到达,则解除任务阻塞。

void vTaskDelayUntil( TickType_t * pxPreviousWakeTime, TickType_t xTimeIncrement );
参数 说明
pxPreviousWakeTime 指针,指向一个变量(指针说明这个变量即可以当做输入类型的,也可以当做输出类型的)。该变量保存任务最后一次解除阻塞的时间。 第一次使用前,该变量必须初始化为当前时间。 之后这个变量会在vTaskDelayUntil()函数内 自动更新
xTimeIncrement 周期循环时间。当时间等于(*pxPreviousWakeTime + xTimeIncrement)时,任务解除阻塞。如果不改变参数xTimeIncrement的值,调用该函数的任务会按照固定频率执行。

如果指定的唤醒时间已经达到,vTaskDelayUntil()立刻返回(不会有阻塞)。因此,使用vTaskDelayUntil()周期性执行的任务,无论任何原因(比如,任务临时进入挂起状态)停止了周期性执行,使得任务少运行了一个或多个执行周期,那么需要重新计算所需要的唤醒时间。这可以通过传递给函数的指针参数pxPreviousWake指向的值与当前系统时钟计数值比较来检测,在大多数情况下,这并不是必须的。

使用示例:

总共有四个任务:

idle task:优先级0

task1 :coutinuous task,优先级1

task2:coutinuous task,优先级1

task3:使用vTaskDelayUntil函数的周期性任务,优先级2

其中,task1、task2和task3的任务内容如下:

void vPeriodicTask( void *pvParameters )//task3
    TickType_t xLastWakeTime;
    const TickType_t xDelay3ms = pdMS_TO_TICKS( 3 );
    xLastWakeTime = xTaskGetTickCount();
    for( ;; )
         vPrintString( "Periodic task is running\r\n" );
         vTaskDelayUntil( &xLastWakeTime, xDelay3ms );
void vContinuousProcessingTask( void *pvParameters )//task2  task1
    char *pcTaskName;
    pcTaskName = ( char * ) pvParameters;
    for( ;; )
        vPrintString( pcTaskName );

直接结果:

vTaskDelayUntil函数比vTaskDelay函数多了一个记录任务本次被唤醒的时刻的变量,因此如果想要实现控制任务能够周期性运行的话,vTaskDelayUntil函数是一种比较简单的方法。

对于绝对延时函数,如果任务不是最高优先级,则仍然能周期性的将任务解除阻塞,但是解除阻塞的任务不一定能获得CPU权限,因此任务主体代码也不会总是精确周期性执行。

如果要想精确周期性执行某个任务,可以使用系统节拍钩子函数vApplicationTickHook(),它在系统节拍中断服务函数中被调用,因此这个函数中的代码必须简洁。

 

https://blog.csdn.net/zhzht19861011/article/details/51705148

https://blog.csdn.net/zhzht19861011/article/details/50454591

一、概述FreeRTOS提供了两个系统延时函数:相对延时函数vTaskDelay()和绝对延时vTaskDelayUntil()。这两个延时函数和自己实现的延时函数不同,这两个延时函数一旦被调用,当前任务会立马进入阻塞状态,而自己写的延时函数(以for循环等形式实现的软件延时)会被当做有效任务而一直执行。相对延时是指每次延时都是从任务执行函数vTaskDelay()开始,延时指定的时间结束; 绝对延时是指每隔指定的时间,执行一次调用vTaskDelayUntil()函数的任务。换句话说:任务以 就是交出CPU一段时间,如果任务一直不延时或者挂起,那么低优先级的任务会无法获得CPU。 FreeRTOS延时的单位是tick,就是调度的基本单位(不是毫秒) vTaskDelay和vTaskDelayUntil都是延时函数,vTaskDelayUntil是精确延时 void vTaskDelay( const TickType_t xTicksToDelay ) vo...
一、vTaskDelay 和 vTaskDelayUntill vTaskDelay :至少等待指定个数的tick interrupt才能变为就绪态。(所以在等待的时候是阻塞态) vTaskDelayUntill :等待到指定的绝对时刻,才能变为就绪态(所以在等待的时候是阻塞态)。 BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,//开始时间 const Ti
最近学习白问网韦东山老师在B站开源的freeRTOS课程,网址:韦东山直播公开课:RTOS实战项目之实现多任务系统 第1节:裸机程序框架和缺陷_哔哩哔哩_bilibili和7天物联网训练营【第2期】7天物联网智能家居实战训练营 在学习过程中按照韦老师的方法分析了下freeRTOS源码,如果有不对的地方请指证。 vTaskDelayUntil源码分析,基于cubemx生成的freeRTOS工程。 void vTaskDelayUntil( TickType_t * const pxPreviou.
想必各位嵌入式工程师对于Delay延时函数再也熟悉不过了~ 但对于各位刚入RTOS的小白来说,有操作系统的延时函数,真的和裸机中的延时函数一样吗?FreeRTOS的任务调度是怎么调度的?如何分配系统的CPU? 今天小编就带大家来扒一下FreeRTOS中的延时函数相对延时vTaskDelay函数,绝对延时vTaskDelayUntil函数。 从事嵌入式这一行的,想必大家在大学的时候一定上过C语言吧,上C语言的时候老师一定给大家写过Delay这个函数吧,给大家举个最简单的延时函数吧~ void De..
<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-b5506197d8.css"> <div id="content_views" class="htmledit_views"> <span style="font-family:Microsoft...
博主联系方式:QQ:1256153255 ,邮箱:1256153255@qq.com 点击这里可申请RH850开发板 最直接的办法就是从函数vTaskDelayUntil( TickType_t * const pxPreviousWakeTime,const TickType_t xTimeIncrement )的源码入手分析 #if ( INCLUDE_vTaskDelayUntil == 1 ) void vTaskDelayUntil( TickType_t * const pxPre
#if ( INCLUDE_vTaskDelay == 1 ) //延时特定时间xTicksToDelay,这个时间需要转换为唤醒绝对时间xTimeToWake, //这样才能在与vTaskIncrementTick函数中操作的数值是一致的xTicksToDelay:延时的节拍数 void vTaskDelay( const TickType_t xTicksToDelay ) ① vTaskDelayUntil精度比vTaskDelay高 ② 使用vTaskDelayUntil的任务不会丢失任务执行,vTaskDelay会丢失执行。 如下代码: Task2使用vTaskDelayUntil延时1s,Task3使用vTaskDelay延时1s, 优先级最高的Task1长期占用CPU(大概3秒),导致Task...
项目场景: ` 最近在准备找工作,没有实际的项目和经验,就买了几个模块结合FreeRTOS来拼凑拼凑整成一个项目——基于ESP8266的远程温度监控,使用MQTT协议和搭载FreeRTOS系统。 省流:vTaskDelay的使用需要放在任务中,否则运行不了! 问题描述: 使用ESP8266时候,按照oneNET的例程移植到STM32上,能够很好的运行,但是把代码复制到FreeRTOS时候却一直初始化不了,等于说是卡在初始化了。下图为初始化函数摆放位置。 原因分析: 在使用串口函数一步一步的在每一个函数
os_delay和vTaskDelay都是延时函数,但是它们的使用场景不同。 os_delay是裸机系统中的延时函数,适用于单片机没有操作系统支持的情况下使用。os_delay函数调用后,会使当前任务挂起一段时间,直到延时时间结束再继续执行下面的任务代码。os_delay函数的单位是毫秒,精度不高,适用于简单的延时操作。 vTaskDelay是FreeRTOS操作系统中的延时函数,适用于多任务情况下使用。vTaskDelay函数调用后,会使当前任务进入阻塞状态,等待延时时间结束后才会被重新调度执行。vTaskDelay函数的单位是系统节拍,可以实现更精确的延时操作。在多任务情况下,使用vTaskDelay可以更好地利用系统资源,避免空闲时间的浪费。