
來(lái)源:網(wǎng)絡(luò)素材
整理:技術(shù)讓夢(mèng)想更偉大 | 李肖遙
定時(shí)器可以說(shuō)是每個(gè) MCU 都有的外設(shè),有的 MCU 其定時(shí)器功能異常強(qiáng)大,比如提供 PWM、輸入捕獲等功能。但是最常用的還是定時(shí)器最基礎(chǔ)的功能——定時(shí),通過(guò)定時(shí)器來(lái)完成需要周期性處理的事務(wù)。
MCU 自帶的定時(shí)器屬于硬件定時(shí)器,不同的 MCU 其硬件定時(shí)器數(shù)量不同,因?yàn)橐紤]成本的問(wèn)題。FreeRTOS 也提供了定時(shí)器功能,不過(guò)是軟件定時(shí)器,軟件定時(shí)器的精度肯定沒(méi)有硬件定時(shí)器那么高,但是對(duì)于普通的精度要求不高的周期性處理的任務(wù)來(lái)說(shuō)夠了。當(dāng) MCU 的硬件定時(shí)器不夠的時(shí)候就可以考慮使用 FreeRTOS 的軟件定時(shí)器。
軟件定時(shí)器允許設(shè)置一段時(shí)間,當(dāng)設(shè)置的時(shí)間到達(dá)之后就執(zhí)行指定的功能函數(shù),被定時(shí)器調(diào)用的這個(gè)功能函數(shù)叫做定時(shí)器的回調(diào)函數(shù)。回調(diào)函數(shù)的兩次執(zhí)行間隔叫做定時(shí)器的定時(shí)周期,簡(jiǎn)而言之,當(dāng)定時(shí)器的定時(shí)周期到了以后就會(huì)執(zhí)行回調(diào)函數(shù)。
軟件定時(shí)器的回調(diào)函數(shù)是在定時(shí)器服務(wù)任務(wù)中執(zhí)行的,所以一定不能在回調(diào)函數(shù)中調(diào)用任何會(huì)阻塞任務(wù)的 API 函數(shù)!比如,定時(shí)器回調(diào)函數(shù)中千萬(wàn)不能調(diào)用 vTaskDelay()、vTaskDelayUnti(),還有一些訪問(wèn)隊(duì)列或者信號(hào)量的非零阻塞時(shí)間的 API 函數(shù)也不能調(diào)用。
定時(shí)器是一個(gè)可選的、不屬于 FreeRTOS 內(nèi)核的功能,它是由定時(shí)器服務(wù)(或 Daemon)任務(wù)來(lái)提供的。
FreeRTOS 提供了很多定時(shí)器有關(guān)的 API 函數(shù),這些 API 函數(shù)大多都使用 FreeRTOS的隊(duì)列發(fā)送命令給定時(shí)器服務(wù)任務(wù)。這個(gè)隊(duì)列叫做定時(shí)器命令隊(duì)列。定時(shí)器命令隊(duì)列是提供給FreeRTOS 的軟件定時(shí)器使用的,用戶不能直接訪問(wèn)!
版權(quán)聲明:本文來(lái)源網(wǎng)絡(luò),免費(fèi)傳達(dá)知識(shí),版權(quán)歸原作者所有。如涉及作品版權(quán)問(wèn)題,請(qǐng)聯(lián)系我進(jìn)行刪除。
???????????????? ?END ????????????????
關(guān)注我的微信公眾號(hào),回復(fù)“加群”按規(guī)則加入技術(shù)交流群。
點(diǎn)擊“閱讀原文”查看更多分享,歡迎點(diǎn)分享、收藏、點(diǎn)贊、在看。

左側(cè)部分屬于用戶應(yīng)用程序的一部分,并且會(huì)在某個(gè)用戶創(chuàng)建的用戶任務(wù)中調(diào)用。圖中右側(cè)部分是定時(shí)器服務(wù)任務(wù)的任務(wù)函數(shù),定時(shí)器命令隊(duì)列將用戶應(yīng)用任務(wù)和定時(shí)器服務(wù)任務(wù)連接在一起。在這個(gè)例子中,應(yīng)用程序調(diào)用了函數(shù) xTimerReset(),結(jié)果就是復(fù)位命令會(huì)被發(fā)送到定時(shí)器命令隊(duì)列中,定時(shí)器服務(wù)任務(wù)會(huì)處理這個(gè)命令。應(yīng)用程序是通過(guò)函數(shù) xTimerReset()間接的向定時(shí)器命令隊(duì)列發(fā)送了復(fù)位命令,并不是直接調(diào)用類(lèi)似 xQueueSend()這樣的隊(duì)列操作函數(shù)發(fā)送的。
配置在文件 FreeRTOSConfig.h 中。
1、configUSE_TIMERS
如果要使用軟件定時(shí)器的話宏 configUSE_TIMERS 一定要設(shè)置為 1,當(dāng)設(shè)置為 1 的話定時(shí)器服務(wù)任務(wù)就會(huì)在啟動(dòng) FreeRTOS 調(diào)度器的時(shí)候自動(dòng)創(chuàng)建。
2、configTIMER_TASK_PRIORITY
設(shè)置軟件定時(shí)器服務(wù)任務(wù)的任務(wù)優(yōu)先級(jí),可以為 0~( configMAX_PRIORITIES-1)。優(yōu)先級(jí)一定要根據(jù)實(shí)際的應(yīng)用要求來(lái)設(shè)置。如果定時(shí)器服務(wù)任務(wù)的優(yōu)先級(jí)設(shè)置的高的話,定時(shí)器命令隊(duì)列中的命令和定時(shí)器回調(diào)函數(shù)就會(huì)及時(shí)的得到處理。
3、configTIMER_QUEUE_LENGTH
此宏用來(lái)設(shè)置定時(shí)器命令隊(duì)列的隊(duì)列長(zhǎng)度。
4、configTIMER_TASK_STACK_DEPTH
此宏用來(lái)設(shè)置定時(shí)器服務(wù)任務(wù)的任務(wù)堆棧大小,單位為字,不是字節(jié)!,對(duì)于 STM32 來(lái)說(shuō)一個(gè)字是 4 字節(jié)。由于定時(shí)器服務(wù)任務(wù)中會(huì)執(zhí)行定時(shí)器的回調(diào)函數(shù),因此任務(wù)堆棧的大小一定要根據(jù)定時(shí)器的回調(diào)函數(shù)來(lái)設(shè)置。
軟件定時(shí)器分兩種:?jiǎn)未味〞r(shí)器和周期定時(shí)器,單次定時(shí)器的話定時(shí)器回調(diào)函數(shù)就執(zhí)行一次,比如定時(shí) 1s,當(dāng)定時(shí)時(shí)間到了以后就會(huì)執(zhí)行一次回調(diào)函數(shù),然后定時(shí)器就會(huì)停止運(yùn)行。對(duì)于單次定時(shí)器我們可以再次手動(dòng)重新啟動(dòng)(調(diào)用相應(yīng)的 API 函數(shù)即可),但是單次定時(shí)器不能自動(dòng)重啟。相反的,周期定時(shí)器一旦啟動(dòng)以后就會(huì)在執(zhí)行完回調(diào)函數(shù)以后自動(dòng)的重新啟動(dòng),這樣回調(diào)函數(shù)就會(huì)周期性的執(zhí)行。

Timer1 為單次定時(shí)器,定時(shí)器周期為 100,Timer2 為周期定時(shí)器,定時(shí)器周期為 200。
有時(shí)候我們可能會(huì)在定時(shí)器正在運(yùn)行的時(shí)候需要復(fù)位軟件定時(shí)器,復(fù)位軟件定時(shí)器的話會(huì)重新計(jì)算定時(shí)周期到達(dá)的時(shí)間點(diǎn),這個(gè)新的時(shí)間點(diǎn)是相對(duì)于復(fù)位定時(shí)器的那個(gè)時(shí)刻計(jì)算的,并不是第一次啟動(dòng)軟件定時(shí)器的那個(gè)時(shí)間點(diǎn)。下圖演示了這個(gè)過(guò)程,Timer1 是單次定時(shí)器,定時(shí)周期是 5s:

定時(shí)器復(fù)位過(guò)程,這是一個(gè)通過(guò)按鍵打開(kāi) LCD 背光的例子,我們假定當(dāng)喚醒鍵被按下的時(shí)候應(yīng)用程序打開(kāi) LCD 背光,當(dāng) LCD 背光點(diǎn)亮以后如果 5s 之內(nèi)喚醒鍵沒(méi)有再次按下就自動(dòng)熄滅。如果在這 5s 之內(nèi)喚醒鍵被按下了,LCD 背光就從按下的這個(gè)時(shí)刻起再亮 5s。
FreeRTOS 提供了兩個(gè) API 函數(shù)來(lái)完成軟件定時(shí)器的復(fù)位:


如果軟件定時(shí)器停止運(yùn)行的話可以使用 FreeRTOS 提供的兩個(gè)開(kāi)啟函數(shù)來(lái)重新啟動(dòng)軟件定時(shí)器。


具體的函數(shù)使用大家可以在用到的時(shí)候搜索用法,看一遍其實(shí)也記不住的。