這個(gè)是全網(wǎng)最詳細(xì)的STM32項(xiàng)目教學(xué)視頻。
第一篇在這里:
視頻在這里
STM32智能小車(chē)V3-STM32入門(mén)教程-openmv與STM32循跡小車(chē)-stm32f103c8t6-電賽 嵌入式學(xué)習(xí) PID控制算法 編碼器電機(jī) 跟隨
**V3:HAL庫(kù)開(kāi)發(fā)、手把手教學(xué)下面功能:PID速度控制、PID循跡、PID跟隨、遙控、避障、PID角度控制、openmv視覺(jué)控制、電磁循跡、FreeRTOS、K210視覺(jué)智能車(chē)(更新中)、K230視覺(jué)智能車(chē)(更新中)、MSPM0G3507視覺(jué)智能車(chē)(更新中)**
21.1-RTOS和任務(wù)的一些概念
多任務(wù)運(yùn)行基本機(jī)制(重點(diǎn)理解 這是RTOS精髓)
理解RTOS的調(diào)度算法是如何安排調(diào)度的
21.1.0-任務(wù)里面寫(xiě)什么
在FreeRTOS中一個(gè)任務(wù)就是一個(gè)某種功能的函數(shù),任務(wù)函數(shù)內(nèi)部的一般是一個(gè)死循環(huán)結(jié)構(gòu)。任何時(shí)候不允許從任務(wù)函數(shù)退出。
可以把RTOS的任務(wù)理解成是裸機(jī)里面main的while循環(huán),一個(gè)任務(wù)就是一個(gè)裸機(jī)里面main的while循環(huán),他們?cè)谶m合的時(shí)機(jī)切換執(zhí)行。
// 溫度傳感器任務(wù)
void vTemperatureSensorTask(void *pvParameters) {
for (;;) {
/*************下面是溫度控制****************/
//讀取傳感器數(shù)值
readTemperatureSensor();
/*************上面是溫度控制****************/
vTaskDelay(1000); // 1秒
}
}
21.1.0-多個(gè)任務(wù)如何在單核MCU"同時(shí)運(yùn)行"
“分時(shí)復(fù)用”-實(shí)現(xiàn)了多個(gè)任務(wù)在單核MCU上的運(yùn)行
PPT 78頁(yè)到115頁(yè)是動(dòng)畫(huà)講解說(shuō)明如何實(shí)現(xiàn)"分時(shí)復(fù)用"
如果某個(gè)任務(wù)延時(shí)時(shí)間達(dá)到,則稱為這個(gè)任務(wù)進(jìn)入就緒狀態(tài)。
如果任務(wù)獲得CPU使用權(quán),則稱之為進(jìn)入運(yùn)行態(tài)。
21.1.1-如果兩個(gè)任務(wù)同時(shí)要運(yùn)行 應(yīng)該運(yùn)行那個(gè)?
假設(shè)某一個(gè)時(shí)刻按鍵掃描任務(wù)和溫度傳感器任務(wù)的阻塞延時(shí)時(shí)間同時(shí)達(dá)到,CPU會(huì)選擇那個(gè)任務(wù)先執(zhí)行?
- 優(yōu)先級(jí)不同執(zhí)行,優(yōu)先級(jí)高的。
- 優(yōu)先級(jí)相同,執(zhí)行先創(chuàng)建的
使用下面的PPT圖片講解
因?yàn)闇囟葌鞲衅魅蝿?wù)和按鍵掃描任務(wù)優(yōu)先級(jí)一樣,所以CPU會(huì)根據(jù)任務(wù)創(chuàng)建先后順序執(zhí)行會(huì)先執(zhí)行溫度傳感器任務(wù)!
21.1.1-如果有任務(wù)十分耗時(shí)且不釋放CPU怎么辦
PPT從119頁(yè)到136頁(yè)
這里我們假設(shè)如果在傳感器讀取任務(wù)中,如果傳感器讀取函數(shù)一直超時(shí)阻塞獲得傳感器數(shù)據(jù),那么將無(wú)法執(zhí)行VtaskDelay()函數(shù),任務(wù)就一直占用CPU 無(wú)法讓出CPU
其他任務(wù)將遲遲得不到執(zhí)行,我們稱之為**“任務(wù)饑餓”**
如何解決這個(gè)問(wèn)題那? 既然任務(wù)不讓出CPU,我們就每隔一段時(shí)間檢測(cè),是否有同優(yōu)先級(jí)或者高優(yōu)先級(jí)任務(wù)就緒,然后進(jìn)行調(diào)度,這就是FreeRTOS 的時(shí)間片輪轉(zhuǎn)調(diào)度機(jī)制
21.1.1-如何讓重要任務(wù)獲得更多CPU使用權(quán)
寫(xiě)過(guò)按鍵檢測(cè)掃描的同學(xué),應(yīng)該都知道按鍵程序要求一定的實(shí)時(shí)性和及時(shí)性,程序設(shè)計(jì)時(shí)要盡力保證按鍵程序的快速相應(yīng)。
所以我們可以把前面設(shè)計(jì)程序里面的按鍵掃描任務(wù)的優(yōu)先級(jí)提高
這樣CPU就會(huì)在兩個(gè)同時(shí)執(zhí)行需要執(zhí)行的任務(wù)中,先執(zhí)行按鍵掃描任務(wù)(因?yàn)槿蝿?wù)優(yōu)先級(jí)高的)—這就叫做基于優(yōu)先級(jí)的搶占式任務(wù)調(diào)度方法。
!!!總結(jié):前面我們介紹了時(shí)間片輪轉(zhuǎn)調(diào)度機(jī)制和基于優(yōu)先級(jí)的搶占式任務(wù)調(diào)度方法,其實(shí)FreeRTOS調(diào)度方式:采用使用時(shí)間片的搶占式任務(wù)調(diào)度方式
下面這段是剛剛演示的偽代碼。
#include "FreeRTOS.h"
//...省略頭文件
// 溫度傳感器任務(wù)
void vTemperatureSensorTask(void *pvParameters) {
for (;;) {
/*************下面是溫度控制****************/
//讀取傳感器數(shù)值
readTemperatureSensor();
/*************上面是溫度控制****************/
vTaskDelay(1000); // 1秒
}
}
// 溫度控制任務(wù)
void vTemperatureControllerTask(void *pvParameters) {
for (;;) {
/*************下面是溫度控制****************/
//根據(jù)閾值 控制加熱器
if (temperature > 50)
printf("Cooling system ON.n");
else
printf("Cooling system OFF.n");
/*************上面是溫度控制****************/
vTaskDelay(2000); // 2秒
}
}
// 按鍵掃描任務(wù)
void vButtonScanTask(void *pvParameters) {
for (;;) {
/*************下面是按鍵掃描內(nèi)容****************/
//通過(guò)GPIO輸入查詢 按鍵是否按下
state = HAL_GPIO_ReadPin(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN);
/*************上面是按鍵掃描內(nèi)容****************/
vTaskDelay(100); // 100毫秒
}
}
int main(void) {
// 創(chuàng)建任務(wù)
xTaskCreate(vTemperatureSensorTask, "Temp Sensor", 1000, NULL, 1, NULL);
xTaskCreate(vTemperatureControllerTask, "Temp Controller", 1000, NULL, 1, NULL);
xTaskCreate(vButtonScanTask, "Button Scan", 1000, NULL, 1, NULL);
// 啟動(dòng)調(diào)度器
vTaskStartScheduler();
// 如果調(diào)度器啟動(dòng)失敗,則進(jìn)入死循環(huán)
for (;;) {}
return 0;
}