1、两个延时函数
- vTaskDelay:至少等待指定个数的Tick Interrupt才能变为就绪态。
- vTaskDelayUntil:等待到指定的绝对时刻,才能变为就绪态。
2、函数原型
/* xTicksToDelay: 等待多少个Tick */
void vTaskDelay( const TickType_t xTicksToDelay );
/* pxPreviousWakeTime: 上一次被唤醒的时间
* xTimeIncrement: 要阻塞到(pxPreviousWakeTime + xTimeIncrement)
* 单位都是Tick Count
*/
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement );
3、画图说明
(1)使用vTaskDelay(n)时,进入、退出vTaskDelay的时间间隔至少是n个Tick中断。
(2)使用xTaskDelayUntil(&Pre, n)时,前后两次退出xTaskDelayUntil的时间至少是n个Tick中断。退出xTaskDelayUntil时任务就进入的就绪状态,一般都能得到执行机会,所以可以使用xTaskDelayUntil来让任务周期性地运行。
4、示例程序
4.1、程序说明
本程序会创建2个任务:Task1和Task2。
(1)Task1
- 高优先级
- 设置变量flag为1,然后调用 vTaskDelay(xDelay50ms);
- 或vTaskDelayUntil(&xLastWakeTime, xDelay50ms);
(2)Task2
- 低优先级
- 设置变量flag为0
4.2、主要函数
(1)main函数
int main( void )
{
//......
/* Task1的优先级更高, Task1先执行 */
xTaskCreate( vTask1, "Task 1", 1000, NULL, 2, NULL );
xTaskCreate( vTask2, "Task 2", 1000, NULL, 1, NULL );
/* 启动调度器 */
vTaskStartScheduler();
/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
return 0;
}
(2)Task1函数
void vTask1( void *pvParameters )
{
const TickType_t xDelay50ms = pdMS_TO_TICKS( 50UL );
TickType_t xLastWakeTime;
int i;
/* 获得当前的Tick Count */
xLastWakeTime = xTaskGetTickCount();
for( ;; )
{
flag = 1;
/* 故意加入多个循环,让程序运行时间长一点 */
for (i = 0; i <5; i++)
printf( "Task 1 is running\r\n" );
#if 1
vTaskDelay(xDelay50ms);
#else
vTaskDelayUntil(&xLastWakeTime, xDelay50ms);
#endif
}
}
(3)Task2函数
void vTask2( void *pvParameters )
{
for( ;; )
{
flag = 0;
printf( "Task 2 is running\r\n" );
}
}
4.3、flag变量的bit波形
使用Keil的逻辑分析观察flag变量的bit波形,如下:
- flag为1时表示Task1在运行,flag为0时表示Task2在运行,也就是Task1处于阻塞状态。
- vTaskDelay:指定的是阻塞的时间。
- vTaskDelayUntil:指定的是任务执行的间隔、周期。
4.4、完整工程下载地址
(1)完整工程存储再码云。
(2)FreeRTOS_CSDN: 保存FreeRTOS学习及使用中的程序