基於Arduino的RTOS入門


RTOS代表**即時作業系統**。它用於併發執行多個任務,按需排程任務,並使它們能夠共享資源。雖然本文不詳細介紹RTOS的細節,但我們將逐步講解一個示例,讓您對RTOS有一個大致瞭解。目前,您只需注意,RTOS 將幫助您在 Arduino 中執行多工處理,就像您計算機上的作業系統幫助您同時執行多個任務(例如撰寫郵件、收聽音樂等)一樣。

由於我們關注的是微控制器,我們將使用**FreeRTOS**,這是一個用於嵌入式裝置的RTOS。基本上,它設計得足夠小,可以支援微控制器。您可以在此處閱讀更多關於 FreeRTOS 的資訊:https://en.wikipedia.org/wiki/FreeRTOS

現在,要在Arduino上開始使用FreeRTOS,我們首先需要一個外部庫。轉到**工具 -> 管理庫**,然後搜尋**FreeRTOS**。

您將看到Richard Barry的庫。如前所述,它適用於**Uno**、**Nano**、**Leonardo**和**Mega**開發板。我們使用的是Uno開發板,因此我們將安裝此庫。

庫安裝完成後,您將能夠在**檔案 -> 示例**中看到與該庫相關的所有示例程式碼。

建議您仔細閱讀所有示例以進一步瞭解FreeRTOS。我們將逐步講解其中一個示例:**Blink_AnalogRead**。

如您所見,我們首先包含庫

#include <Arduino_FreeRTOS.h>

之後,我們宣告兩個任務:Blink任務和AnalogRead任務。

void TaskBlink( void *pvParameters );
void TaskAnalogRead( void *pvParameters );

請注意,它接收**pvParameters**指標作為輸入。我們稍後會再討論這一點。

接下來是重要的設定部分。

示例

// the setup function runs once when you press reset or power the board
void setup() {  
   // initialize serial communication at 9600 bits per second:
   Serial.begin(9600);  
   while (!Serial) {
      ; // wait for serial port to connect. Needed for native USB, on LEONARDO, MICRO, YUN, and other 32u4 based boards.
   }
   // Now set up two tasks to run independently.
   xTaskCreate(
      TaskBlink
      ,   "Blink"    // 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 );
   xTaskCreate(
      TaskAnalogRead
      ,   "AnalogRead"
      ,   128   // Stack size
      ,   NULL
      ,   1   // Priority
      ,   NULL
   );
   // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}

請注意此部分中的所有註釋。

我們首先初始化序列埠,然後等待其初始化。

然後,我們使用xTaskCreate建立任務。xTaskCreate的語法如下:

語法

BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,const char * const pcName,configSTACK_DEPTH_TYPE usStackDepth,void *pvParameters, UBaseType_t uxPriority,TaskHandle_t *pxCreatedTask);
  • **pvTaskCode**是執行任務的函式名稱(**TaskBlink**和**TaskAnalogRead**)。
  • **pcName**是任務的名稱(如註釋中所述,僅供人類參考)。
  • **usStackDepth**是分配給任務堆疊的字數。請參考您的開發板的資料手冊以確定一個字等於多少位元組。
  • **pvParameters**是要傳遞給已建立任務的引數。還記得在宣告任務時使用的**pvParameters**引數嗎?它們就是從這裡來的。例如,您想向任務傳遞數字1,可以透過將(void *) 1傳遞給**xTaskCreate**的**pvParameters**引數來實現。
  • **uxPriority**定義任務的優先順序。數字越大,優先順序越高。
  • **pxCreatedTask**是任務控制代碼。這是可選的,您可以傳入NULL。它的目的是在程式碼的其他部分引用任務。

建立任務後,如註釋中所述,任務排程程式會自動啟動。接下來,我們的迴圈為空,因為我們在任務中執行程式碼。

最後,定義了兩個任務的函式。

示例

void TaskBlink(void *pvParameters)   // This is a task.
{
   (void) pvParameters;

/*
   Blink
   Turns on an LED on for one second, then off for one second, repeatedly.
   Most Arduinos have an on-board LED you can control. On the UNO, LEONARDO, MEGA, and ZERO, it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN takes care of use the correct LED pin whatever is the board used.
   The MICRO does not have a LED_BUILTIN available. For the MICRO board please substitute the LED_BUILTIN definition with either LED_BUILTIN_RX or LED_BUILTIN_TX. e.g. pinMode(LED_BUILTIN_RX, OUTPUT); etc.
   If you want to know what pin the on-board LED is connected to on your Arduino model, check the Technical Specs of your board at https://www.arduino.cc/en/Main/Products
   
   This example code is in the public domain.
   modified 8 May 2014
   by Scott Fitzgerald
   modified 2 Sep 2016
   by Arturo Guadalupi
*/

   // initialize digital LED_BUILTIN on pin 13 as an output.
   pinMode(LED_BUILTIN, OUTPUT);

   for (;;) // A Task shall never return or exit.
   {
      digitalWrite(LED_BUILTIN, HIGH);    // turn the LED on (HIGH is the voltage level)
      vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
      digitalWrite(LED_BUILTIN, LOW);      // turn the LED off by making the voltage LOW
      vTaskDelay( 1000 / portTICK_PERIOD_MS ); // wait for one second
   }
}

void TaskAnalogRead(void *pvParameters)   // This is a task.
{
   (void) pvParameters;
   
/*
   AnalogReadSerial
   Reads an analog input on pin 0, prints the result to the serial monitor.
   Graphical representation is available using serial plotter (Tools > Serial Plotter menu)
   Attach the center pin of a potentiometer to pin A0, and the outside pins to +5V and ground.
   This example code is in the public domain.
*/

   for (;;)
   {
      // read the input on analog pin 0:
      int sensorValue = analogRead(A0);
      // print out the value you read:
      Serial.println(sensorValue);
      vTaskDelay(1);   // one tick delay (15ms) in between reads for stability
   }

任務中的註釋很好地解釋了程式碼。請注意,在任務中,我們使用任務中的**vTaskDelay()**代替**delay()**。**vTaskDelay(1)** 引入 1 個 tick 的延遲。1 個 tick 可能對應 1ms,也可能不對應。如**AnalogRead**任務的註釋中所述,1 個 tick 對應 15ms。這取決於開發板的時鐘頻率。為了獲得以毫秒為單位的延遲時間,我們可以將毫秒時間除以**portTICK_PERIOD_MS**常量。如**TaskBlink**中所做的那樣,1 秒的延遲透過以下命令實現:**vTaskDelay( 1000 / portTICK_PERIOD_MS );**

您可以在此處閱讀更多關於 freeRTOS 的資訊:https://www.freertos.org/

更新於:2021年3月24日

968 次瀏覽

開啟您的職業生涯

完成課程獲得認證

開始學習
廣告