FreeRTOS深度解析:隊列集(Queue Sets)的原理與應用

FreeRTOS深度解析:隊列集(Queue Sets)的原理與應用

什么是隊列集?

在FreeRTOS中,隊列集(Queue Sets,英文名xQueueSet)是一種強大的數據結構,用于高效管理多個隊列。它的主要作用是讓任務能夠同時等待多個隊列中的消息,而不必單獨輪詢每個隊列。

隊列集本質上是多個隊列的集合,提供了一種便捷的方式來監視多個隊列,只要集合中的任何一個隊列收到消息,任務就能被喚醒并處理該消息。

為什么需要隊列集?

在多任務系統中,經常會出現一個任務需要從多個隊列接收數據的情況。讓我們通過一個實際場景來理解隊列集的必要性:

假設我們有一個溫濕度監控系統:

  • 任務1負責采集數據:將溫度數據發送到隊列A,將濕度數據發送到隊列B
  • 任務2需要處理這兩種數據:必須從隊列A和隊列B都讀取數據

傳統方法的問題

如果不使用隊列集,任務2需要分別讀取兩個隊列:

// 傳統方法:分別讀取兩個隊列
// 先嘗試讀取隊列A
if(xQueueReceive(queueA, &tempData, portMAX_DELAY) == pdTRUE) {// 處理溫度數據
}// 再嘗試讀取隊列B
if(xQueueReceive(queueB, &humidData, portMAX_DELAY) == pdTRUE) {// 處理濕度數據
}

這種方法存在嚴重問題:

  1. 阻塞問題:如果隊列A沒有數據,任務會阻塞在第一個xQueueReceive調用,即使隊列B中已有數據也無法處理
  2. 效率低下:需要編寫復雜的輪詢邏輯以避免阻塞
  3. 實時性差:無法保證及時處理所有可用數據

隊列集的解決方案

隊列集優雅地解決了上述問題。它將多個隊列組合成一個整體,任務只需監聽這個隊列集:

// 創建隊列集
QueueSetHandle_t queueSet = xQueueCreateSet(totalQueueSize);// 將隊列添加到隊列集
xQueueAddToSet(queueA, queueSet);
xQueueAddToSet(queueB, queueSet);// 在任務中等待任意隊列的數據
QueueSetMemberHandle_t activeMember = xQueueSelectFromSet(queueSet, portMAX_DELAY);// 判斷是哪個隊列收到了數據
if(activeMember == queueA) {xQueueReceive(queueA, &tempData, 0);// 處理溫度數據
} else if(activeMember == queueB) {xQueueReceive(queueB, &humidData, 0);// 處理濕度數據
}

隊列集的核心API函數

FreeRTOS提供了幾個關鍵函數來操作隊列集:

  1. xQueueCreateSet() - 創建一個新的隊列集

    QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength);
    
  2. xQueueAddToSet() - 將隊列添加到隊列集

    BaseType_t xQueueAddToSet(QueueHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet);
    
  3. xQueueRemoveFromSet() - 從隊列集中移除隊列

    BaseType_t xQueueRemoveFromSet(QueueHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet);
    
  4. xQueueSelectFromSet() - 等待并返回隊列集中有消息的隊列

    QueueSetMemberHandle_t xQueueSelectFromSet(QueueSetHandle_t xQueueSet, TickType_t xTicksToWait);
    
  5. xQueueSelectFromSetFromISR() - 中斷服務程序中使用的版本

    QueueSetMemberHandle_t xQueueSelectFromSetFromISR(QueueSetHandle_t xQueueSet);
    

隊列集的高級應用案例

隊列集不僅可以管理隊列,還可以管理信號量,讓我們看一個更復雜的應用場景:

假設我們有一個IoT設備,需要同時處理:

  • UART接收的數據(通過隊列)
  • 定時器觸發的采樣任務(通過二值信號量)
  • 外部中斷事件(通過計數信號量)

使用隊列集可以優雅地實現這一需求:

// 創建資源
QueueHandle_t uartQueue = xQueueCreate(10, sizeof(uint8_t));
SemaphoreHandle_t timerSem = xSemaphoreCreateBinary();
SemaphoreHandle_t extIntSem = xSemaphoreCreateCounting(10, 0);// 創建隊列集
QueueSetHandle_t iotQueueSet = xQueueCreateSet(10 + 1 + 10);// 添加到隊列集
xQueueAddToSet(uartQueue, iotQueueSet);
xQueueAddToSet(timerSem, iotQueueSet);
xQueueAddToSet(extIntSem, iotQueueSet);// 主任務處理
while(1) {QueueSetMemberHandle_t activeMember = xQueueSelectFromSet(iotQueueSet, portMAX_DELAY);if(activeMember == uartQueue) {// 處理UART數據uint8_t data;xQueueReceive(uartQueue, &data, 0);processUartData(data);} else if(activeMember == timerSem) {// 處理定時事件xSemaphoreTake(timerSem, 0);performScheduledSampling();}else if(activeMember == extIntSem) {// 處理外部中斷xSemaphoreTake(extIntSem, 0);handleExternalInterrupt();}
}

使用隊列集的注意事項

  1. 隊列集中的所有隊列/信號量必須為空才能被添加到隊列集中
  2. 隊列集的大小必須能夠容納所有成員隊列/信號量的總容量
  3. 不支持遞歸互斥量(Recursive Mutex)
  4. 在讀取到隊列集中有活動的隊列后,仍需調用相應的xQueueReceivexSemaphoreTake函數獲取實際數據

總結

隊列集是FreeRTOS中一個極其實用的功能,能有效提高代碼效率和系統響應性。它通過允許任務同時等待多個事件源,減少了代碼復雜度,避免了常見的阻塞陷阱,是開發復雜實時系統的得力助手。

如果想深入學習FreeRTOS和隊列集的更多高級用法,推薦訪問我的GitHub倉庫:https://github.com/Despacito0o/FreeRTOS,這里有從入門到精通的全面FreeRTOS學習資源,包括詳細的示例項目和中英雙語文檔!


如果您喜歡這篇文章,歡迎點贊、收藏和關注,您的支持是我創作的最大動力!有任何問題也歡迎在評論區留言交流!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/76890.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/76890.shtml
英文地址,請注明出處:http://en.pswp.cn/web/76890.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

QT creater和vs2017文件路徑問題

1. \\雙反斜杠,傳統寫法,需轉義 在 C/C 字符串中,\ 具有特殊含義,例如: \n 表示換行 \t 表示制表符 \" 表示雙引號 如果要表示一個真正的反斜杠,必須寫成 \\,否則編譯器會將其解釋為轉…

對流對象的理解

在c里,“流”可以理解為數據傳輸與操作的“介質”。 從輸入輸出角度來看,有輸入流(比如cin)和輸出流(cout)。對于輸入流,數據通過它從外部設備(例如鍵盤)“流入”程序內…

Visium HD多樣本拼片拆分

Visium HD實驗的時候一個捕獲區域內可以包含多個樣本拼片(例如多個組織切片或不同樣本的排列)是常見的實驗設計,多樣本拼片能夠提升實驗效率,單張玻片處理多個樣本,降低試劑和測序成本,后續分析的時候只需要…

進程(Process)詳解

進程(Process)詳解 一、基本定義 ?概念? 進程是計算機中程序的一次動態執行實例,包含程序代碼、數據及運行狀態,是操作系統進行資源分配和調度的基本單位?。與靜態的“程序”不同,進程是動態實體,隨程…

畢業論文超清pdf帶標簽導出

Word直接導出的pdf不夠清晰,使用打印導出的pdf又不帶書簽以及目錄跳轉功能這一問題,查閱網上資料使用Adobe DC似乎能夠解決但是下載安裝比較麻煩,于是寫了python程序解決該問題。 解決思路: 使用python腳本對兩個pdf文件進行合并…

NOIP2012提高組.同余方程

目錄 題目算法標簽: 數論, 擴展歐幾里得算法思路代碼 題目 203. 同余方程 算法標簽: 數論, 擴展歐幾里得算法 思路 簡單的擴展歐幾里得算法應用題, 擴展歐幾里得算法可以直接計算同余方程的通解, 因為求得是最小正整數解, 因此需要取模轉換為正整數 a x b y ≡ 1 ax by …

C++學習-入門到精通-【0】計算機和C++簡介

C學習-入門到精通-[0]計算機和C簡介 計算機和C簡介 C學習-入門到精通-[0]計算機和C簡介一、計算機的組成二、硬件和軟件三、數據的層次結構四、機器語言、匯編語言和高級語言五、C標準庫六、面向對象技術 一、計算機的組成 計算機是由多個不同功能的邏輯單元組成的&#xff1a…

macOS 系統設置息屏情況下,PHP等后臺腳本繼續執行

在 macOS 系統下,當屏幕息屏或合上蓋子時,后臺腳本程序是否會繼續運行,主要取決于以下幾個因素: 1. 系統睡眠狀態的影響 默認情況:合蓋/息屏后,Mac 會進入「睡眠模式」(部分硬件休眠&#xff…

SpringBoot集成ActiveMQ異常處理機制:若未捕獲異常,消息會被重新投遞

一、問題描述 SpringBoot項目集成AvtiveMQ,作為消息消費者。如果在消費消息的方法中,拋出異常,會產生什么效果? 二、ActiveMQ異常處理機制(AI問答僅供參考) 在Spring Boot項目集成ActiveMQ作為消息消費者…

【Java學習筆記】random的使用

random使用方法 使用說明&#xff1a;返回的是(0<n<1)這個范圍中的任意帶正號的double值 代碼實例 public class helloworld{public static void main(String[] args){System.out.println(Math.random());} }生成0-100中的任意數代碼示例 public class Main {public …

(三)垂直分庫架構、分布式數據庫

文章目錄 垂直分庫架構/分布式數據庫什么是垂直分庫架構架構模型優缺點優點缺點 技術案例分布式數據庫架構模型優缺點優點缺點 技術案例 垂直分庫架構/分布式數據庫 什么是垂直分庫架構 根據業務的模塊劃分&#xff0c; 將不同業務的數據放到不同的數據庫中。 比如一個電子商城…

數據結構線性表的順序存儲結構

線性表是由零個或多個數據元素組成的有序序列。 特點&#xff1a; 數據元素間是有順序的&#xff1b; 數據元素的個數是有限的&#xff1b; 一般來說&#xff0c;數據元素的類型是相同的&#xff08;強類型語言&#xff09;。c/c是強類型語言&#xff0c;必須指定數據類型。…

扣子空間試用:生成五一騎行規劃+notion文章編寫

今天試用了一下扣子空間&#xff0c;正好五一快到了&#xff0c;讓它幫忙做了五一騎行規劃&#xff0c;效果不賴&#xff01; 生成五一騎行規劃 點擊前往網站查看效果 prompt 如下&#xff1a; 幫我做一個五一上海騎行規劃 要求&#xff1a; - 風景優美 - 人少 - 100km總路程…

最新得物小程序sign簽名加密,請求參數解密,響應數據解密逆向分析

點擊精選&#xff0c;出現https://app.dewu.com/api/v1/h5/index/fire/index 這個請求 直接搜索sign的話不容易定位 直接搜newAdvForH5就一個&#xff0c;進去再搜sign&#xff0c;打上斷點 可以看到t.params就是沒有sign的請求參數&#xff0c; 經過Object(a.default)該函數…

在C#串口通信中,一發一收的場景,如何處理不同功能碼的幀數據比較合理,代碼結構好

在 C# 串口通信的一發一收場景里&#xff0c;處理不同功能碼的幀數據可采用以下合理的代碼結構&#xff0c;它能讓代碼更具可讀性、可維護性和可擴展性。 實現思路 定義幀結構&#xff1a;創建一個類來表示通信幀&#xff0c;其中包含功能碼、數據等信息。功能碼處理邏輯&…

【C++】vector擴容縮容

vector擴容縮容 1 擴容 一般來說&#xff0c;主要是重新分配內存 2 縮容 resize 縮小后&#xff0c;vector 的容量&#xff08;capacity()&#xff09;可能保持不變&#xff0c;需要顯式調用 shrink_to_fit() 來釋放內存。 驗證代碼&#xff1a; #include <vector>…

java中,線程的執行狀態有哪些

在 Java 里&#xff0c;線程有 6 種執行狀態&#xff0c;這些狀態都在 java.lang.Thread.State 枚舉類中被定義。下面為你詳細介紹這些狀態&#xff1a; 1. NEW&#xff08;新建狀態&#xff09; 當你創建了一個 Thread 對象&#xff0c;卻還未調用其 start() 方法時&#xf…

MATLAB 控制系統設計與仿真 - 41

魯棒控制的其他函數 - 回路成型函數 loopsyn 靈敏度問題由魯棒控制工具箱中的loopsyn就可以直接求解,該函數采用H無窮回路成型算法設計控制器,函數的調用格式為: [K,CL,gamma,info] = loopsyn(G,Gd) % G為受控對象模型% Gd為期望的回路傳遞函數% K為回路成型控制器模型% C…

查詢Hologres或postgresql中的數據

因Hologres使用postgresql的語法.所以兩者查詢一樣. 方案1: import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; import java.util.List;/*** 一個使用簡單連接池管理PostgreSQL連接的工具類。*/ publi…

OpenBayes 一周速覽|EasyControl 高效控制 DiT 架構,助力吉卜力風圖像一鍵生成;TripoSG 單圖秒變高保真 3D 模型

公共資源速遞 10 個教程&#xff1a; * 一鍵部署 R1-OneVision * UNO&#xff1a;通用定制化圖像生成 * TripoSG&#xff1a;單圖秒變高保真 3D * 使用 VASP 進行機器學習力場訓練 * InfiniteYou 高保真圖像生成 Demo * VenusFactory 蛋白質工程設計平臺 * Qwen2.5-0mni…