stm32基于Ucos消息队列的空闲中断信息读取储存和发送

最近做一个中继,一边是基于Wifi的网络,一边是基于串口的嵌入式设备。两者之间通过中继进行通信。

具体结构:


网络设备(手机,pad,PC等等)→→ WIFI网络→→ UART1→→ STM32消息队列→→UART2→→ 嵌入式设备


直连的话会遇到以下 2  个问题:

1.当WIFI网络或嵌入式设备发送来的数据过多,接收后来不及发送给另一边。数据会丢失

2.数据不定长


所以用了下面 2 个解决方法:

1.基于Ucos的消息队列:将接收到的数据立刻存入队列中,达到一个缓冲的目的。保证接收到数据都发送出去,当然缓冲时的数据不能多余消息队列的开的大小。(消息队列开的过大会造成硬件中断,所有程序无法执行。)

2.串口空闲中断,当串口idle中断时,通过控制DMA通道的使能,来接收数据。节约CPU资源。稳定可靠。


PCB截图:




开始码代码:

STM32的Ucos移植就不说了,网上一抓一大把。


首先搭建任务,很明显这个项目里需要两个Task。

一个是Task_ReadFromWifi(),用来从wifi网络中读取数据,然后存入消息队列

另一个是Task_ReadFromUart(),用来从嵌入式设备中读取数据,然后存入消息队列


构建任务,每一个任务相当于一个线程。他需要三个必须的东西:身份证(任务管理模块),房子(栈),大脑(代码块)。

首先分别设置优先级和分配栈

<span style="font-size:18px;"><span style="font-size:18px;">/*******************ÉèÖÃÈÎÎñÓÅÏȼ¶*******************/
#define TASK_READFROMWIFI_PRIO 5
#define TASK_READFROMUART_PR
<think>好的,用户想了解如何利用循环队列处理串口空闲中断数据接收,需要方法及示例代码。首先,我得回忆一下之前学过的相关知识。记得循环队列(环形缓冲区)可以有效地管理串口接收数据,避免数据覆盖,提高系统效率。同时,空闲中断可以用来检测一帧数据的结束,这样就不需要依赖固定的数据长度或超时判断。 首先,用户的问题涉及到两个主要部分:循环队列空闲中断。我需要解释这两者如何结合使用。根据引用[2],使用环形队列作为缓冲区可以避免在中断中直接处理数据,这样不会阻塞中断服务程序,提高系统的实时性。引用[1]提到结合uCOS-III循环队列,但用户可能不需要操作系统部分,所以重点放在循环队列空闲中断的处理上。 然后,空闲中断的作用。当串口总线在接收数据后一段时间没有活动,就会触发空闲中断。这时候可以认为一帧数据接收完成。引用[4]提到STM32的总线空闲中断,所以需要配置相应的中断使能,并在中断服务函数中处理。 接下来,步骤应该是初始化循环队列、配置串口空闲中断,然后在中断中将接收到的数据存入队列,主循环中处理数据。同时,需要注意处理空闲中断时可能的情况,比如数据长度、校验等,但用户可能只需要基础框架。 示例代码部分,需要展示循环队列的结构体定义、初始化、入队出队操作。然后,配置串口的中断,包括接收中断空闲中断。在中断服务函数中,当接收数据时,存入队列;当空闲中断触发时,设置标志位通知主程序处理数据。主程序中检查标志位,从队列中取出数据并处理。 需要确保代码正确,比如在中断中使用短小的操作,避免长时间处理。同时,循环队列的实现要注意队头队尾的指针管理,防止溢出。引用[3]提到在while循环中判断接收字节数大于0,这可能对应主程序中的处理部分,当检测到空闲中断后,处理队列中的数据。 可能的问题点:如何正确清除空闲中断标志?在STM32中,读取SRDR寄存器来清除空闲中断。需要确认这一点在代码中是否体现,否则可能导致中断不断触发。 另外,校验帧处理可能需要状态机,但用户的问题可能不需要复杂协议,所以示例代码可以简化,只展示基本的数据接收队列处理流程。 总结回答的结构:先讲方法步骤,分点说明循环队列的作用、空闲中断配置、中断处理逻辑主程序处理流程。然后给出示例代码,包括队列结构、初始化、中断服务函数主循环处理。最后可能的相关问题。 需要确保代码语法正确,使用C语言,并符合STM32的标准库函数。同时,引用相关的参考资料,比如引用[2][4],说明环形队列空闲中断的应用。 现在检查是否有遗漏的步骤,比如循环队列的判满判空条件是否正确,中断中的入队操作是否安全(比如是否在中断外有修改队列的可能,是否需要临界区保护)。可能需要使用__disable_irq()或类似的函数来保护关键操作,但示例代码可能简化这一点,假设只在中断中入队,主循环中出队,单生产者单消费者情况下不需要加锁。 最后,确保回答符合用户要求,使用中文,行内公式正确(但这里可能不需要数学公式),独立公式单独成段。但用户的问题是关于代码串口处理的,可能不涉及数学公式,所以这部分可能用不上。不过需要确认是否有变量或技术术语需要格式处理,比如中断服务例程(ISR)等,可能需要使用代码块或强调。</think>### 使用循环队列实现串口空闲中断数据接收的方法 #### 1. **设计循环队列** 循环队列(环形缓冲区)用于缓存串口接收的原始数据,避免在中断中直接处理数据,提高系统实时性[^2]。 ```c #define QUEUE_SIZE 256 typedef struct { uint8_t buffer[QUEUE_SIZE]; uint16_t head; // 写入位置 uint16_t tail; // 读取位置 } RingBuffer; // 初始化队列 void RingBuffer_Init(RingBuffer *rb) { rb->head = rb->tail = 0; } // 写入数据(中断中调用) uint8_t RingBuffer_Put(RingBuffer *rb, uint8_t data) { uint16_t next_head = (rb->head + 1) % QUEUE_SIZE; if (next_head != rb->tail) { rb->buffer[rb->head] = data; rb->head = next_head; return 1; // 成功 } return 0; // 队列满 } // 读取数据(主循环中调用) uint8_t RingBuffer_Get(RingBuffer *rb, uint8_t *data) { if (rb->tail != rb->head) { *data = rb->buffer[rb->tail]; rb->tail = (rb->tail + 1) % QUEUE_SIZE; return 1; // 成功 } return 0; // 队列空 } ``` --- #### 2. **配置串口空闲中断** - 使能串口接收中断总线空闲中断(以STM32为例): ```c // 使能接收中断空闲中断 __HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE); // 接收中断 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); // 空闲中断 ``` --- #### 3. **中断服务函数逻辑** 在中断中处理接收空闲事件: ```c RingBuffer uart_rx_queue; // 全局变量 void USART1_IRQHandler(void) { // 接收中断 if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE)) { uint8_t data = (uint8_t)(huart1.Instance->DR); RingBuffer_Put(&uart_rx_queue, data); } // 空闲中断(检测到数据包结束) if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) { __HAL_UART_CLEAR_IDLEFLAG(&huart1); // 清除空闲标志 uart_rx_complete_flag = 1; // 通知主循环处理数据 } } ``` --- #### 4. **主循环处理数据** 主循环中检查空闲中断标志,从队列中提取完整数据包: ```c volatile uint8_t uart_rx_complete_flag = 0; void main() { RingBuffer_Init(&uart_rx_queue); // ...其他初始化... while (1) { if (uart_rx_complete_flag) { uint8_t data; while (RingBuffer_Get(&uart_rx_queue, &data)) { // 解析数据包(例如校验、帧头帧尾检查) } uart_rx_complete_flag = 0; } } } ``` --- ### 关键点说明 1. **循环队列的作用** 避免直接在中断中处理数据,防止长时间阻塞中断服务函数。 2. **空闲中断触发逻辑** 总线空闲时自动触发中断,标志一帧数据接收完成[^4]。 3. **数据完整性保障** 主循环中可结合状态机校验数据包格式(帧头、长度、校验等)。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值