• 方案介紹
  • 附件下載
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

23.1.1-消息隊(duì)列的概念和函數(shù) FreeRTOS 項(xiàng)目 FreeRTOS學(xué)習(xí)筆記

02/16 08:24
1742
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

聯(lián)系方式.txt

共1個(gè)文件

這個(gè)是全網(wǎng)最詳細(xì)的STM32項(xiàng)目教學(xué)視頻。
第一篇CSDN文章在這里在這里:
75


STM32智能小車V3-STM32入門教程-openmv與STM32循跡小車-stm32f103c8t6-電賽 嵌入式學(xué)習(xí) PID控制算法 編碼器電機(jī) 跟隨

V3:HAL庫開發(fā)、手把手教學(xué)下面功能:PID速度控制、PID循跡、PID跟隨、遙控、避障、PID角度控制、openmv視覺控制、電磁循跡、FreeRTOS、K210視覺智能車(更新中)、K230視覺智能車(更新中)、MSPM0G3507視覺智能車(更新中)

在這里插入圖片描述

23.1.1-消息隊(duì)列的概念和函數(shù)

消息隊(duì)列概念

消息隊(duì)列簡稱隊(duì)列,是一種常用于任務(wù)間通信的數(shù)據(jù)結(jié)構(gòu)。

如下圖:消息隊(duì)列可以在任務(wù)與任務(wù)間、中斷與任務(wù)間傳遞消息,實(shí)現(xiàn)任務(wù)接收來自其它任務(wù)或中斷的不固定長度的消息。
在這里插入圖片描述
相比于裸機(jī)的全局?jǐn)?shù)組,使用消息隊(duì)列有如下優(yōu)勢:

  • 消息隊(duì)列具有超時(shí)機(jī)制,可以讓 FreeRTOS 內(nèi)核有效地管理任務(wù)。
  • 使用消息隊(duì)列可以防止多任務(wù)的訪問沖突、防止數(shù)據(jù)競爭 出現(xiàn)錯(cuò)誤.
  • 使用消息隊(duì)列可以有效地解決中斷服務(wù)程序與任務(wù)之間消息傳遞的問題,使用全局?jǐn)?shù)組的話,任務(wù)得不斷去監(jiān)測標(biāo)志位以獲取數(shù)據(jù)
  • 消息隊(duì)列具有FIFO與LIFO儲存機(jī)制,方便處理數(shù)據(jù)。

消息隊(duì)列的通信機(jī)制

消息隊(duì)列是一種異步的通信方式。

任務(wù)能夠從隊(duì)列中讀取消息,當(dāng)隊(duì)列中的消息為空時(shí),讀取消息的任務(wù)將被阻塞。用戶可以指定阻塞的任務(wù)時(shí)間 xTicksToWait,在這段時(shí)間中,如果隊(duì)列為空,該任務(wù)將保持阻塞狀態(tài)以等待隊(duì)列數(shù)據(jù)有效。當(dāng)隊(duì)列中有新消息時(shí),被阻塞的任務(wù)會被喚醒并處理新消息;當(dāng)?shù)却臅r(shí)間超過指定的阻塞時(shí)間,即使隊(duì)列中沒有有效數(shù)據(jù),任務(wù)也會自動從阻塞態(tài)轉(zhuǎn)為就緒態(tài)。

通過消息隊(duì)列服務(wù),任務(wù)或中斷服務(wù)可以將一條或多條消息放入消息隊(duì)列中。同樣,一個(gè)或多個(gè)任務(wù)可以從消息隊(duì)列中獲得消息。當(dāng)有多個(gè)消息發(fā)送到消息隊(duì)列時(shí),通常是將先進(jìn)入消息隊(duì)列的消息先傳給任務(wù),也就是說,任務(wù)先得到的是最先進(jìn)入消息隊(duì)列的消息,即先進(jìn)先出原則(FIFO),F(xiàn)reeRTOS的隊(duì)列也支持后進(jìn)先出原則(LIFO)。

FreeRTOS中消息隊(duì)列特性

  • 消息支持先進(jìn)先出方式排隊(duì),支持異步讀寫工作方式
  • 讀寫隊(duì)列均支持超時(shí)機(jī)制
  • 消息支持后進(jìn)先出方式排隊(duì),向隊(duì)首發(fā)送消息(LIFO)
  • 可以允許不同長度(不超過隊(duì)列節(jié)點(diǎn)最大值)的任意類型消息
  • 一個(gè)任務(wù)能夠從任意一個(gè)消息隊(duì)列接收和發(fā)送消息
  • 多個(gè)任務(wù)能夠從同一個(gè)消息隊(duì)列接收和發(fā)送消息
  • 當(dāng)隊(duì)列使用結(jié)束后,可以通過刪除隊(duì)列函數(shù)進(jìn)行刪除

消息隊(duì)列應(yīng)用場景

消息隊(duì)列可用于發(fā)送不定長消息的場合。

隊(duì)列是FreeRTOS 主要的任務(wù)間通信方式,可以在任務(wù)與任務(wù)間、中斷和任務(wù)間傳送信息,發(fā)送到隊(duì)列的消息是通過復(fù)制方式實(shí)現(xiàn)的,這意味著隊(duì)列存儲的數(shù)據(jù)是原始數(shù)據(jù),而不是原始數(shù)據(jù)的引用。

消息隊(duì)列的常用API函數(shù)

創(chuàng)建消息隊(duì)列

xQueueCreate():

QueueHandle_t xQueueCreate( 
    UBaseType_t uxQueueLength, //隊(duì)列的最大長度,表示隊(duì)列可以容納的元素個(gè)數(shù)。
    UBaseType_t uxItemSize //隊(duì)列中每個(gè)元素的大?。ㄒ宰止?jié)為單位)。即每個(gè)元素占用的內(nèi)存空間??梢允侨魏螖?shù)據(jù)類型的大小,例如 sizeof(int)、sizeof(char) 等。
);
QueueHandle_t 返回值:
成功:返回隊(duì)列句柄(QueueHandle_t),這個(gè)句柄將用于后續(xù)的隊(duì)列操作(如發(fā)送和接收數(shù)據(jù))。
失敗:如果創(chuàng)建隊(duì)列失敗,返回 NULL。       
任務(wù)中向隊(duì)列發(fā)送數(shù)據(jù)-不會覆蓋原有數(shù)據(jù)

xQueueSend() :

A

BaseType_t xQueueSend( 
    QueueHandle_t xQueue, //隊(duì)列句柄,表示你要操作的隊(duì)列。
    const void * pvItemToQueue, //指向要發(fā)送到隊(duì)列的數(shù)據(jù)的指針。數(shù)據(jù)會被復(fù)制到隊(duì)列中。
    TickType_t xTicksToWait //等待隊(duì)列空間的時(shí)間。如果隊(duì)列滿了,xQueueSend 會等待空閑空間。此值可以是 0 表示非阻塞操作,portMAX_DELAY 表示無限等待,或者其他自定義的等待時(shí)間。
);
BaseType_t 返回值:
pdPASS:成功將數(shù)據(jù)發(fā)送到隊(duì)列。
errQUEUE_FULL:隊(duì)列已滿,無法立即放入數(shù)據(jù)。如果 xTicksToWait 設(shè)置為 0,則是非阻塞的,隊(duì)列滿時(shí)返回 errQUEUE_FULL。
errQUEUE_BLOCKED:如果隊(duì)列滿且設(shè)置了阻塞時(shí)間,任務(wù)會被阻塞直到有空間。                     
任務(wù)中向隊(duì)列發(fā)送數(shù)據(jù)-會強(qiáng)制覆蓋原有數(shù)據(jù)
BaseType_t xQueueOverwrite( QueueHandle_t xQueue,       //隊(duì)列句柄
                           const void *pvItemToQueue    //要發(fā)送到隊(duì)列的數(shù)據(jù)指針
                          );

函數(shù)作用:函數(shù)會強(qiáng)制將新數(shù)據(jù)寫入隊(duì)列,并覆蓋隊(duì)列中原有的元素。
返回值:
如果操作成功,返回 pdPASS。
如果隊(duì)列為空或出現(xiàn)其他錯(cuò)誤,返回 errQUEUE_FULL。
任務(wù)中接收隊(duì)列數(shù)據(jù)-會從隊(duì)列中移除該數(shù)據(jù)

xQueueReceive():

BaseType_t xQueueReceive( 
    QueueHandle_t xQueue, //要接收數(shù)據(jù)的隊(duì)列句柄。這個(gè)句柄是在創(chuàng)建隊(duì)列時(shí)由 xQueueCreate() 返回的。它標(biāo)識了隊(duì)列。
    void * const pvBuffer, //指向接收數(shù)據(jù)存儲位置的指針。數(shù)據(jù)將被放置到這個(gè)緩沖區(qū)中,緩沖區(qū)的大小應(yīng)當(dāng)足夠存儲隊(duì)列中每個(gè)消息的內(nèi)容。
    TickType_t xTicksToWait//指定任務(wù)在隊(duì)列中沒有數(shù)據(jù)時(shí)應(yīng)該等待的時(shí)間,單位是 FreeRTOS 系統(tǒng)中的“滴答”(tick)。如果設(shè)置為 0,則表示不等待,隊(duì)列為空時(shí) xQueueReceive() 將立即返回。如果設(shè)置為 portMAX_DELAY,表示無限期等待,直到隊(duì)列中有數(shù)據(jù)。
);

返回值:
pdPASS:
如果成功從隊(duì)列接收數(shù)據(jù),返回 pdPASS(即 1)。
errQUEUE_EMPTY:
如果隊(duì)列為空且任務(wù)設(shè)置的等待時(shí)間為 0,或者任務(wù)等待超時(shí),返回 errQUEUE_EMPTY(即 0)。
任務(wù)中接收隊(duì)列數(shù)據(jù)-但不會將數(shù)據(jù)移除
BaseType_t xQueuePeek( QueueHandle_t xQueue,//這是隊(duì)列的句柄,指向你想要查看的隊(duì)列。隊(duì)列句柄是通過 xQueueCreate() 創(chuàng)建隊(duì)列時(shí)獲得的。
                      void * pvBuffer, //這是一個(gè)指向接收數(shù)據(jù)的緩沖區(qū)的指針,隊(duì)列中的數(shù)據(jù)會被復(fù)制到這個(gè)緩沖區(qū)。注意,數(shù)據(jù)將從隊(duì)列復(fù)制到該緩沖區(qū)中,但不會刪除隊(duì)列中的數(shù)據(jù)。
                      TickType_t xTicksToWait //如果隊(duì)列為空,xQueuePeek() 會阻塞直到隊(duì)列中有數(shù)據(jù)可用。如果 xTicksToWait 為 0,表示函數(shù)不會阻塞(即,如果隊(duì)列為空,函數(shù)會立即返回)。如果為 portMAX_DELAY,則函數(shù)會一直等待,直到隊(duì)列有數(shù)據(jù)可用。
                     );

返回值
pdPASS:如果成功地從隊(duì)列中“查看”到數(shù)據(jù),則返回 pdPASS。
errQUEUE_EMPTY:如果隊(duì)列為空且 xTicksToWait 為 0,表示沒有數(shù)據(jù)可查看,函數(shù)將返回 errQUEUE_EMPTY。
其他返回值:在發(fā)生錯(cuò)誤時(shí),可能會返回其他錯(cuò)誤碼。
    
如果隊(duì)列為空, xQueuePeek() 會阻塞直到隊(duì)列中有數(shù)據(jù)可用。如果 xTicksToWait 為 0,表示函數(shù)不會阻塞(即,如果隊(duì)列為空,函數(shù)會立即返回)。如果為 portMAX_DELAY,則函數(shù)會一直等待,直到隊(duì)列有數(shù)據(jù)可用。
中斷中向隊(duì)列發(fā)送數(shù)據(jù)-不會覆蓋原有數(shù)據(jù)

xQueueSendFromISR():

BaseType_t xQueueSendFromISR(
    QueueHandle_t xQueue,         // 要發(fā)送數(shù)據(jù)的隊(duì)列句柄
    const void * pvItemToQueue,   // 指向要發(fā)送的數(shù)據(jù)的指針
    BaseType_t * pxHigherPriorityTaskWoken // 用于指示是否喚醒了更高優(yōu)先級的任務(wù)
);

**返回值**

- **`pdPASS`**: 表示隊(duì)列成功接收數(shù)據(jù)并且返回成功。
- **`errQUEUE_FULL`**: 表示隊(duì)列已滿,無法發(fā)送數(shù)據(jù)到隊(duì)列中。
    
在 FreeRTOS 中,默認(rèn)情況下, xQueueSendFromISR() 會根據(jù)隊(duì)列是否已滿來判斷是否將數(shù)據(jù)寫入隊(duì)列。如果隊(duì)列已經(jīng)滿了,并且沒有使用 隊(duì)列覆蓋機(jī)制,它會返回 errQUEUE_FULL,并且數(shù)據(jù)不會被寫入隊(duì)列。如果希望強(qiáng)制寫入隊(duì)列使用 xQueueOverwriteFromISR()
中斷中向隊(duì)列發(fā)送數(shù)據(jù)-會且強(qiáng)制覆蓋原有數(shù)據(jù)
BaseType_t xQueueOverwriteFromISR(
    QueueHandle_t xQueue,                  //要操作的隊(duì)列句柄(通過 xQueueCreate() 創(chuàng)建)。
    const void *pvItemToQueue,			   //指向要發(fā)送到隊(duì)列的數(shù)據(jù)的指針。數(shù)據(jù)的大小由創(chuàng)建隊(duì)列時(shí)指定的大?。╱xItemSize)決定。
    BaseType_t *pxHigherPriorityTaskWoken   // 用于指示是否需要任務(wù)切換的標(biāo)志
);
BaseType_t  返回值
pdPASS:表示數(shù)據(jù)已成功寫入隊(duì)列(覆蓋舊數(shù)據(jù))。
此函數(shù)沒有返回 errQUEUE_FULL,因?yàn)樗偸菚采w數(shù)據(jù),即使隊(duì)列已滿。
    
FreeRTOS 中的一個(gè)特殊隊(duì)列操作函數(shù),專門用于在 中斷服務(wù)例程(ISR)中 向隊(duì)列寫入數(shù)據(jù),并 強(qiáng)制覆蓋隊(duì)列中的現(xiàn)有數(shù)據(jù)。也就是在隊(duì)列已經(jīng)滿的時(shí)候依舊可以寫入最新數(shù)據(jù)。
中斷中從隊(duì)列接收數(shù)據(jù)-會從隊(duì)列中移除該數(shù)據(jù)

**xQueueReceiveFromISR(): **

BaseType_t xQueueReceiveFromISR(
    QueueHandle_t xQueue,                    // 要從中接收數(shù)據(jù)的隊(duì)列句柄
    void * const pvBuffer,                   // 用于存儲接收到的數(shù)據(jù)的緩沖區(qū)
    BaseType_t * const pxHigherPriorityTaskWoken // 用于指示是否需要任務(wù)切換的標(biāo)志
);

返回值:

- **`pdPASS`**:表示從隊(duì)列成功接收到數(shù)據(jù)。
- **`errQUEUE_EMPTY`**:表示隊(duì)列為空,沒有數(shù)據(jù)可以接收。

xQueueReceiveFromISR() 在 接收數(shù)據(jù)時(shí)會 接收完數(shù)據(jù)后,會將該數(shù)據(jù)移除
中斷中從隊(duì)列接收數(shù)據(jù)-但不移除該數(shù)據(jù)
BaseType_t xQueuePeekFromISR( 
    QueueHandle_t xQueue,                //隊(duì)列的句柄,指定你要從中讀取數(shù)據(jù)的隊(duì)列
    void *pvBuffer, 	                //指向存儲接收數(shù)據(jù)的緩沖區(qū)的指針。接收到的數(shù)據(jù)會存放在這里,但不會從隊(duì)列中移除。
    BaseType_t *pxHigherPriorityTaskWoken //指向 BaseType_t 類型的變量,標(biāo)記是否有高優(yōu)先級任務(wù)被喚醒。如果在調(diào)用過程中有高優(yōu)先級任務(wù)就緒,F(xiàn)reeRTOS 會根據(jù)這個(gè)標(biāo)志決定是否進(jìn)行任務(wù)切換。
);
xQueuePeekFromISR() 從隊(duì)列中讀取數(shù)據(jù),但 不移除數(shù)據(jù)。這意味著即使讀取了隊(duì)列中的數(shù)據(jù),隊(duì)列中原來的數(shù)據(jù)仍然保留,其他任務(wù)或中斷可以繼續(xù)讀取隊(duì)列中的數(shù)據(jù)。
返回值:
pdPASS:表示成功接收到數(shù)據(jù)。
errQUEUE_EMPTY:表示隊(duì)列為空,沒有接收到任何數(shù)據(jù)。

 

  • 聯(lián)系方式.txt
    下載

相關(guān)推薦

方案定制

去合作
方案開發(fā)定制化,2000+方案商即時(shí)響應(yīng)!