目录一、延时函数分类:1.相对延时vTaskDelay2.绝对延时vTaskDelayUntil二、vTaskDelay 与 HAL_Delay 的区别:vTaskDelayFreeRTOSHAL_DelayHAL库一、延时函数分类:相对延时vTaskDelay绝对延时vTaskDelayUntil1.相对延时vTaskDelayvTaskDelay函数实现的是相对延时即从当前时刻开始计算延时时间。这个函数会将任务挂起指定的系统时钟节拍数ticks直到指定的时间过去后任务才会被重新调度执行。vTaskDelay( xTicksToDelay );xTicksToDelay这是要延时的系统时钟节拍数。可以通过pdMS_TO_TICKS宏将毫秒数转换为系统时钟节拍数。vTaskDelay( pdMS_TO_TICKS(100) );这会导致任务挂起直到100毫秒后。2.绝对延时vTaskDelayUntilvTaskDelayUntil函数实现的是绝对延时即从某个特定的未来时刻开始计算延时时间。这个函数会将任务挂起直到从上一次调用vTaskDelayUntil后经过了指定的时间间隔。vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement );pxPreviousWakeTime这是一个指针指向一个变量该变量保存了任务上一次被唤醒的时间以系统时钟节拍为单位。每次调用vTaskDelayUntil时都应该传入同一个变量的地址。xTimeIncrement这是要延时的系统时钟节拍数。例如如果你想让任务每隔100毫秒执行一次可以这样调用const TickType_t xDelay pdMS_TO_TICKS(100); TickType_t xLastWakeTime; // 初始化xLastWakeTime xLastWakeTime xTaskGetTickCount(); while(1) { // 任务代码... // 延时直到下一个100毫秒 vTaskDelayUntil( xLastWakeTime, xDelay ); }在这个循环中xLastWakeTime会在每次调用vTaskDelayUntil时更新以确保任务每隔100毫秒被唤醒一次。总结来说vTaskDelay是基于当前时间的相对延时而vTaskDelayUntil是基于上一次唤醒时间的绝对延时。使用vTaskDelayUntil可以更容易地实现周期性的任务调度。二、vTaskDelay与HAL_Delay的区别:vTaskDelay和HAL_Delay是两个完全不同的函数它们分别属于不同的系统和库用于不同的上下文和目的。下面是它们的主要区别vTaskDelayFreeRTOSvTaskDelay是FreeRTOS实时操作系统RTOS中的一个函数。它用于实现任务的延时使当前任务挂起指定的系统时钟节拍数ticks让出CPU给其他任务运行。vTaskDelay是协作式的它不会立即阻塞CPU而是让任务进入阻塞状态直到指定的延时时间过去。它允许任务在延时期间被操作系统的其他部分如中断服务例程打断。vTaskDelay的参数是系统时钟节拍数可以通过pdMS_TO_TICKS宏将毫秒数转换为系统时钟节拍数。HAL_DelayHAL库HAL_Delay是硬件抽象层HAL库中的一个函数通常用于STM32等微控制器。它用于实现一个简单的延时通常是通过阻塞CPU来实现的即在延时期间CPU不做其他事情只是等待。HAL_Delay是非协作式的它会阻塞CPU直到指定的毫秒数过去。它不允许在延时期间被中断打断因此可能会影响系统的实时性。HAL_Delay的参数是毫秒数。void vTaskDelay( const TickType_t xTicksToDelay ) { BaseType_t xAlreadyYielded pdFALSE; /* A delay time of zero just forces a reschedule. */ if( xTicksToDelay ( TickType_t ) 0U ) { configASSERT( uxSchedulerSuspended 0 ); vTaskSuspendAll(); { traceTASK_DELAY(); /* A task that is removed from the event list while the scheduler is suspended will not get placed in the ready list or removed from the blocked list until the scheduler is resumed. This task cannot be in an event list as it is the currently executing task. */ prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE ); } xAlreadyYielded xTaskResumeAll(); } else { mtCOVERAGE_TEST_MARKER(); } /* Force a reschedule if xTaskResumeAll has not already done so, we may have put ourselves to sleep. */ if( xAlreadyYielded pdFALSE ) { portYIELD_WITHIN_API(); } else { mtCOVERAGE_TEST_MARKER(); } }__weak void HAL_Delay(uint32_t Delay) { uint32_t tickstart HAL_GetTick(); uint32_t wait Delay; /* Add a freq to guarantee minimum wait */ if (wait HAL_MAX_DELAY) { wait (uint32_t)(uwTickFreq); } while ((HAL_GetTick() - tickstart) wait) { } }vTaskDelay 作用是让任务阻塞任务阻塞后RTOS系统调用其它处于就绪状态的优先级最高的任务来执行。HAL_Delay 一直不停的调用获取系统时间的函数直到指定的时间流逝然后退出故其占用了全部CPU时间。在实际应用中选择使用哪个函数取决于你的系统需求和上下文如果你在使用FreeRTOS并且需要实现任务间的协作和调度那么应该使用vTaskDelay。如果你在使用STM32 HAL库并且需要一个简单的CPU阻塞延时那么可以使用HAL_Delay。需要注意的是HAL_Delay可能会影响RTOS的调度因为它会阻塞CPU所以在使用RTOS的情况下通常推荐使用vTaskDelay或其他RTOS提供的延时函数。此外HAL_Delay通常依赖于系统的时钟配置而vTaskDelay则依赖于FreeRTOS的时钟节拍配置。参考资料1. FreeRTOS官方文档https://www.freertos.org/2. STM32 HAL库开发手册本文为个人学习笔记整理仅供学习交流使用。