Arduino 中的 FreeRTOS 佇列
佇列是一種資料結構,它有助於在不同的任務之間或在任務和中斷之間交換資料。它儲存有限數量的專案(在初始化時定義),並以 FIFO 模式執行。
我們將逐步講解 FreeRTOS 庫中的一個示例,以瞭解佇列。
您可以在以下位置找到示例:**檔案 → 示例 → FreeRTOS → StructQueue**。
在此程式碼中,兩個任務從不同的模擬引腳讀取模擬值,並將這些值傳遞到佇列中。另一個任務從佇列讀取值並將它們列印到序列埠監視器上。還有一個第四個閃爍任務與佇列無關,並行執行。
我們首先包含庫:
// Include Arduino FreeRTOS library #include <Arduino_FreeRTOS.h> // Include queue support #include <queue.h>
接下來,我們定義一個結構體,其中包含兩個整數,一個用於引腳編號,另一個用於引腳值。
// Define a struct struct pinRead { int pin; int value; };
然後,定義一個 **QueueHandle_t** 物件,稍後將在 Setup 中使用。
/* * Declaring a global variable of type QueueHandle_t * */ QueueHandle_t arrayQueue;
在 Setup 中,我們建立佇列並將其大小設定為 **10 個 pinRead 結構體**(它一次可以儲存 10 個這樣的結構體)。如果佇列建立正確,則建立 4 個任務。序列埠任務被賦予最高優先順序 (2),**兩個** **analogRead** 任務被賦予較低優先順序 (1),閃爍任務被賦予最低優先順序 (0)。迴圈中沒有任何操作。
void setup() { /** * Create a queue. * https://www.freertos.org/a00116.html */ structQueue = xQueueCreate(10, // Queue length sizeof(struct pinRead) // Queue item size ); if (structQueue != NULL) { // Create task that consumes the queue if it was created. xTaskCreate(TaskSerial, // Task function "Serial", // A name just for humans 128, // This stack size can be checked & adjusted by reading the Stack Highwater NULL, 2, // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest. NULL); // Create task that publish data in the queue if it was created. xTaskCreate(TaskAnalogReadPin0, // Task function "AnalogReadPin0", // Task name 128, // Stack size NULL, 1, // Priority NULL); // Create other task that publish data in the queue if it was created. xTaskCreate(TaskAnalogReadPin1, // Task function "AnalogReadPin1", // Task name 128, // Stack size NULL, 1, // Priority NULL); } xTaskCreate(TaskBlink, // Task function "Blink", // Task name 128, // Stack size NULL, 0, // Priority NULL ); } void loop() {}
接下來是兩個 **analogRead** 任務的定義。兩者非常相似。一個讀取 A0 引腳,另一個讀取 A1 引腳。每個任務填充一個 **pinRead** 結構體並將其新增到佇列中。**xQueueSend** 的第三個引數是應該等待佇列中有可用空間的最長時間。將其設定為 portMAX_DELAY,我們將使任務無限期地等待佇列中有可用空間。參見 https://www.freertos.org/a00117.html
/** * Analog read task for Pin A0 * Reads an analog input on pin 0 and send the readed value through the queue. * See Blink_AnalogRead example. */ void TaskAnalogReadPin0(void *pvParameters) { (void) pvParameters; for (;;) { // Read the input on analog pin 0: struct pinRead currentPinRead; currentPinRead.pin = 0; currentPinRead.value = analogRead(A0); /** * Post an item on a queue. * https://www.freertos.org/a00117.html */ xQueueSend(structQueue, ¤tPinRead, portMAX_DELAY); // One tick delay (15ms) in between reads for stability vTaskDelay(1); } } /** * Analog read task for Pin A1 * Reads an analog input on pin 1 and send the readed value through the queue. * See Blink_AnalogRead example. */ void TaskAnalogReadPin1(void *pvParameters) { (void) pvParameters; for (;;) { // Read the input on analog pin 1: struct pinRead currentPinRead; currentPinRead.pin = 1; currentPinRead.value = analogRead(A1); /** * Post an item on a queue. * https://www.freertos.org/a00117.html */ xQueueSend(structQueue, ¤tPinRead, portMAX_DELAY); // One tick delay (15ms) in between reads for stability vTaskDelay(1); } }
序列埠任務初始化序列埠,然後只要佇列中有專案,它就會將其讀入區域性結構體,然後在序列埠監視器上列印引腳編號和值。
void TaskSerial(void * pvParameters) { (void) pvParameters; // Init Arduino serial Serial.begin(9600); // Wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards. while (!Serial) { vTaskDelay(1); } for (;;) { struct pinRead currentPinRead; /** * Read an item from a queue. * https://www.freertos.org/a00118.html */ if (xQueueReceive(structQueue, ¤tPinRead, portMAX_DELAY) == pdPASS) { Serial.print("Pin: "); Serial.print(currentPinRead.pin); Serial.print(" Value: "); Serial.println(currentPinRead.value); } } }
閃爍任務並行執行,不使用佇列。
/* * Blink task. * See Blink_AnalogRead example. */ void TaskBlink(void *pvParameters) { (void) pvParameters; pinMode(LED_BUILTIN, OUTPUT); for (;;) { digitalWrite(LED_BUILTIN, HIGH); vTaskDelay( 250 / portTICK_PERIOD_MS ); digitalWrite(LED_BUILTIN, LOW); vTaskDelay( 250 / portTICK_PERIOD_MS ); } }