【问题标题】:How to implement a message queue in standard C如何在标准 C 中实现消息队列
【发布时间】:2022-05-11 03:33:49
【问题描述】:

我有一个项目(使用 c 代码的微控制器 STM32),我需要从串口接收消息(例如字符串),我需要将消息放入队列中,稍后我将读取字符串。

谁能告诉我在哪里可以找到关于如何使用标准 C 创建字符串(或字节数组)的消息队列(如 FIFO)的示例以及如何管理队列?感谢您的任何支持。

【问题讨论】:

  • 你搜索了吗,“stm32 fifo queue”。
  • 链接“未找到”
  • 你知道在非嵌入式 C 中实现队列的方法吗?使用数组或链表之类的?
  • 通常我使用特殊对象来管理队列,但在具有标准 C 的微控制器中,您应该管理缓冲区、创建队列、将元素入队和出队.. 完全不同并且很难没有图书馆
  • @Lorenzo,是的,绝对是。使用 C89,您可以创建基于链表的消息队列。一个简单的消息队列对于 OP 来说可能就足够了。除此之外,您可以使用汇编函数实现诸如信号量之类的 OS 结构,因此如果 OP 当前使用的编译器尚不支持锁/互斥锁,您将获得锁/互斥锁。嵌入式操作系统,如 FreeRTOS 和 uCOS,有非常漂亮的代码,可以成为一个很好的学习工具。它们都在嵌入式目标上运行。那么嵌入式 C 究竟缺少哪些功能,从而阻止了 OP 实现队列?

标签: c message-queue stm32


【解决方案1】:
  • “关于如何使用标准 C 创建字符串(或字节数组)的电子消息队列(如 FIFO)以及如何管理队列的示例”

  • “在具有标准 C 的微控制器中,您应该管理缓冲区、创建队列、将元素入队和出队”

下面给出的例子应该满足要求。

如有必要,使用的库函数可以轻松替换为特定于平台的版本或标准 C 数组操作。

队列的内存分配也可以作为静态变量而不是堆栈变量来完成。如果需要,甚至可以使用 malloc

消息类型可以轻松扩展。队列和数据大小被定义为常量。

@leonardo 对如何构建处理给出了很好的提示,即在中断例程中将消息入队并在 main 中将它们出队。我想需要使用某种信号量,这样操作队列的函数的执行就不会混淆。对此的一些想法在semaphore like synchronization in ISR (Interrupt service routine)

中进行了讨论
/*
Portable array-based cyclic FIFO queue.
*/

#include <stdbool.h>
#include <stdio.h>
#include <string.h>

#define MESSAGE_SIZE 64
#define QUEUE_SIZE 3

typedef struct {
char data[MESSAGE_SIZE];
} MESSAGE;

typedef struct {
    MESSAGE messages[QUEUE_SIZE];
    int begin;
    int end;
    int current_load;
} QUEUE;

void init_queue(QUEUE *queue) {
    queue->begin = 0;
    queue->end = 0;
    queue->current_load = 0;
    memset(&queue->messages[0], 0, QUEUE_SIZE * sizeof(MESSAGE_SIZE));
}

bool enque(QUEUE *queue, MESSAGE *message) {
    if (queue->current_load < QUEUE_SIZE) {
        if (queue->end == QUEUE_SIZE) {
            queue->end = 0;
        }
        queue->messages[queue->end] = *message;
        queue->end++;
        queue->current_load++;
        return true;
    } else {
        return false;
    }
}

bool deque(QUEUE *queue, MESSAGE *message) {
    if (queue->current_load > 0) {
        *message = queue->messages[queue->begin];
        memset(&queue->messages[queue->begin], 0, sizeof(MESSAGE));
        queue->begin = (queue->begin + 1) % QUEUE_SIZE;
        queue->current_load--;
        return true;
    } else {
        return false;
    }
}

int main(int argc, char** argv) {
    QUEUE queue;
    init_queue(&queue);

    MESSAGE message1 = {"This is"};
    MESSAGE message2 = {"a simple"};
    MESSAGE message3 = {"queue!"};

    enque(&queue, &message1);
    enque(&queue, &message2);
    enque(&queue, &message3);

    MESSAGE rec;

    while (deque(&queue, &rec)) {
        printf("%s\n", &rec.data[0]);
    }
}

编译运行:

$ gcc -Wall queue.c
$ ./a.out          
This is
a simple
queue!
$ 

【讨论】:

    【解决方案2】:

    C 语言没有内置队列(它是一种不包括电池的语言),您需要自己构建。如果您只需要一个 FIFO 将内容推送到您的中断例程中,然后将它们弹出到您的主循环中(顺便说一句,这是一个很好的设计),请检查 A Simple Message Queue for C 是否适合您。

    【讨论】:

      猜你喜欢
      • 2011-05-10
      • 2014-05-04
      • 2011-05-19
      • 2011-12-18
      • 2012-04-18
      • 2012-04-21
      • 2011-11-04
      • 1970-01-01
      • 2014-08-23
      相关资源
      最近更新 更多