【教程】STM32 FreeRTOS實(shí)時(shí)系統(tǒng)移植系列4:FreeRTOS 軟件定時(shí)器

寫在前面:
?
本文章為《STM32MP157開發(fā)教程之FreeRTOS操作系統(tǒng)篇》系列中的一篇,筆者使用的開發(fā)平臺(tái)為華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157開發(fā)板)。stm32mp157是ARM雙核,2個(gè)A7核,1個(gè)M4核,A7核上可以跑Linux操作系統(tǒng),M4核上可以跑FreeRTOS、RT-Thread等實(shí)時(shí)操作系統(tǒng),STM32MP157開發(fā)板所以既可以學(xué)嵌入式linux,也可以學(xué)stm32單片機(jī)。
針對(duì)FS-MP1A開發(fā)板,除了FreeRTOS操作系統(tǒng)篇外,還包括其他多系列教程,包括Cortex-A7開發(fā)篇、Cortex-M4開發(fā)篇、擴(kuò)展板驅(qū)動(dòng)移植篇、Linux應(yīng)用開發(fā)篇、Linux系統(tǒng)移植篇、Linux驅(qū)動(dòng)開發(fā)篇、硬件設(shè)計(jì)篇、人工智能機(jī)器視覺篇、Qt應(yīng)用編程篇、Qt綜合項(xiàng)目實(shí)戰(zhàn)篇等。歡迎關(guān)注,更多stm32mp157開發(fā)教程及視頻,可加技術(shù)交流Q群459754978,感謝關(guān)注。
FS-MP1A開發(fā)板詳情介紹:https://item.taobao.com/item.htm?id=622457259672
2.FreeRTOS軟件定時(shí)器
2.1軟件定時(shí)器簡(jiǎn)介
對(duì)于MCU而言,其自帶的定時(shí)器屬于硬件定時(shí)器,在FreeRTOS系統(tǒng)中,另外提供了軟件定時(shí)器功能。軟件定時(shí)器的精度比不上硬件定時(shí)器,但對(duì)于要求不高的周期性處理任務(wù)來說足夠了。
軟件定時(shí)器可以設(shè)置一段時(shí)間,當(dāng)設(shè)置的時(shí)間到達(dá)以后就去執(zhí)行回調(diào)函數(shù),其中,回調(diào)函數(shù)的兩次執(zhí)行間隔就是定時(shí)器的定時(shí)周期,即每次定時(shí)周期到達(dá)以后就去執(zhí)行一次回調(diào)函數(shù)。因?yàn)榛卣{(diào)函數(shù)是在定時(shí)器服務(wù)函數(shù)中執(zhí)行的,因此在回調(diào)函數(shù)中一定不能調(diào)用會(huì)阻塞任務(wù)的API函數(shù)。
軟件定時(shí)器分為周期定時(shí)器和單次定時(shí)器兩種。周期定時(shí)器啟動(dòng)以后就會(huì)在執(zhí)行完回調(diào)函數(shù)后自動(dòng)的重新啟動(dòng),所以回調(diào)函數(shù)可以周期性執(zhí)行,對(duì)于單次定時(shí)器,回調(diào)函數(shù)只執(zhí)行一次,執(zhí)行完以后,定時(shí)器就會(huì)停止運(yùn)行,當(dāng)然我們可以調(diào)用函數(shù)再次手動(dòng)重新啟動(dòng)。
2.2軟件定時(shí)器函數(shù)
2.2.1 復(fù)位定時(shí)器
在定時(shí)器正常運(yùn)行時(shí),我們有時(shí)可能需要定時(shí)器的復(fù)位操作,當(dāng)復(fù)位軟件定時(shí)器時(shí),系統(tǒng)會(huì)重新計(jì)算定時(shí)周期到達(dá)的時(shí)間點(diǎn),但此時(shí)間點(diǎn)是相對(duì)于復(fù)位時(shí)刻計(jì)算的,并不是第一次啟動(dòng)軟件定時(shí)器的那個(gè)時(shí)間點(diǎn)。
在新版FreeRTOS中,共有兩個(gè)API函數(shù)可以完成軟件定時(shí)器的復(fù)位,分別應(yīng)用于任務(wù)中和中斷中。
任務(wù)級(jí)復(fù)位軟件定時(shí)器函數(shù)xTimerReset(),此函數(shù)是一個(gè)宏,其函數(shù)原型如下
BaseType_t xTimerReset( TimerHandle_t xTimer,
TickType_t xTicksToWait)
參數(shù):
xTimer:要復(fù)位的軟件定時(shí)器的句柄。
xTickToWait:設(shè)置阻塞時(shí)間。
返回值:
pdPASS:軟件定時(shí)器復(fù)位成功,即命令發(fā)送成功。
pdFAIL:軟件定時(shí)器復(fù)位失敗,即命令發(fā)送失敗。
任務(wù)級(jí)復(fù)位軟件定時(shí)器函數(shù)xTimerReset(),此函數(shù)是一個(gè)宏,其函數(shù)原型如下
BaseType_t xTimerResetFromISR( TimerHandle_t xTimer,
BaseType_t * pxHigherPriorityTaskWoken );
參數(shù):
xTimer:要復(fù)位的軟件定時(shí)器的句柄。
pxHigherPriorityTaskWoken:記退出此函數(shù)以后是否進(jìn)行任務(wù)切換,用戶不用進(jìn)行設(shè)置。
返回值:
pdPASS:軟件定時(shí)器復(fù)位成功,即命令發(fā)送成功。
pdFAIL:軟件定時(shí)器復(fù)位失敗,即命令發(fā)送失敗。
2.2.2 創(chuàng)建軟件定時(shí)器
創(chuàng)建軟件定時(shí)器的函數(shù)有兩個(gè),分別如下:
xTimerCreate(),此函數(shù)用于創(chuàng)建軟件定時(shí)器,所需要的內(nèi)存通過動(dòng)態(tài)內(nèi)存管理方法分配,創(chuàng)建以后軟件定時(shí)器處于休眠狀態(tài),其函數(shù)原型如下:
TimerHandle_t xTimerCreate( const char * const pcTimerName,
TickType_t xTimerPeriodInTicks,
UBaseType_t uxAutoReload,
void * pvTimerID,
TimerCallbackFunction_t pxCallbackFunction )
參數(shù):
pcTimerName: 軟件定時(shí)器名字,是一串字符串,用于調(diào)試使用。
xTimerPeriodInTicks: 定時(shí)器周期,單位是時(shí)鐘節(jié)拍數(shù)。
uxAutoReload: 設(shè)置定時(shí)器模式,單次定時(shí)器還是周期定時(shí)器。
pvTimerID: 定時(shí)器ID號(hào)。
pxCallbackFunction: 定時(shí)器回調(diào)函數(shù)。
返回值:
NULL:軟件定時(shí)器創(chuàng)建失敗。
其他值:創(chuàng)建成功的軟件定時(shí)器句柄。
xTimerCreateStatic(),此函數(shù)也用于創(chuàng)建軟件定時(shí)器,所需要的內(nèi)存通過用戶自行分配,創(chuàng)建以后軟件定時(shí)器處于休眠狀態(tài),其函數(shù)原型如下:
TimerHandle_t xTimerCreateStatic(const char * const pcTimerName,
TickType_t xTimerPeriodInTicks,
UBaseType_t uxAutoReload,
void * pvTimerID,
TimerCallbackFunction_t pxCallbackFunction,
StaticTimer_t * pxTimerBuffer )
參數(shù):
pcTimerName: 軟件定時(shí)器名字,是一串字符串,用于調(diào)試使用。
xTimerPeriodInTicks:定時(shí)器周期,單位是時(shí)鐘節(jié)拍數(shù)。
uxAutoReload: 設(shè)置定時(shí)器模式,單次定時(shí)器還是周期定時(shí)器。
pvTimerID: 定時(shí)器ID號(hào)。
pxCallbackFunction: 定時(shí)器回調(diào)函數(shù)。
pxTimerBuffer: 指向一個(gè)StaticTimer_t類型的變量,用來保存定時(shí)器結(jié)構(gòu)體。
返回值:
NULL:軟件定時(shí)器創(chuàng)建失敗。
其他值:創(chuàng)建成功的軟件定時(shí)器句柄。
2.2.3 開啟軟件定時(shí)器
開啟軟件定時(shí)器的函數(shù)也有兩個(gè),分別如下:
任務(wù)級(jí)開啟定時(shí)器函數(shù)xTimerStart(),此函數(shù)是個(gè)宏,如果軟件定時(shí)器沒有運(yùn)行的話調(diào)用函數(shù) xTimerStart()就會(huì)計(jì)算定時(shí)器到期時(shí)間,如果軟件定時(shí)器正在運(yùn)行的話調(diào)用函數(shù) xTimerStart()的結(jié)果和 xTimerReset()一樣,其函數(shù)原型如下:
BaseType_t xTimerStart( TimerHandle_t xTimer,
TickType_t xTicksToWait )
參數(shù):
xTimer: 要開啟的軟件定時(shí)器句柄。
xTickToWait: 設(shè)置阻塞時(shí)間。
返回值:
pdPASS:軟件定時(shí)器開啟成功,即命令發(fā)送成功。
pdFAIL:軟件定時(shí)器開啟失敗,即命令發(fā)送失敗。
中斷級(jí)開啟定時(shí)器函數(shù)xTimerStartFromISR(),此函數(shù)也是個(gè)宏,為函數(shù)xTimerStart()的中斷版本,只能用于中斷服務(wù)函數(shù)中,其函數(shù)原型如下:
BaseType_t xTimerStartFromISR( TimerHandle_t xTimer,
BaseType_t * pxHigherPriorityTaskWoken );
參數(shù):
xTimer: 要開啟的軟件定時(shí)器句柄。
pxHigherPriorityTaskWoken: 標(biāo)記退出此函數(shù)以后是否進(jìn)行任務(wù)切換。
返回值:
pdPASS:軟件定時(shí)器開啟成功,即命令發(fā)送成功。
pdFAIL:軟件定時(shí)器開啟失敗,即命令發(fā)送失敗。
2.2.4 停止軟件定時(shí)器
與開啟軟件定時(shí)器一樣,停止軟件定時(shí)器的函數(shù)也有兩個(gè),分別如下:
任務(wù)級(jí)停止定時(shí)器函數(shù)xTimerStop(),此函數(shù)是個(gè)宏,其函數(shù)原型如下:
BaseType_t xTimerStop( TimerHandle_t xTimer,
TickType_t xTicksToWait )
參數(shù):
xTimer: 要停止的軟件定時(shí)器句柄。
xTickToWait: 設(shè)置阻塞時(shí)間。
返回值:
pdPASS:軟件定時(shí)器停止成功,即命令發(fā)送成功。
pdFAIL:軟件定時(shí)器停止失敗,即命令發(fā)送失敗。
中斷級(jí)停止定時(shí)器函數(shù)xTimerStopFromISR(),此函數(shù)也是個(gè)宏,為函數(shù)xTimerStop()的中斷版本,只能用于中斷服務(wù)函數(shù)中,其函數(shù)原型如下:
BaseType_t xTimerStopFromISR( TimerHandle_t xTimer,
BaseType_t * pxHigherPriorityTaskWoken );
參數(shù):
xTimer: 要停止的軟件定時(shí)器句柄。
pxHigherPriorityTaskWoken: 標(biāo)記退出此函數(shù)以后是否進(jìn)行任務(wù)切換。
返回值:
pdPASS:軟件定時(shí)器停止成功,即命令發(fā)送成功。
pdFAIL:軟件定時(shí)器停止失敗,即命令發(fā)送失敗。
2.3操作實(shí)驗(yàn)
2.3.1實(shí)驗(yàn)設(shè)計(jì)
本次實(shí)驗(yàn)創(chuàng)建兩個(gè)軟件定時(shí)器,分別為周期定時(shí)器CycleTimer_Handle和單次定時(shí)器SingleTimer_Handle,其中,CycleTimer_Handle的定時(shí)器周期為1000個(gè)時(shí)鐘節(jié)拍,SingleTimer_Handle的定時(shí)器周期為2000個(gè)時(shí)鐘節(jié)拍。
可參考12.3.2章節(jié)進(jìn)行導(dǎo)入已有工程,工程存放路徑【華清遠(yuǎn)見-FS-MP1A開發(fā)資料\02-程序源碼\ARM體系結(jié)構(gòu)與接口技術(shù)\FreeRTOS\4_MP1A-FreeRTOS-TIMER】
通過按鍵中斷設(shè)置不同的指令,在任務(wù)中根據(jù)接收到的指令來控制周期定時(shí)器與單次定時(shí)器的工作。
任務(wù)及其功能如下:
StartTask02(): 控制LED3閃爍,提示系統(tǒng)正在運(yùn)行。
StartDefaultTask():進(jìn)行指令處理,根據(jù)接收的指令控制定時(shí)器工作。
2.3.2實(shí)驗(yàn)過程與分析
首先,根據(jù)之前幾章內(nèi)容配置好CubeMX,按照上一節(jié)配置“FREERTOS”,完成后生成代碼。 在StartDefaultTask() 與StartTask02()中添加代碼如下。

當(dāng)按下KEY1鍵時(shí),單次定時(shí)器工作,當(dāng)定時(shí)器時(shí)間到了以后就會(huì)調(diào)用OneShotCallback()函數(shù),此時(shí)會(huì)發(fā)現(xiàn)LED1的電平發(fā)生翻轉(zhuǎn),然后停止運(yùn)行。當(dāng)按下KEY2鍵時(shí),周期定時(shí)器工作,當(dāng)定時(shí)器時(shí)間到了以后就會(huì)調(diào)用AutoReloadCallback()函數(shù),因?yàn)橹芷诙〞r(shí)器不會(huì)停止運(yùn)行,此時(shí)會(huì)發(fā)現(xiàn)LED2每隔1秒電平發(fā)生翻轉(zhuǎn)。當(dāng)按下KEY3鍵時(shí),單次定時(shí)器和周期定時(shí)器關(guān)閉,LED燈的電平不再發(fā)生變化。
硬件平臺(tái):華清遠(yuǎn)見FS-MP1A開發(fā)板(STM32MP157)
部分開發(fā)教程下載:加QQ群459754978,群文件里有。
淘寶購(gòu)買鏈接:華清遠(yuǎn)見stm32mp157開發(fā)板stm32 linux開發(fā)板單片機(jī)arm嵌入式學(xué)習(xí)
手機(jī)淘寶分享碼:復(fù)制本行文字打開手淘?T4FPXn3YYJ2?