Skip to main content

STM32 RTOS 系列教學 - 第六篇:RTOS Queue 任務間資料傳輸實作

STM32 RTOS 系列教學 - 第六篇:RTOS Queue 任務間資料傳輸實作

🎯 教學目標

  • 理解 RTOS 中 Queue(佇列)的用途與特性
  • 學會在任務之間安全地傳遞資料
  • 使用 Queue 實作一個簡單的生產者-消費者範例

📦 Queue 是什麼?

Queue(佇列)是一種資料結構,可在 RTOS 中讓任務之間以 FIFO(先進先出)方式安全交換資料。每個任務可以是資料的「生產者」或「消費者」。

📌 特性

  • 支援固定長度的訊息資料(byte 或結構)
  • 多任務可同時傳送(Send)與接收(Receive)資料
  • 有 blocking / timeout 功能,等待 Queue 可用

🛠 STM32CubeMX 設定 Queue

Step 1:新增 Queue

  • 開啟 Middleware > FreeRTOS > CMSIS RTOS v2
  • 新增 Message Queue,命名為 myQueue01
  • 設定:
    • 資料長度:sizeof(uint16_t) 或自訂 struct
    • Queue 長度:例如 10(最多可存放 10 筆資料)

Step 2:取得 Handle 並初始化

osMessageQueueId_t myQueue01Handle;

const osMessageQueueAttr_t myQueue01_attributes = {
  .name = "myQueue01"
};
myQueue01Handle = osMessageQueueNew(10, sizeof(uint16_t), &myQueue01_attributes);

🧪 範例:數值傳送與接收

任務 A(傳送端) - 每秒傳送一個數字:

void StartSenderTask(void *argument)
{
  uint16_t value = 0;
  for(;;)
  {
    osMessageQueuePut(myQueue01Handle, &value, 0, 0);
    value++;
    osDelay(1000);
  }
}

任務 B(接收端) - 接收後印出數值:

void StartReceiverTask(void *argument)
{
  uint16_t recvVal;
  for(;;)
  {
    if(osMessageQueueGet(myQueue01Handle, &recvVal, NULL, osWaitForever) == osOK)
    {
      printf("Received: %d\n", recvVal);
    }
  }
}

🧠 應用場景

  • 任務間傳送 sensor 資料
  • 接收中斷服務程式的資料(需透過中斷內部觸發任務)
  • 排程控制命令、狀態

✅ 成功條件檢查

  • 每秒有數值被傳送與接收
  • 無資料遺失(Queue 空間足夠)
  • 接收順序正確(FIFO)

🧩 下一篇預告

第 7 篇:RTOS Timer 與軟體定時器應用