STM32 串口 DMA 接收任意长度数据

news2024/10/6 0:30:02

DMA 局限性

DMA 传输完成会产生中断告知 CPU,这对于固定长度的数据是没什么问题的。但是对于不定长的数据就不行了,DMA 一定要接收到足够多(设定的长度)的数据时才产生完成中断,如果接收到的数据量小于设定的长度,这个时候 CPU 就无法通过中断方式取处理这点数据了。那 CPU 怎样优化这个缺陷呢?那就是使用轮询的方式,主动获取 DMA 当前收到了多少字节数据,然后决定要不要处理这些数据。但是,一旦使用轮询方式就背离了 DMA 原有的设计意图(为 CPU 减负)。
那还有什么办法可以优雅地解决这个问题吗?那就是使用串口空闲中断。

串口空闲中断

这里是转变了一个思路,单纯从 DMA 角度解决问题貌似找不到很好的答案,那就转换到串口上来。因为本身的工作是串口 DMA 接收任意长度数据。
串口有个空闲中断,大概是串口总线在一个字节的时间内没有再接收到数据,认为一帧数据传输完毕了,就会产生串口空闲中断。
这样我们就不使用 DMA 中断了,只使用串口空闲中断,即在串口空闲中断中获取 DMA 接收的数据并处理,然后再开启下次 DMA 接收。

关键代码

使能串口空闲中断

__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);

添加串口空闲中断处理函数

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
  UART_IRQHandler_IDLE(&huart1); // 串口空闲中断处理函数
  /* USER CODE END USART1_IRQn 1 */
}

/* USER CODE BEGIN 1 */
void UART_IRQHandler_IDLE(UART_HandleTypeDef *huart)
{
	if(huart == &huart1)
	{	
		if(__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET)
		{
			HAL_UART_DMAStop(&huart1);
			uint8_t data_length  = sizeof(recv_buf) - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
			HAL_UART_Transmit(&huart1, recv_buf, data_length, 100);
			__HAL_UART_CLEAR_IDLEFLAG(&huart1);
			__HAL_UART_CLEAR_OREFLAG(&huart1);
			HAL_UART_Receive_DMA(&huart1, recv_buf, sizeof(recv_buf));
		}
	}
}
/* USER CODE END 1 */

避坑

在使用串口中断时,一定记得要清除 ORE flag,不然中断会出各种意想不到的异常,比如串口发送数据会触发串口接收中断。

__HAL_UART_CLEAR_OREFLAG(&huart1);

测试

在这里插入图片描述

完整代码

https://download.csdn.net/download/lyndon_li/88054148
对应硬件:STM32F107VCT6

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux的基础配置

配置篇 前置步骤:先租一个服务器或装个Linux再或者虚拟机都可以 1.安装gcc,g,gdb 在Linux下我们能用什么工具来编译所编写好的代码呢,其实Linux下这样的工具有很多,但我们只介绍两款常用的工具,它们分别是gcc和g. gcc和g的主要…

解决端口占用

解决办法: 1、换一个其它未被占用的端口 2、端口被占用了,先看下是哪个程序再用,停掉就OK了 下面演示结束端口被占用的程序的过程: 1、查看被占用的端口的进程 netstat -aon|findstr 端口号2、根据PID找到占用此端口的进程 ta…

Redis单机伪集群配置与搭建

目录 1. 复制6个redis配置文件到当前目录下 2. 启动每个节点 3. 判断集群是否可用 4. 初始化集群 5. 查看集群信息 6. 获取与插槽对应的节点 (1)手动重定向 (2)自动重定向 7. 故障恢复 需求:配置一个三主三从的集…

为什么ConcurrentHashMap不允许插入null值而HashMap可以?

为什么ConcurrentHashMap不允许插入null值而HashMap可以? 文章目录 为什么ConcurrentHashMap不允许插入null值而HashMap可以?HashMap源码ConcurrentHashMap源码为什么ConcurrentHashMap需要加空值校验呢?二义性问题测试代码代码分析测试结果结…

纯css3实现水波纹从中心向四周扩散动画

纯css3实现水波纹从中心向四周扩散动画 效果可用于pc端或移动端,引导用户点击,间接带来一定的转化率 示例效果 示例代码 <template><div class"zanbtn-wrap"><div click"handleClick(https://pay.aikelaidev.cn/paypage/?merchant35bdYxSx7dCUr…

子网划分路由网卡

1."IPv4 CIDR" "IPv4 CIDR" 是与互联网协议地址&#xff08;IP address&#xff09;和网络的子网划分有关的概念。 - "IPv4" 代表 "Internet Protocol version 4"&#xff0c;也就是第四版互联网协议&#xff0c;这是互联网上最广泛使…

IPv4 与 IPv6:网络协议的差异和转换方法

在网络的世界里&#xff0c;IPv4 和 IPv6 这两个协议就像是两个不同的王国&#xff0c;各自拥有着独特的领土和规则。虽然它们都是为了互联网的发展而存在&#xff0c;但它们之间究竟有哪些差异&#xff0c;以及如何在这两个王国之间穿梭&#xff0c;仍然是很多网络小白们的困惑…

Spring使用注解存储Bean对象

文章目录 一. 配置扫描路径二. 使用注解储存Bean对象1. 使用五大类注解储存Bean2. 为什么要有五大类注解&#xff1f;3.4有关获取Bean参数的命名规则 三. 使用方法注解储存Bean对象1. 方法注解储存对象的用法2. Bean的重命名 在前一篇博客中&#xff08; Spring项目创建与Bean…

Excel中Vlookup

VLOOKUP($A:$A,Sheet3!$A:$D,COLUMN(Sheet3!B1),FALSE) ps: 1.按F4&#xff0c;锁定第一个和第二个参数 2.第二个参数&#xff0c;要选择全部范围(包括被查找列&#xff0c;以及查找内容) 2.第三个参数用column&#xff08;&#xff09;函数&#xff0c;第三列不要锁定 3.…

【Linux】自动化构建工具-make/Makefile详解

前言 大家好吖&#xff0c;欢迎来到 YY 滴 Linux系列 &#xff0c;热烈欢迎&#xff01;本章主要内容面向接触过Linux的老铁&#xff0c;主要内容含 欢迎订阅 YY 滴Linux专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 订阅专栏阅读&#xff1a;YY的《…

Alpha-GO打败⼈类的秘籍- 强化学习(Reinforcement Learning)

为了深⼊理解强化学习&#xff08;Reinforcement Learning&#xff0c;简称RL&#xff09;这⼀核⼼概念&#xff0c;我们从⼀个⽇常游戏的例⼦出发。在“贪吃蛇”这个经典游戏中&#xff0c;玩家需要掌控⼀条蛇&#xff0c;引导它吞吃屏幕上出现的各种果实。每次成功捕获果实&a…

CSS层叠

声明冲突 同一个样式&#xff0c;多次应用到同一个元素。 此时可以看到我们的a元素的样式和浏览器的默认样式发生了冲突 层叠 解决声明冲突的过程&#xff0c;浏览器会自动处理&#xff08;权重计算&#xff09;&#xff0c;权重大的获胜 1.比较重要性 重要性从高到低 1&…

Docker 教程

Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。 容器是完全使用沙箱机制&a…

省电液晶驱动IC,VK2C22G,COG片高抗干扰抗噪系列LCD段码驱动芯片,I2C通信接口

型号:VK2C22G DICE(邦定COB)/COG&#xff08;绑定玻璃用&#xff09; VK2C22G概述&#xff1a; VK2C22G是一个点阵式存储映射的LCD驱动器&#xff0c;可支持最大176点&#xff08;44SEGx4COM&#xff09;的LCD屏。单片机可通过I2C接口配置显示参数和读写显示数据&#…

C# 接口2.0 (028 课程)

参考视频教程&#xff1a;B站 刘铁猛 028 接口 依赖反转 单元测试 接口是一种供方和需求方都遵守的契约 — 即规则。 文章目录 原始代码利用用接口简化函数重载紧耦合程序实体松耦合代码实体设计一个紧耦合 -- 接口松耦合 -- 单元测试紧耦合程序实例松耦合程序实体 -- 引入接…

latex子图无法重新编号问题

问题 想让后四个子图&#xff0c;从a开始编号 解决方法 如上原因是由于全局自动编号机制&#xff0c;在 \begin{figure*}[h] \centering下面添加&#xff1a; \setcounter{subfigure}{0}

SpringBoot+ShardingSphere+Mybatis实现Mysql8读写分离

场景 CentOS7安装Mysql8并进行主从复制配置&#xff1a; CentOS7安装Mysql8并进行主从复制配置_霸道流氓气质的博客-CSDN博客 在上面搭建起来Mysql之间的主从复制的基础上&#xff0c;在SpringBoot项目中实现Mysql数据的 读写分离&#xff0c;即写入操作一个库&#xff0c;…

为什么重写 equals 方法要重写 hashCode 方法

前言 看了挺多关于这个问题相关的文章&#xff0c;发现回答缺少因果逻辑。直到看了一篇文章提到 《Effective Java》中有关于这个问题的答案。于是找了电子书看了一下&#xff0c;查看相关源码理清了因果逻辑&#xff0c;得出怎样回答这个问题比较好。 1 hashCode 的通用约定…

k8s 如何升级应用

如何升级应用 在之前的分享中&#xff0c;我们知道一个程序如何放到容器中&#xff0c;一个镜像如何生成 pod&#xff0c; pod 的创建&#xff0c;运行&#xff0c;管理&#xff0c;删除过程&#xff0c;挂载等等 那么我们有没有想过&#xff0c;在真正的生产环境中&#xff…

golang 验证器库go-playground/validator实践

当我们将一个接口值传递给一个 reflect.ValueOf 函数调用时&#xff0c;此调用返回的是代表着此接口值的动态值的一个 reflect.Value 值。我们必须通过间接的途径获得一个代表一个接口值的 reflect.Value 值。 reflect.Value 类型有很多方法&#xff08;Package reflect - The …