[STM32 HAL库]串口中断编程思路

一、前言

最近在准备蓝桥杯比赛(嵌入式赛道),研究了以下串口空闲中断+DMA接收不定长的数据,感觉这个方法的接收效率很高,十分好用。方法配置都成功了,但是有一个点需要进行考虑,就是一般我们需要对串口接收的数据进行处理,这个数据处理是在中断的回调函数里面处理还是在主函数里面处理好呢?以下就这两个方法进行分析:

二、方法分析

目前我想到的有两种方法:

方法一

在回调函数里直接处理数据

优点:

  • 实时性强:数据接收完成后立即处理,减少了数据处理的延迟。
  • 代码简洁:数据接收和处理逻辑在同一个地方,代码易于理解和维护。

缺点:

  • 占用中断处理时间:如果数据处理逻辑复杂或耗时,会影响中断的响应速度,进而影响系统其他功能的实时性。
  • 可维护性差:如果数据处理逻辑复杂,中断处理函数会变得冗长,难以维护。

方法二

在回调函数中设置标志位,在主函数里读取标志位再进行数据处理

优点:

  • 保护中断响应速度:中断处理函数只负责设置标志位,数据处理在主循环中进行,保证了中断的响应速度。
  • 代码结构清晰:中断处理函数和数据处理逻辑分离,代码结构更清晰,易于维护和扩展。
  • 资源利用率高:可以在主循环中根据系统状态灵活调度数据处理,避免在中断中处理复杂逻辑造成的资源浪费。

缺点:

  • 增加了一定的复杂性:需要额外管理标志位,以及同步数据接收和处理的逻辑。
  • 可能引入延迟:数据处理被推迟到主循环中进行,可能会引入一定的处理延迟。

总结

  • 数据处理的复杂度:如果数据处理逻辑复杂或耗时,建议采用方法二,以保护中断响应速度。
  • 系统的实时性要求:如果系统对实时性要求较高,且数据处理不是非常耗时,方法一可能更合适。但如果数据处理可能影响到系统的其他实时功能,方法二则更为稳妥。
  • 代码的可维护性和扩展性:如果希望代码结构更清晰,易于维护和扩展,方法二通常是更好的选择。

三、实际操作

配置的方法可以看之前写的文章
链接: [STM32 HAL库]串口空闲中断+DMA接收不定长数据

实验现象:将电脑发来的数据,原封不到的发送回去。特别注意BUFF_SIZE的大小,太小会造成接收数据的丢失。

方法一

在这个方法中,在中断的回调函数里直接发送回去数据,并手动开启下一次的中断。

#define BUFF_SIZE	128
uint8_t rx_buffer[BUFF_SIZE];  // 创建接收缓存,大小为BUF_SIZE
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFF_SIZE);//手动开启串口DMA模式接收数据__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);	//手动关闭DMA_IT_HT中断	while (1){}
}
void SystemClock_Config(void)
{//...
}
/* 串口接收完成回调函数 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{if (huart->Instance == USART1){HAL_UART_Transmit(&huart1, rx_buffer, Size, 0xffff);// 将接收到的数据再发出HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx_buffer, BUFF_SIZE); // 接收完毕后重启串口DMA模式接收数据__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);// 手动关闭DMA_IT_HT中断memset(rx_buffer, 0, BUFF_SIZE);// 清除接收缓存	}
}
/* 串口错误回调函数 */
void HAL_UART_ErrorCallback(UART_HandleTypeDef * huart)
{if(huart->Instance == USART1){HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx_buffer, BUFF_SIZE); // 接收完毕后重启串口DMA模式接收数据__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);// 手动关闭DMA_IT_HT中断memset(rx_buffer, 0, BUFF_SIZE);// 清除接收缓存}
}

方法二

在这个方法中,在串口接收完成的回调函数置接收完成的标志位,然后在主函数中进行判断。判断成立则进行数据的发送,并手动开启下一次的中断和清除标志位。

需要注意的是,不要在回调函数里面手动开启下一次的中断,因为有可能会出现主函数数据还未处理完成,下一个串口数据就到来而覆盖上一次的串口数据。
所以,这里程序的处理方法是:程序处理完本次数据,则开启下一次中断接收;程序未处理完本次数据,则不开启下一次中断接收

#define BUFF_SIZE	128
uint8_t rx_buffer[BUFF_SIZE];  	// 创建接收缓存,大小为BUF_SIZE
_Bool 	u1_rx_end_flag = 0;		//USART1接收数据完成标志位 1:接收完成
uint16_t u1_rx_size;			//USART1接收数据实际长度
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFF_SIZE);//手动开启串口DMA模式接收数据__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);		   	//手动关闭DMA_IT_HT中断	while (1){/* 判断接收是否完成 */if(u1_rx_end_flag == 1){/* 对接收的数据进行处理 */HAL_UART_Transmit(&huart1, rx_buffer, u1_rx_size, 0xffff);// 将接收到的数据再发出memset(rx_buffer, 0, BUFF_SIZE);	// 清除接收缓存/* 开启下一次中断 */HAL_UARTEx_ReceiveToIdle_DMA(&huart1,rx_buffer,BUFF_SIZE);//手动开启串口DMA模式接收数据__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);//手动关闭DMA_IT_HT中断	/* 清除标志位 */u1_rx_end_flag = 0;}}
void SystemClock_Config(void)
{//...
}
/* 串口接收完成回调函数 */
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{if (huart->Instance == USART1){u1_rx_end_flag = 1;	//置标志位u1_rx_size = Size;		//获取接收数据长度}
}	
/* 串口错误回调函数 */
void HAL_UART_ErrorCallback(UART_HandleTypeDef * huart)
{if(huart->Instance == USART1){HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx_buffer, BUFF_SIZE);//手动开启串口DMA模式接收数据__HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);// 手动关闭DMA_IT_HT中断memset(rx_buffer, 0, BUFF_SIZE);// 清除接收缓存}
}

值得一提的是,若是没有手动开启串口空闲中断,那么串口错误中断也不会被开启,也就无法进入串口错误回调函数

四、实验现象

两个方法实现现象一致
在这里插入图片描述

应该还有更好的串口接收模式,现在来说,这个方法应该够用了。

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

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

相关文章

嵌入式 工程配置

本次用的STM32F4芯片系列 目录 1. 新建文件夹 2. 新建文件夹下创建 3. 打开keil5 3.1.1 点击菜单栏project 点击new project 3.1.2. 选择刚刚新建的文件夹 3.1.3.将项目文件保存到Project文件夹里 3.1.4. 将项目命名这里命名为STM32 保存 3.1.5. 保存好后会跳出选择芯…

我的图形布局 组织结构图布局

组织结构图布局,有的人也叫它树状布局,在图形中是经常用到的布局算法.形成类似如下图的图形布局方式 首先创建一个类, public class TreeLayouter {private int m_space 40;/// <summary>/// 空间间隔/// </summary>public int Space{get { return m_space; }se…

计算机网络介质访问控制全攻略:从信道划分到协议详解!!!

一、信道划分介质访问控制 介质访问控制&#xff1a;多个节点共享同一个“总线型”广播信道时&#xff0c;可能发生“信号冲突” 应该怎么控制各节点对传输介质的访问&#xff0c;才能减少冲突&#xff0c;甚至避免冲突? 时分复用(TDM) 时分复用&#xff1a;将时间分为等长的“…

sql主从同步

今天给大家介绍两种mysql的主从同步方式&#xff1a;第一种是基于binlogzhu主从同步&#xff1b;第二种就是基于gtid的主从同步方式。 首先给大家介绍一下什么是sql的主从复制。 主从复制&#xff1a; 通过将MySQL的某一台主机&#xff08;master&#xff09;的数据复制到其…

计算机组成原理——数据表示(二)

当生活的压力和困惑缠绕在身边&#xff0c;我们往往需要振奋精神&#xff0c;勇往直前。无论在何种困境中&#xff0c;我们都要保持积极的态度和坚定的信念。将悲观的情绪抛之脑后&#xff0c;展现出坚强的意志力和无尽的活力。振奋精神意味着我们要战胜自己内心的负面情绪&…

Spring Boot整合Thymeleaf、JDBC Template与MyBatis配置详解

本文将详细介绍如何在Spring Boot项目中整合Thymeleaf模板引擎、JDBC Template和MyBatis&#xff0c;涵盖YAML配置、依赖版本匹配、项目结构设计及代码示例。 一、版本兼容性说明 Spring Boot版本与Java版本对应关系 Spring Boot 2.x&#xff1a;支持Java 8、11&#xff08;推…

概率论里的特征函数,如何用卷积定理去理解

概率论里的特征函数&#xff0c;如何用卷积定理去理解_哔哩哔哩_bilibili

论文笔记(六十二)Diffusion Reward Learning Rewards via Conditional Video Diffusion

Diffusion Reward Learning Rewards via Conditional Video Diffusion 文章概括摘要1 引言2 相关工作3 前言4 方法4.1 基于扩散模型的专家视频建模4.2 条件熵作为奖励4.3 训练细节 5 实验5.1 实验设置5.2 主要结果5.3 零样本奖励泛化5.4 真实机器人评估5.5 消融研究 6 结论 文章…

HashMap用法

一、构造方法 构造方法有4个。 1、手动声明初始容量及负载因子的构造函数。初容容量的最大值不能超过MAXIMUM_CAPACITY 2、手动声明初始容量的构造函数&#xff0c;负载因子是默认大小。 默认的负载因子是0.75 3、无参的构造函数&#xff0c;会指定默认的负载因子。容量是默…

Java基础 (一)

基础概念及运算符、判断、循环 基础概念 关键字 数据类型 分为两种 基本数据类型 标识符 运算符 运算符 算术运算符 隐式转换 小 ------>>> 大 强制转换 字符串 拼接符号 字符 运算 自增自减运算符 ii赋值运算符 赋值运算符 包括 强制转换 关系运算符 逻辑运算符 …

无人机在城市执法监管中的应用:技术革新与监管挑战

随着科技的不断进步&#xff0c;无人机技术在城市管理中的应用越来越广泛。无人机以其灵活性、高效性和低成本的优势&#xff0c;正在逐渐成为城市执法监管的得力助手。本文将探讨无人机在城市执法监管中的应用现状、技术优势以及面临的挑战。 无人机技术在城市执法监管中的应用…

AI模型提示词(prompt)优化-实战(一)

一、prompt作用 用户与AI模型沟通的核心工具&#xff0c;用于引导模型生成特定内容、控制输出质量、调整行为模式&#xff0c;并优化任务执行效果&#xff0c;从而提升用户体验和应用效果 二、prompt结构 基本结构 角色&#xff1a;设定一个角色&#xff0c;给AI模型确定一个基…

mac 电脑上安装adb命令

在Mac下配置android adb命令环境&#xff0c;配置方式如下&#xff1a; 1、下载并安装IDE &#xff08;android studio&#xff09; Android Studio官网下载链接 详细的安装连接请参考 Mac 安装Android studio 2、配置环境 在安装完成之后&#xff0c;将android的adb工具所在…

电子应用设计方案101:智能家庭AI喝水杯系统设计

智能家庭 AI 喝水杯系统设计 一、引言 智能家庭 AI 喝水杯系统旨在为用户提供个性化的饮水提醒和健康管理服务&#xff0c;帮助用户养成良好的饮水习惯。 二、系统概述 1. 系统目标 - 精确监测饮水量和饮水频率。 - 根据用户的身体状况和活动量&#xff0c;智能制定饮水计划。…

5G网络下移动机器人的图像和指令传输用于远程操作

论文标题 **英文标题&#xff1a;**Image and Command Transmission Over the 5G Network for Teleoperation of Mobile Robots **中文标题&#xff1a;**5G网络下移动机器人的图像和指令传输用于远程操作 作者信息 Thiago B. Levin,, Joo Miguel Oliveira,, Ricardo B. Sou…

AIGC视频生成国产之光:ByteDance的PixelDance模型

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍ByteDance的视频生成模型PixelDance&#xff0c;论文于2023年11月发布&#xff0c;模型上线于2024年9月&#xff0c;同时期上线的模型还有Seaweed&…

软件安全性测试报告如何编写?

在当今数字化时代&#xff0c;软件安全性问题愈发显得重要&#xff0c;软件产品的安全性已经成为企业竞争力的重要组成部分。而软件安全性测试报告是通过对软件系统进行全面的安全性测试后&#xff0c;整理出的关于其安全性状况、潜在风险及改进建议的专业文档。此报告旨在帮助…

从密码学原理与应用新方向到移动身份认证与实践

相关学习资料放下面啦&#xff01; 记得关注❤️&#xff5e;后续分享更多资料 通过百度网盘分享的文件&#xff1a;从密码学原理与应... 链接https://pan.baidu.com/s/1mHpHkvPuf8DUwReQkoYQlw?pwdGza7 提取码&#xff1a;Gza7 复制这段内容打开「百度网盘APP 即可获取」 记…

【玩转全栈】---基于YOLO8的图片、视频目标检测

本篇主要讲YOLO8的具体操作&#xff0c;想要了解YOLO的具体原理&#xff0c;可以去官网查询 目录 下载ultralytics库 开始检测 介绍 YOLOv8&#xff08;You Only Look Once Version 8&#xff09;是 YOLO 系列的最新版本&#xff0c;由 Ultralytics 开发并发布&#xff0c;是一…

生成对抗网络(GAN)入门与编程实现

生成对抗网络&#xff08;Generative Adversarial Networks, 简称 GAN&#xff09;自 2014 年由 Ian Goodfellow 等人提出以来&#xff0c;迅速成为机器学习和深度学习领域的重要工具之一。GAN 以其在图像生成、风格转换、数据增强等领域的出色表现&#xff0c;吸引了广泛的研究…