freertos串口消息队列
时间: 2025-01-21 17:29:51 浏览: 50
### FreeRTOS 中串口通信的消息队列实现
在嵌入式开发中,FreeRTOS 的消息队列机制能够有效地处理来自不同任务之间的数据交换。对于串口通信而言,通常涉及到接收和发送两个方向上的数据流控制。
#### 创建消息队列
为了便于管理和调度,在初始化阶段应当创建专门用于保存接收到的数据以及待发送指令的消息队列:
```c
// 定义全局变量来保存队列句柄
QueueHandle_t xRxedChars; // 接收字符缓冲区
QueueHandle_t xStringsToSend; // 发送字符串缓冲区
void vInitQueues(void){
// 初始化接收队列, 可容纳20个unsigned char类型的元素
xRxedChars = xQueueCreate(20, sizeof(unsigned char));
// 初始化发送队列, 存储指向char*指针的数组
xStringsToSend = xQueueCreate(10, sizeof(char *));
}
```
上述代码片段展示了如何利用 `xQueueCreate()` 来建立两个不同类型的消息队列实例[^2]。第一个参数表示该队列为最大可存储项的数量;第二个参数则指定每条消息所占字节数大小。
#### 处理串口中断事件
当发生UART中断时(比如新字符到达),应立即将这些信息推送到相应的消息队列里等待后续的任务去消费它们:
```c
void UART_IRQHandler(void){
portBASE_TYPE xHigherPriorityWoken = pdFALSE;
unsigned char receivedChar;
while(UART_GetFlagStatus(UART_FLAG_RXNE)){
/* 获取新的输入字符 */
receivedChar = UART_ReceiveData();
/* 将其放入到接收队列中 */
xQueueSendToBackFromISR(xRxedChars,&receivedChar,&xHigherPriorityWoken);
}
/* 如果有更高优先级的任务被唤醒,则在此处执行上下文切换 */
portYIELD_FROM_ISR(xHigherPriorityWoken);
}
```
这段C语言代码实现了从硬件层面上捕获到来自外部设备传来的单个ASCII码值,并通过调用`xQueueSendToBackFromISR()`将其安全地加入到之前定义好的接收队列当中[^3]。注意这里的最后一个布尔型参数用来指示是否有更高级别的线程因为这次操作而变得就绪状态,从而可能触发立即性的任务重排。
#### 构建消费者/生产者模型
最后一步就是编写具体的应用逻辑——即所谓的“生产者”负责准备要传输的信息,“消费者”则是实际完成物理I/O动作的部分:
```c
static void prvUartTxTask(void *pvParameters){
const TickType_t xBlockTime = pdMS_TO_TICKS(200UL); // 设置阻塞时间长度
for (;;){
char *pcString;
if(pdPASS == xQueueReceive(xStringsToSend,(void *)&pcString,xBlockTime)){
// 执行具体的发送过程...
printf("%s", pcString);
// 假设我们使用动态分配内存的方式构建了这个字符串,
// 则在这里释放它以防止泄露。
vPortFree(pcString);
}
}
}
static void prvUartRxTask(void *pvParameters){
static char cInputBuffer[8];
size_t uxIndex = 0;
for (;;){
unsigned char receivedChar;
if (pdTRUE == xQueueReceive(xRxedChars, &receivedChar, portMAX_DELAY)) {
// 对于简单回显功能来说可以直接打印出来
putchar(receivedChar);
// 或者收集一系列连续键入形成完整的命令行再做进一步解析...
if ('\r' != receivedChar && '\n' != receivedChar) {
cInputBuffer[uxIndex++] = receivedChar;
if (sizeof(cInputBuffer)-1 == uxIndex || ' '==receivedChar ) {
cInputBuffer[uxIndex]='\0';
// 进行必要的业务处理
uxIndex=0;
}
}
}
}
}
```
以上两段伪代码分别代表了一个典型的发送端(`prvUartTxTask`) 和接收端 (`prvUartRxTask`)工作流程。前者不断尝试从未满载的状态下获取下一个待发报文并输出之;后者持续监听着已填充完毕的新鲜资料以便即时响应用户的交互请求[^4]。
阅读全文
相关推荐


















