使用 UART 空闲中断(IDLE) + DMA 实现非阻塞接收

1. 基本原理

  • 空闲中断(IDLE):当 UART 接收数据后,总线在 1 字节传输时间 内无新数据时触发中断。

  • DMA 传输:在后台自动将 UART 接收的数据搬运到内存缓冲区,无需 CPU 干预。

  • 协作流程

    1. 启动 DMA 接收,持续监听 UART 数据。

    2. 当数据到达时,DMA 自动填充缓冲区。

    3. 数据停止传输后,触发空闲中断。

    4. 在中断中计算实际接收长度,处理数据。

2. 硬件与库配置

2.1 硬件使能

  • 在 STM32CubeMX 中:

    1. 启用 UART 的 DMA RX 通道

    2. 启用 UART 的 全局中断(NVIC Settings)。

2.2 代码配置

// 定义全局变量
#define RX_BUFFER_SIZE 64
uint8_t g_rxBuffer[RX_BUFFER_SIZE];  // DMA 接收缓冲区
volatile uint16_t g_rxLength = 0;     // 实际接收数据长度
volatile bool g_rxComplete = false;   // 接收完成标志// 在 main() 初始化中启动 DMA 接收
void UART_Init(void) {// 启用 UART 空闲中断(需手动添加)__HAL_UART_ENABLE_IT(&huart4, UART_IT_IDLE);// 启动 DMA 接收HAL_UART_Receive_DMA(&huart4, g_rxBuffer, RX_BUFFER_SIZE);
}

3. 中断处理

3.1 空闲中断回调

// 在 stm32xx_it.c 的 USARTx_IRQHandler 中添加空闲中断判断
void USARTx_IRQHandler(void) {if (__HAL_UART_GET_FLAG(&huart4, UART_FLAG_IDLE)) {__HAL_UART_CLEAR_IDLEFLAG(&huart4);  // 清除空闲中断标志UART_IdleCallback(&huart4);          // 调用自定义处理函数
    }HAL_UART_IRQHandler(&huart4);            // HAL 库默认中断处理
}

3.2 计算数据长度

// 自定义空闲中断处理函数
void UART_IdleCallback(UART_HandleTypeDef *huart) {if (huart == &huart4) {// 停止 DMA 防止数据覆盖HAL_UART_DMAStop(&huart4);// 计算实际接收数据长度g_rxLength = RX_BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart->hdmarx);// 设置接收完成标志g_rxComplete = true;}
}

4. 数据处理

4.1 主循环中检测标志

while (1) {if (g_rxComplete) {// 处理接收到的数据(例如 "10.00\r\n")char *end = strstr((char*)g_rxBuffer, "\r\n");if (end != NULL) {*end = '\0';float power = atof((char*)g_rxBuffer);usRegInputBuf[Addr_Photo_StateRedLaserPower] = (uint16_t)(power * 10);}// 重置状态并重启 DMA 接收g_rxComplete = false;memset(g_rxBuffer, 0, RX_BUFFER_SIZE);HAL_UART_Receive_DMA(&huart4, g_rxBuffer, RX_BUFFER_SIZE);}// 其他任务osDelay(10);
}

5. 关键问题与优化

5.1 数据溢出处理

  • 若数据长度超过 RX_BUFFER_SIZE,DMA 会循环覆盖缓冲区(需根据协议启用/禁用循环模式)。

  • 建议在协议中设计数据帧长度限制,或增加动态缓冲区。

5.2 错误处理

// 在 DMA 或 UART 错误中断中恢复接收
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {if (huart == &huart4) {HAL_UART_DMAStop(&huart4);memset(g_rxBuffer, 0, RX_BUFFER_SIZE);HAL_UART_Receive_DMA(&huart4, g_rxBuffer, RX_BUFFER_SIZE);}
}

6. 总结

  • 优势

    • 非阻塞接收,极大降低 CPU 占用率。

    • 自动适应不定长数据帧,无需预设超时时间。

    • 高效处理高速数据流(如 115200bps 及以上)。

  • 适用场景

    • 需要实时响应的工业控制设备。

    • 高频数据采集(如传感器网络)。

    • 复杂多任务系统(如 RTOS 环境)。

通过此方案,可彻底解决轮询接收中的超时问题,同时提升系统整体性能和稳定性。实际部署时需根据硬件特性调整缓冲区和中断优先级。

 

 



 



    

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/893395.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Feedalyze - 让你听得见、听得清用户的反馈

Feedalyze - 专注于用户反馈的管理分析工具,让你听得见、听得清用户的反馈!满足用户需求,解决用户问题,获得适当报酬是商业成功最为重要的因素。然而扪心自问,当您推出新产品后,您真的在听、听得见、听得清用户的反馈么? 当今信息传播迅猛,渠道繁多,优秀产品随口碑效应…

自己写一个下载器,速度堪比IDM下载器

心血来潮,想自己做个下载器,类似于腾讯的游戏高速下载器。类似下图这种,这样又可以接受客户定制喽。开干!解决单文件exe问题这类程序都会利用第三方的下载插件来提升下载速度,但是就会出现多个文件的问题,给人体验感就不好了。利用ILMerge将三方的插件都合并起来,顺利解…

文件下载方法

通用下载1 package com.stig.business.web.contoller;2 3 import com.stig.business.web.mobel.po.EbssFileInfo;4 import com.stig.common.constant.Constants;5 import com.stig.common.properties.BusStopSignProperties;6 import com.stig.common.utils.RedisUtils;7 impor…

Charles安装及使用教程

一. 简介及安装 一、charles的使用 1.1 charles的说明 Charles其实是一款代理服务器,通过过将自己设置成系统(电脑或者浏览器)的网络访问代理服务器,然后截取请求和请求结果达到分析抓包的目的。该软件是用Java写的,能够在Windows,Mac,Linux上使用。安装Charles的时候要…

47.9K star!全平台开源笔记神器,隐私安全首选!

"Joplin 是一款开源的笔记记录和待办事项应用,支持端到端加密同步,完美替代商业笔记软件" —— 来自开发者 Laurent Cozic嗨,大家好,我是小华同学,关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法"Joplin 是一款开源的笔记记录和待办事项应…

什么是项目管理?五大流程是什么?

项目管理这东西,大家可能听过,但是具体怎么操作,很多人可能就一头雾水了。 简单来说,项目管理就是为了完成某个特定目标,把时间、资源、人员等因素有条不紊地组织、协调、控制和调整,最终确保项目按时、按预算、高质量地完成。 这个“项目”可以是任何东西,比如公司新产…

最全面的浏览器教程-完结撒花

完结撒花 🎉🎉🎉完结撒花 🎉🎉🎉 《最全面的浏览器教程》目前要告一段落了,耗时我一个多月,整理了大量的笔记,参考了很多教程和文章,累计写了 24 篇文章,7.3 万字,200 多张图片,收获了很多粉丝和鼓励,在此表示感谢。 如果后续有学到什么新技巧,看到好玩意…

牛客题解 | 字符串相乘

牛客题库题解题目 题目链接 题解 题目难度:中等难度 知识点:字符串、大数相乘 模拟人工计算 计算的过程基本上和小学生列竖式做乘法相同。为编程方便,并不急于处理进位,而将进位问题留待最后统一处理。数组a存储第一个数字123(逆序)数组b存储第二数组20(逆序)结果存入数…

皮尔逊、斯皮尔曼、肯德尔相关系数

相关系数和特征选择 相关系数和特征选择,一个是属性,一个是特征。一般,把数据集中的各列成为属性,而对算法模型表现有益的属性成为特征。例如,在预测泰坦尼克乘客的存活情况时,乘客姓名这个属性对我们的预测可能没有帮助,甚至会干扰模型表现;而乘客年龄、性别或许与存活…

认识 TapFlow,以编程方式运行 TapData

TapFlow 是 TapData Live Data Platform 最新推出的一个面向编程的API 框架。TapFlow 可以让开发者和数据工程师用一个简单易用而又强大的编程语言来进行数据管道和数据模型的开发工作。**什么是TapFlow? ** TapFlow 是 TapData Live Data Platform 最新推出的一个面向编程的A…

Maya 影视渲染,渲染101 让创作无压力!

Maya 创作时,渲染是不是常让人崩溃?漫长等待、电脑性能不足、报错频出,今天就给大家分享基于渲染 101 平台的 Maya 云渲染,轻松解决这些难题!告别漫长等待,效率飙升**** 自己电脑渲染复杂 Maya 项目,耗时久,进度慢。渲染 101 的云渲染有强大计算集群,众多高性能服务器…