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 );
   }
}

更新於:2021年7月30日

1K+ 次瀏覽

啟動您的 職業生涯

完成課程後獲得認證

開始
廣告