色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

嵌入式環形隊列和消息隊列的實現

CHANBAEK ? 來源:南山府嵌入式 ? 作者:編外人員 ? 2023-04-14 11:52 ? 次閱讀

說明

嵌入式環形隊列和消息隊列是實現數據緩存和通信的常見數據結構,廣泛應用于嵌入式系統中的通信協議和領域。

環形隊列是一種先進先出(FIFO)的數據結構,其中數據被存儲在一個環形緩沖區中。 它使用兩個指針,分別指向隊列的頭和尾,以便在讀寫操作時追蹤隊列的狀態。 當隊列滿時,新數據將覆蓋舊數據,以確保隊列的長度保持不變。 環形隊列在實現嵌入式通信協議時特別有用,例如UARTCAN等。

消息隊列是一種多個發送者和接收者之間共享數據的通信機制。 它允許多個任務或線程向隊列發送消息,并允許多個任務或線程從隊列中接收消息。 每個消息都有一個固定的大小和格式,并可以根據需要進行排隊和檢索。 在嵌入式系統中,消息隊列廣泛用于處理異步事件,例如中斷處理和任務之間的通信。

主要應用于:

  1. 網絡通信協議(例如TCP/IP,UDP等)中的數據緩存和隊列管理。
  2. 嵌入式操作系統(例如FreeRTOS,uC/OS等)中的任務通信和事件處理。
  3. 汽車電子領域中的CAN和LIN通信協議。
  4. 工業自動化領域中的Modbus,Profibus等通信協議。
  5. 無線通信領域中的藍牙ZigbeeLoRa等通信協議。

大致應用

  1. 串口通信中,可以使用環形隊列來接收和發送數據。 當接收到新的數據時,將其存儲到環形隊列中,并在需要發送數據時從隊列中取出數據發送。 這種方式可以減少中斷處理的時間,提高系統的響應速度。
  2. 多任務系統中,消息隊列用于任務之間的通信。 每個任務都可以向消息隊列中發送消息,其他任務可以從隊列中獲取消息并進行相應的處理。 這種方式可以實現任務之間的解耦,提高系統的可擴展性和可維護性。
  3. 實時控制系統中,環形隊列可以用于緩存傳感器數據或控制命令。 當傳感器或其他設備向系統發送數據時,可以將其存儲到環形隊列中,然后由控制任務從隊列中獲取數據并進行相應的處理。 這種方式可以減少系統對硬件的依賴性,提高系統的靈活性和可靠性。
  4. 音頻處理中,環形隊列可以用于實現音頻數據的緩存。 當音頻數據輸入時,將其存儲到環形隊列中,然后由音頻處理任務從隊列中獲取數據并進行處理。 這種方式可以實現音頻數據的流式處理,提高系統的處理效率和響應速度。

嵌入式環形隊列

嵌入式環形隊列是一種先進先出(FIFO)的隊列,其實現基于環形緩沖區。 隊列的頭尾指針分別指向隊列的第一個元素和最后一個元素,當隊列滿時,新加入的元素將覆蓋隊列頭的元素。 嵌入式環形隊列的實現過程如下:

  1. 隊列初始化:初始化頭尾指針為0,表示隊列為空。
  2. 入隊操作:將元素插入隊列尾部,尾指針加1,如果隊列滿了,則尾指針回到隊列開頭,覆蓋頭指針所指向的元素。
  3. 出隊操作:將隊列頭部元素出隊,并將頭指針加1,如果隊列已經空了,則頭指針回到隊列開頭。

嵌入式環形隊列的實現可以使用數組或鏈表來實現。 使用數組時,需要考慮隊列滿時需要覆蓋隊列頭的元素,所以需要額外的邏輯來保證正確性。

嵌入式環形隊列操作步驟(大致如此)

1)定義一個固定大小的數組

1#define QUEUE_SIZE 10
2int queue[QUEUE_SIZE];

2)定義兩個指針,分別指向隊列的起始位置和末尾位置

1int head = 0;  // 隊列起始位置
2int tail = 0;  // 隊列末尾位置

3)實現入隊操作,即將元素添加到隊列末尾。 如果隊列已滿,則不能再添加元素

1void enqueue(int data) {
2    if ((tail + 1) % QUEUE_SIZE == head) {
3        // 隊列已滿
4        return;
5    }
6    queue[tail] = data;
7    tail = (tail + 1) % QUEUE_SIZE;
8}

4)實現出隊操作,即將隊列中的元素刪除并返回。 如果隊列為空,則不能執行出隊操作。

1int dequeue() {
2    if (head == tail) {
3        // 隊列為空
4        return -1;
5    }
6    int data = queue[head];
7    head = (head + 1) % QUEUE_SIZE;
8    return data;
9}

5)實現查詢隊列大小的函數

1int queue_size() {
2    return (tail - head + QUEUE_SIZE) % QUEUE_SIZE;
3}

完整代碼實現

1#define QUEUE_SIZE 10
 2int queue[QUEUE_SIZE];
 3int head = 0;
 4int tail = 0;
 5
 6void enqueue(int data) {
 7    if ((tail + 1) % QUEUE_SIZE == head) {
 8        // 隊列已滿
 9        return;
10    }
11    queue[tail] = data;
12    tail = (tail + 1) % QUEUE_SIZE;
13}
14
15int dequeue() {
16    if (head == tail) {
17        // 隊列為空
18        return -1;
19    }
20    int data = queue[head];
21    head = (head + 1) % QUEUE_SIZE;
22    return data;
23}
24
25int queue_size() {
26    return (tail - head + QUEUE_SIZE) % QUEUE_SIZE;
27}

嵌入式消息隊列

嵌入式消息隊列的實現原理

嵌入式消息隊列通常采用循環緩沖區實現,即使用一個數組作為緩沖區,通過頭指針和尾指針來管理隊列。 消息隊列的基本操作包括入隊和出隊

入隊操作

入隊操作將一個消息寫入隊列中,實現方法如下:

1void queue_push(queue_t *queue, void *data, size_t size)
 2{
 3    uint32_t next = (queue->tail + 1) % queue->capacity;
 4
 5    if (next == queue->head) {
 6        // 隊列已滿,不再添加數據
 7        return;
 8    }
 9
10    queue_item_t *item = &queue->items[queue->tail];
11    item->size = size;
12    item->data = malloc(size);
13    memcpy(item->data, data, size);
14
15    queue->tail = next;
16}

在入隊操作中,我們首先檢查隊列是否已滿。 如果隊列已滿,就直接返回,不再添加數據。 如果隊列未滿,則使用尾指針指向的空間來存儲新的數據。 為了避免新的數據覆蓋舊的數據,我們需要動態分配一個新的內存空間,將數據復制到該空間中,并將其地址存儲到隊列的元素中。 最后,我們將尾指針往后移動一個位置。

出隊操作

出隊操作將一個消息從隊列中讀取出來,并將其從隊列中刪除,實現方法如下

1void queue_pop(queue_t *queue, void *data, size_t *size)
 2{
 3    if (queue->head == queue->tail) {
 4        // 隊列為空,無法讀取數據
 5        return;
 6    }
 7
 8    queue_item_t *item = &queue->items[queue->head];
 9    *size = item->size;
10    memcpy(data, item->data, *size);
11
12    free(item->data);
13    queue->head = (queue->head + 1) % queue->capacity;
14}

在出隊操作中,我們首先檢查隊列是否為空。 如果隊列為空,就直接返回,無法讀取數據。 如果隊列非空,則使用頭指針指向的空間來讀取數據。 我們將元素中存儲的數據復制到指定的地址中,并返回數據的大小。 最后,我們釋放元素中分配的內存空間,并將頭指針往后移動一個位置。

消息示例:

1#include 
  2#include 
  3#include 
  4
  5// 消息隊列結構體
  6typedef struct {
  7    uint8_t *buf;    // 指向隊列緩存區的指針
  8    uint32_t head;   // 隊頭指針
  9    uint32_t tail;   // 隊尾指針
 10    uint32_t size;   // 隊列容量
 11    uint32_t count;  // 當前隊列中的消息數量
 12} message_queue_t;
 13
 14// 創建一個消息隊列
 15message_queue_t *message_queue_create(uint32_t size) {
 16    message_queue_t *mq = (message_queue_t *)malloc(sizeof(message_queue_t));
 17    if (mq == NULL) {
 18        return NULL;
 19    }
 20
 21    mq->buf = (uint8_t *)malloc(size);
 22    if (mq->buf == NULL) {
 23        free(mq);
 24        return NULL;
 25    }
 26
 27    mq->head = 0;
 28    mq->tail = 0;
 29    mq->size = size;
 30    mq->count = 0;
 31
 32    return mq;
 33}
 34
 35// 銷毀一個消息隊列
 36void message_queue_destroy(message_queue_t *mq) {
 37    if (mq == NULL) {
 38        return;
 39    }
 40
 41    if (mq->buf != NULL) {
 42        free(mq->buf);
 43    }
 44
 45    free(mq);
 46}
 47
 48// 向消息隊列中發送一條消息
 49uint32_t message_queue_send(message_queue_t *mq, uint8_t *buf, uint32_t len) {
 50    if (mq == NULL || buf == NULL || len == 0) {
 51        return 0;
 52    }
 53
 54    // 如果隊列已滿,則無法發送消息
 55    if (mq->count >= mq->size) {
 56        return 0;
 57    }
 58
 59    // 將消息寫入隊列緩存區
 60    uint32_t i;
 61    for (i = 0; i < len; i++) {
 62        mq->buf[mq->tail] = buf[i];
 63        mq->tail = (mq->tail + 1) % mq->size;
 64    }
 65
 66    // 更新隊列狀態
 67    mq->count += len;
 68
 69    return len;
 70}
 71
 72// 從消息隊列中接收一條消息
 73uint32_t message_queue_recv(message_queue_t *mq, uint8_t *buf, uint32_t len) {
 74    if (mq == NULL || buf == NULL || len == 0) {
 75        return 0;
 76    }
 77
 78    // 如果隊列為空,則無法接收消息
 79    if (mq->count == 0) {
 80        return 0;
 81    }
 82
 83    // 讀取隊列緩存區中的消息
 84    uint32_t i;
 85    for (i = 0; i < len && i < mq->count; i++) {
 86        buf[i] = mq->buf[mq->head];
 87        mq->head = (mq->head + 1) % mq->size;
 88    }
 89
 90    // 更新隊列狀態
 91    mq->count -= i;
 92
 93    return i;
 94}
 95
 96// 獲取消息隊列中的消息數量
 97uint32_t message_queue_count(message_queue_t *mq) {
 98    if (mq == NULL) {
 99        return 0;
100    }
101
102    return mq->count;
103}

消息隊列示例說明

上面的示例是一個基于循環隊列實現的簡單嵌入式消息隊列的代碼實現,下面詳細說明其實現原理:

消息隊列結構體

定義一個消息隊列結構體,包含隊列緩存區指針、隊頭指針、隊尾指針、隊列容量和當前隊列中的消息數量等信息

1typedef struct {
2    uint8_t *buf;    // 指向隊列緩存區的指針
3    uint32_t head;   // 隊頭指針
4    uint32_t tail;   // 隊尾指針
5    uint32_t size;   // 隊列容量
6    uint32_t count;  // 當前隊列中的消息數量
7} message_queue_t;

創建消息隊列

使用 message_queue_create 函數創建一個消息隊列,該函數會動態分配一塊內存用于存儲消息隊列結構體和隊列緩存區,初始化消息隊列的各個參數,并返回一個指向消息隊列結構體的指針。

1message_queue_t *message_queue_create(uint32_t size) {
 2    message_queue_t *mq = (message_queue_t *)malloc(sizeof(message_queue_t));
 3    if (mq == NULL) {
 4        return NULL;
 5    }
 6
 7    mq->buf = (uint8_t *)malloc(size);
 8    if (mq->buf == NULL) {
 9        free(mq);
10        return NULL;
11    }
12
13    mq->head = 0;
14    mq->tail = 0;
15    mq->size = size;
16    mq->count = 0;
17
18    return mq;
19}

銷毀消息隊列

使用 message_queue_destroy 函數銷毀一個消息隊列,該函數會釋放消息隊列結構體和隊列緩存區所占用的內存。

1void message_queue_destroy(message_queue_t *mq) {
 2    if (mq == NULL) {
 3        return;
 4    }
 5
 6    if (mq->buf != NULL) {
 7        free(mq->buf);
 8    }
 9
10    free(mq);
11}

發送消息

使用 message_queue_send 函數向消息隊列中發送一條消息,該函數會將消息寫入隊列緩存區,并更新隊列的狀態,返回實際寫入隊列緩存區的消息長度。

1uint32_t message_queue_send(message_queue_t *mq, uint8_t *buf, uint32_t len) {
 2    if (mq == NULL || buf == NULL || len == 0) {
 3        return 0;
 4    }
 5
 6    // 如果隊列已滿,則無法發送消息
 7    if (mq->count >= mq->size) {
 8        return 0;
 9    }
10
11    // 將消息寫入隊列緩存區
12    uint32_t i;
13    for (i = 0; i < len; i++) {
14        mq->buf[mq->tail] = buf[i];
15        mq->tail = (mq->tail + 1) % mq->size;
16    }
17
18    // 更新隊列狀態
19    mq->count += len;
20
21    return len;
22}
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 嵌入式
    +關注

    關注

    5082

    文章

    19104

    瀏覽量

    304822
  • TCP
    TCP
    +關注

    關注

    8

    文章

    1353

    瀏覽量

    79055
  • 數據結構
    +關注

    關注

    3

    文章

    573

    瀏覽量

    40123
  • 隊列
    +關注

    關注

    1

    文章

    46

    瀏覽量

    10893
  • 消息隊列
    +關注

    關注

    0

    文章

    33

    瀏覽量

    2972
收藏 人收藏

    評論

    相關推薦

    嵌入式開發中消息隊列實現

    嵌入式開發中經常會看到消息隊列的身影,隊列的應用是很廣泛的,它可以應用的場景有很多,比如緩存通信消息,暫存執行內容,數據順序轉發等的操作。
    發表于 08-22 11:19 ?1193次閱讀
    <b class='flag-5'>嵌入式</b>開發中消息<b class='flag-5'>隊列</b>的<b class='flag-5'>實現</b>

    基于STM32的串口環形隊列IAP調試

    基于STM32的串口環形隊列IAP調試心得
    的頭像 發表于 09-18 15:33 ?1532次閱讀
    基于STM32的串口<b class='flag-5'>環形</b><b class='flag-5'>隊列</b>IAP調試

    環形隊列在串口數據接收中的使用

    前言??書接上回,前文主要介紹了環形隊列實現原理以及C語言實現及測試過程,本文將回歸到嵌入式平臺的應用中,話不多說,淦,上干貨!實驗目的H
    發表于 12-06 06:27

    如何使用隊列實現STM32串口環形緩沖?

    串口環形緩沖的好處是什么?如何使用隊列實現STM32串口環形緩沖?
    發表于 12-07 07:13

    嵌入式軟件中的隊列有何特點

    數據結構之隊列篇1 隊列之特點及在嵌入式軟件中的應用隊列(queue)是一個簡單線性表,它是一個允許在一端進行插入操作,而在另一端進行刪除操作的線性表。
    發表于 12-21 07:28

    實現隊列環形緩沖的方法

    串口隊列環形緩沖區隊列串口環形緩沖的好處代碼實現隊列??要
    發表于 02-21 07:11

    環形隊列的相關資料分享

    前言??當代碼,不再是簡單的完成需求,對代碼進行堆砌,而是開始思考如何寫出優美代碼的時候,我們的代碼水平必然會不斷提升,今天,咱們來學習環形隊列結構。環形隊列的基本概念??相信對數據結
    發表于 02-23 06:10

    環形隊列的操作如何去實現

    環形隊列結構的定義是什么?環形隊列的操作如何去實現呢?
    發表于 02-25 06:35

    基于環形隊列的串口打印阻塞解決方法

    隊列(FIFO)是一種常見的線性存儲結構,在嵌入式開發中經常用到,主要的應用場景有:
    的頭像 發表于 01-22 09:47 ?2885次閱讀
    基于<b class='flag-5'>環形</b><b class='flag-5'>隊列</b>的串口打印阻塞解決方法

    深度解析數據結構與算法篇之隊列環形隊列實現

    的位置。 02 — 環形隊列實現 要想將元素放入隊列我們必須知道對頭和隊尾,在隊列長度不能無限大的條件下我們還要知道
    的頭像 發表于 06-18 10:07 ?1923次閱讀

    TencentOS-tiny中環形隊列實現

    1. 什么是隊列隊列(queue)是一種只能在一端插入元素、在另一端刪除元素的數據結構,遵循「先入先出」(FIFO)的規則。 隊列中有兩個基本概念: 隊頭指針(可變):永遠指向此隊列的第一個數據元素
    的頭像 發表于 10-08 16:30 ?1380次閱讀

    STM32串口環形緩沖--使用隊列實現(開放源碼)

    串口隊列環形緩沖區隊列串口環形緩沖的好處代碼實現隊列??要
    發表于 12-24 19:04 ?28次下載
    STM32串口<b class='flag-5'>環形</b>緩沖--使用<b class='flag-5'>隊列</b><b class='flag-5'>實現</b>(開放源碼)

    嵌入式環形隊列和消息隊列是如何去實現的?

    嵌入式環形隊列和消息隊列實現數據緩存和通信的常見數據結構,廣泛應用于嵌入式系統中的通信協議和領
    發表于 05-20 14:55 ?1129次閱讀

    裸機中環形隊列與RTOS中消息隊列有何區別呢?

    環形隊列”和“消息隊列”在嵌入式領域有應用非常廣泛,相信有經驗的嵌入式軟件工程師對它們都不陌生。
    的頭像 發表于 01-26 09:38 ?710次閱讀
    裸機中<b class='flag-5'>環形</b><b class='flag-5'>隊列</b>與RTOS中消息<b class='flag-5'>隊列</b>有何區別呢?

    嵌入式環形隊列與消息隊列實現原理

    嵌入式環形隊列,也稱為環形緩沖區或循環隊列,是一種先進先出(FIFO)的數據結構,用于在固定大小的存儲區域中高效地存儲和訪問數據。其主要特點
    的頭像 發表于 09-02 15:29 ?478次閱讀
    主站蜘蛛池模板: 国产不卡在线观看视频| 免费看到湿的小黄文软件APP | 久久亚洲精品AV无码四区| 神马影院午夜伦理限级| 69久久国产精品热88人妻| 国产亚洲精品品视频在线| 日本ccc三级| 69精品国产人妻蜜桃国产毛片| 好男人在线高清WWW免费观看 | 女子叉开腿让男子桶免费软件| 亚洲人成77777| 国产精品卡1卡2卡三卡四| 秋霞电影网视频一区二区三区| 曰本老头同性xxxxx| 国产小视频免费在线观看| 日本学生VIDEOVIDEOS更新| 最近日本字幕免费高清 | 久久中文字幕免费视频| 欧美激情视频二区| 亚洲 日本 天堂 国产 在线| 扒开老师粉嫩的泬10P| 美女张开腿露出尿口扒开来摸动漫| 亚洲三级成人| 国内精品日本久久久久影院| 视频成人永久免费视频| 仓井空torrent| 啪啪后入内射日韩| 7777色鬼xxxx欧美色夫| 久久九九有精品国产23百花影院| 亚洲黄色录像片| 国产毛片A级久久久不卡精品| 日日摸夜夜嗷嗷叫日日拍| 扒开老师大腿猛进AAA片邪恶 | 亚洲精品有码在线观看| 国产精品无码亚洲网| 少妇高潮久久久久7777 | 国产亚洲精品久久播放| 无人区在线日本高清免费| 国产成人无码视频一区二区三区| 日韩a在线看免费观看视频| jizz教师|