yaqinblog.wordpress什么是網(wǎng)站推廣優(yōu)化
延時(shí)函數(shù)介紹
函數(shù) | 描述 |
vTaskDelay() | 相對(duì)延時(shí) |
xTaskDelayUntil() | 絕對(duì)延時(shí) |
相對(duì)延時(shí):指每次延時(shí)都是從執(zhí)行函數(shù)vTaskDelay()開(kāi)始,直到延時(shí)指定的時(shí)間結(jié)束?
絕對(duì)延時(shí):指將整個(gè)任務(wù)的運(yùn)行周期看成一個(gè)整體,適用于需要按照一定頻率運(yùn)行的任務(wù)?
- 為任務(wù)主體,也就是任務(wù)真正要做的工作
- 是任務(wù)函數(shù)中調(diào)用vTaskDelayUntil()對(duì)任務(wù)進(jìn)行延時(shí)
- 為其他任務(wù)在運(yùn)行?
vTaskDelay()
函數(shù) vTaskDelay()?用于對(duì)任務(wù)進(jìn)行延時(shí),延時(shí)的時(shí)間單位為系統(tǒng)時(shí)鐘節(jié)拍,使用函數(shù),需要的 FreeRTOSConfig.h 文件中將配置項(xiàng) INCLUDE_vTaskDelay 配置為 1。
void vTaskDelay(const TickType_t xTicksToDelay);?
????????函數(shù)用于使任務(wù)進(jìn)入阻塞狀態(tài),以實(shí)現(xiàn)延時(shí)功能。延時(shí)的時(shí)間以 FreeRTOS 的時(shí)鐘節(jié)拍為單位。?指每次延時(shí)都是從執(zhí)行函數(shù) vTaskDelay() 開(kāi)始,直到延時(shí)指定的時(shí)間(參數(shù):滴答值)結(jié)束。?
????????參數(shù) xTicksToDelay 用于設(shè)置延遲的時(shí)鐘節(jié)拍個(gè)數(shù),范圍 1- 0xFFFFFFFF。?
????????在使用此函數(shù)進(jìn)行任務(wù)延時(shí)時(shí),如果傳入的參數(shù)為 0,那表明不進(jìn)行任務(wù)延時(shí),而是強(qiáng)制進(jìn)行一次任務(wù)切換。
void vTaskDelay( const TickType_t xTicksToDelay )
{BaseType_t xAlreadyYielded = pdFALSE;/* 只有在延時(shí)時(shí)間大于 0 的時(shí)候,才需要進(jìn)行任務(wù)阻塞,* 否則相當(dāng)于強(qiáng)制進(jìn)行任務(wù)切換,而不阻塞任務(wù)*/if( xTicksToDelay > ( TickType_t ) 0U ){configASSERT( uxSchedulerSuspended == 0 );/* 掛起任務(wù)調(diào)度器 */vTaskSuspendAll();{/* 用于調(diào)試,不用理會(huì) */traceTASK_DELAY();/* 將任務(wù)添加到阻塞態(tài)任務(wù)列表中 */prvAddCurrentTaskToDelayedList( xTicksToDelay, pdFALSE );}/* 恢復(fù)任務(wù)調(diào)度器運(yùn)行,調(diào)用此函數(shù)會(huì)返回是否需要進(jìn)行任務(wù)切換*/xAlreadyYielded = xTaskResumeAll();}else{mtCOVERAGE_TEST_MARKER();}/* 根據(jù)標(biāo)志進(jìn)行任務(wù)切換 */if( xAlreadyYielded == pdFALSE ){portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();}
}
xTaskDelayUntil()
????????函數(shù)?xTaskDelayUntil() 用于對(duì)任務(wù)進(jìn)行絕對(duì)延時(shí),延時(shí)的時(shí)間單位為系統(tǒng)時(shí)鐘節(jié)拍,使用需要在 FreeRTOSConfig.h 文件中將配置項(xiàng) INCLUDE_vTaskDelayUntil?配置為 1。?
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,const TickType_t xTimeIncrement );
?????????函數(shù)描述:函數(shù) vTaskDelayUntil 用于周期性延遲。 屬于絕對(duì)延時(shí),指間隔指定的時(shí)間(參數(shù):滴答值),執(zhí)行一次調(diào)用 vTaskDelayUntil() 函數(shù)的任務(wù)。
參數(shù) | 說(shuō)明 |
pxPreviousWakeTime | 存儲(chǔ)任務(wù)最后一次解除阻塞的時(shí)間 |
xTimeIncrement | 周期性延遲時(shí)間 |
返回值 | BaseType_t |
pdTRUE | 操作成功 |
pdFALSE | 操作失敗 |
#if ( INCLUDE_xTaskDelayUntil == 1 )
BaseType_t xTaskDelayUntil(TickType_t * const pxPreviousWakeTime, /*上一次阻塞超時(shí)時(shí)間*/const TickType_t xTimeIncrement ) /*延時(shí)的時(shí)間*/
{TickType_t xTimeToWake;BaseType_t xAlreadyYielded, xShouldDelay = pdFALSE;configASSERT( pxPreviousWakeTime );configASSERT( ( xTimeIncrement > 0U ) );configASSERT( uxSchedulerSuspended == 0 );/* 掛起任務(wù)調(diào)度器 */vTaskSuspendAll();{const TickType_t xConstTickCount = xTickCount;/* 計(jì)算任務(wù)下一次阻塞超時(shí)的時(shí)間,* 這個(gè)阻塞超時(shí)時(shí)間是相對(duì)于上一次阻塞超時(shí)的時(shí)間的*/xTimeToWake = *pxPreviousWakeTime + xTimeIncrement/* 如果在上一次阻塞超時(shí)后,* 系統(tǒng)時(shí)鐘節(jié)拍計(jì)數(shù)器溢出過(guò)*/if( xConstTickCount < *pxPreviousWakeTime ){/* 只有在下一次阻塞超時(shí)時(shí)間也溢出,* 并且下一次阻塞超時(shí)時(shí)間大于系統(tǒng)時(shí)鐘節(jié)拍計(jì)數(shù)器的值時(shí),* 需要做相應(yīng)的溢出處理,否則就好像沒(méi)有溢出*/if( ( xTimeToWake < *pxPreviousWakeTime ) &&( xTimeToWake > xConstTickCount ) ){xShouldDelay = pdTRUE;/* 標(biāo)記因?yàn)橐绯?#xff0c;需要做相應(yīng)的處理 */}else{mtCOVERAGE_TEST_MARKER();}}else{/* 系統(tǒng)時(shí)鐘節(jié)拍計(jì)數(shù)器沒(méi)有溢出,* 但是下一次阻塞超時(shí)時(shí)間溢出了,* 并且下一次阻塞超時(shí)時(shí)間大于系統(tǒng)時(shí)鐘節(jié)拍計(jì)數(shù)器的值時(shí),* 需要做相應(yīng)的溢出處理*/if( ( xTimeToWake < *pxPreviousWakeTime ) ||( xTimeToWake > xConstTickCount ) ){ xShouldDelay = pdTRUE; /* 標(biāo)記因?yàn)橐绯?#xff0c;需要做相應(yīng)的溢出處理 */}else{mtCOVERAGE_TEST_MARKER();}}/* 更新上一次阻塞超時(shí)時(shí)間為下一次阻塞超時(shí)時(shí)間 */*pxPreviousWakeTime = xTimeToWake;/* 根據(jù)標(biāo)記,做相應(yīng)的溢出處理 */if( xShouldDelay != pdFALSE ){/* 用于調(diào)試,不用理會(huì) */traceTASK_DELAY_UNTIL( xTimeToWake );/* 將任務(wù)添加到阻塞態(tài)任務(wù)列表中 */prvAddCurrentTaskToDelayedList( xTimeToWake - xConstTickCount,pdFALSE );}else{mtCOVERAGE_TEST_MARKER();}}/* 恢復(fù)任務(wù)調(diào)度器運(yùn)行,* 調(diào)用此函數(shù)會(huì)返回是否需要進(jìn)行任務(wù)切換*/xAlreadyYielded = xTaskResumeAll();/* 根據(jù)標(biāo)志進(jìn)行任務(wù)切換 */if( xAlreadyYielded == pdFALSE ){portYIELD_WITHIN_API();}else{mtCOVERAGE_TEST_MARKER();} return xShouldDelay;
}
#endif /* INCLUDE_xTaskDelayUntil */
不知道你們有沒(méi)有想過(guò)為什么是?xTaskDelayUntil() 而不是?vTaskDelayUntil(),我在tasks.c文件中找到
延時(shí)函數(shù)演示實(shí)驗(yàn)
學(xué)習(xí) FreeRTOS 相對(duì)延時(shí)和絕對(duì)延時(shí)API 函數(shù)的使用,并了解其區(qū)別
實(shí)驗(yàn)設(shè)計(jì):
將設(shè)計(jì)三個(gè)任務(wù):start_task、task1、task2?
三個(gè)任務(wù)的功能如下:
- start_task:用來(lái)創(chuàng)建其他的2個(gè)任務(wù)
- task1:用于展示相對(duì)延時(shí)函數(shù)vTaskDelay ( )的使用
- task2:用于展示絕對(duì)延時(shí)函數(shù)vTaskDelayUntil( )的使用
?其他部分代碼如有需要可參考上一篇博文
?FreeRTOS 任務(wù)相關(guān)API函數(shù)
//用于展示相對(duì)延時(shí)函數(shù)vTaskDelay ( )的使用
void task1(void * pvParameters)
{while(1){LED0_TOGGLE();delay_ms(10);vTaskDelay(500);}}//用于展示絕對(duì)延時(shí)函數(shù)vTaskDelayUntil( )的使用
void task2(void * pvParameters)
{TickType_t xLastWakeTime = xTaskGetTickCount();while(1){LED1_TOGGLE(); delay_ms(10);xTaskDelayUntil(&xLastWakeTime,500);}
}
?現(xiàn)象
注意:
可能會(huì)出現(xiàn)任務(wù)一在延時(shí)時(shí),任務(wù)2在運(yùn)行,但是在任務(wù)1解除延時(shí)時(shí)候任務(wù)2剛好在死延時(shí),因?yàn)閮?yōu)先級(jí)原因所以任務(wù)1運(yùn)行不了代表任務(wù)1不止延時(shí)了510ms。