☛ 功能說明
利用 Arduino UNO 開發板及 FreeRTOS 函式庫控制兩個 LED 同時以不同頻率閃爍,並且透過 Serial Monitor 觀察每一個時間兩個任務 ( Tash ) 的運行狀況。
☛ 使用材料
Arduino UNO R3 開發板 × 1、LED × 2、電阻 220Ω × 2。
☛ 電路圖及麵包板接線圖
☛ 程式碼
#include<Arduino_FreeRTOS.h> //引用 FreeRTOS 函式庫 void Task1( void *pvParameters ); //宣告 Task1 void Task2( void *pvParameters ); //宣告 Task2 void Taskprint( void *pvParameters ); //宣告 Taskprint void setup() { Serial.begin(9600); //設定串列埠鮑率為 9600 bps pinMode(9, OUTPUT); //數位接腳 9 連接至 LED1 pinMode(10, OUTPUT); //數位接腳 10 連接至 LED2 xTaskCreate(TaskBlink1,"Task1",128,NULL,1,NULL); //建立 Task1Blink1 任務 xTaskCreate(TaskBlink2,"Task2",128,NULL,1,NULL); //建立 Task1Blink2 任務 xTaskCreate(Taskprint,"Task3",128,NULL,1,NULL); //建立 Taskprint 任務 vTaskStartScheduler(); //對所有任務 Task 進行任務排程 } void loop() { } void TaskBlink1(void *pvParameters) //LED1 閃爍頻率 200ms { while(1) { digitalWrite(9, HIGH); //點亮 LED1 vTaskDelay( 200 / portTICK_PERIOD_MS ); //延遲 200ms digitalWrite(9, LOW); //關閉 LED1 Serial.println("Task1"); //列印 Task1 vTaskDelay( 200 / portTICK_PERIOD_MS ); //延遲 200ms } } void TaskBlink2(void *pvParameters) //LED2 閃爍頻率 500ms { while(1) { digitalWrite(10, HIGH); //點亮 LED2 vTaskDelay( 500 / portTICK_PERIOD_MS ); //延遲 500ms digitalWrite(10, LOW); //關閉 LED2 Serial.println("Task2"); //列印 Task2 vTaskDelay( 500 / portTICK_PERIOD_MS ); //延遲 500ms } } void Taskprint(void *pvParameters) //輸出任務運行狀況至 Serial Monitor 視窗 { int counter = 0; //循環計數 while(1) { counter++; Serial.println(counter); //列印循環計數值 vTaskDelay( 500 / portTICK_PERIOD_MS ); //延遲 500ms } }
☛ 說明
FreeRTOS 多任務程式基本結構說明如下:
⑴ 首先,包含 Arduino FreeRTOS 檔。
⑵ 宣告所有要執行任務的函數的函數原型。 如下所示:
void Task1( void *pvParameters ); void Task2( void *pvParameters );
⑶ 在 void setup() 函數中,創建任務並啟動任務調度器。 創建任務,在 setup 函數中使用某些參數調用 API 函數 xTaskCreate()。
xTaskCreate( TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask );
參數說明如下:
① pvTaskCode:它只是實現任務的函數的指標。
② pcName:任務的描述性名稱。 FreeRTOS 不使用此功能。 純粹是出於調試目的將其包括在內。
③ usStackDepth:每個任務都有自己的唯一堆棧,內核在創建任務時將其分配給任務。 該值指定堆疊可以容納的字數,而不是位元組數。 例如,如果堆棧為 32 位寬,並且 usStackDepth 作為 100 傳入,那麼將在 RAM 中分配 400 位元組的堆疊空間 ( 100 * 4 位元組 )。
④ pvParameters:任務輸入參數 ( 可以為 NULL )。
⑤ uxPriority:任務的優先順序 ( 0是最低優先順序 )。
⑥ pxCreatedTask:可用於向正在創建的任務傳遞句柄。 然後,可以使用此句柄在 API 呼叫中引用工作,例如,更改工作優先順序或刪除工作 ( 可以為 NULL )。
⑷ 創建任務后,在 setup 函數中使用 vTaskStartScheduler() 中啟動調度程式。 ( 注意:所有的設定宣告,必須要寫在此調度程式之前,否則不會生效 )。
⑸ loop() 函數將保持為空,因為任務執行現在由調度程序處理。
⑹ 現在,我們必須實現任務函數,並在這些函數內編寫要執行的邏輯。 函數名稱應與 xTaskCreate() 的第一個參數相同。
void task1(void *pvParameters) { while(1) { //put your task code here, to run repeatedly: } }uu
⑺ 大多數代碼都需要延遲函數來停止正在運行的任務,但是在 RTOS 中,不建議使用 Delay() 函數,因為它會停止 CPU,因此 RTOS 也將停止工作。 因此,FreeRTOS 具有內核API,可以在特定時間內阻止任務。
vTaskDelay( const TickType_t xTicksToDelay );
該 API 可用於延遲目的。 此 API 將任務延遲給定的滴答數。 任務保持阻塞的實際時間取決於滴答率。 常量 portTICK_PERIOD_MS 可用於根據滴答率計算即時性。 這意味著如果您想要 200ms 的延遲,只需如下編寫。
vTaskDelay( 200 / portTICK_PERIOD_MS );