| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> STM32 HAL串口USART DMA接收(不定长)汇总 -> 正文阅读 |
|
[嵌入式]STM32 HAL串口USART DMA接收(不定长)汇总 |
先提供一份测试完全没问题的代码,后面详解一下,以下是在中断文件中的回调函数。
下面是串口中断函数配置
然后,我们从头开始说起。 一、串口配置问题串口配置属于比较基础的,stm32cubeide简直是懒人神器,这里注意几个点即可。 1、串口接收引脚要上拉这个一般不会有什么影响,但是有时485芯片电压不稳的时候,会产生非常多的接收信号干扰,造成程序跑飞,做了上拉,就可以避免这个问题。 2、串口根据波特率设置对应的引脚速度一般9600及以下选择LOW即可,19200~115200选择MEDIUM, 再往上的直接用HIGH就行。这里要注意,有一个output level,这个是设置GPIO初始电平高低的,尽量串口输入配置LOW。 3、串口驱动方式用推挽PUSH PULL比较合适,开漏OPEN Drain有时会有问题,这个跟电路设计有关系。 4、DMA配置启用接收配置,发送尽量不用DMA,这里有一个DMA的逻辑陷阱,对于DMA发送来说,它不管你要发送的数据又多少,只要放到寄存器中,就启动发送程序,如果转移数据的速度没有发送快,或者分几波放置数据的方式,你会发觉发送的数据就没有完整的时候。所以,为了避免这些麻烦,用阻塞方式来做串口发送会是相对来说简单的选择。除非要发送的数据量非常大,这个时候就需要好好设计一下DMA发送的逻辑和时序配合了。 5、串口初始化使用stm32cubeide有一个优势,它会自动帮你把外设用较好的顺序进行了初始化,这样就不会因为时钟初始化顺序问题,引起一些莫名其妙的问题。 但是串口中断及DMA初始化,一般还是需要单独做的。一般是先使用IDLE,后使能DMA,有很多文章提到要先初始化DMA,后初始化IDLE,以防一上电就产生接收,我觉得这个不是问题,只要做好接收数据判断即可。但是先使能DMA会造成串口干扰导致中断频发,这种问题才是最难处理的。 ?? ?__HAL_UART_ENABLE_IT(&USART, UART_IT_IDLE); //使能IDLE中断 二、串口DMA接收的配置很多文章和帖子中都做了配置说明,经过长时间的试错,可以确认以下几件事情,避免让大家进坑。 1,DMA是否需要开中断?答案是,不需要开中断。 DMA传输只要配置到串口接收端口上,在串口数据(一般会使用IDLE空闲中断)来临会自动调用DMA程序,DMA负责把串口上的数据转移到片上RAM中,记得,DMA转移时不需要DMA中断动作的,如果加了DMA中断,轻则程序不丝滑,重则程序卡死而找不到原因。 2,DMA与串口是否有对应关系?答案是,看具体芯片而定。对于stm32F系列芯片来说,很多都需要做对应关系,但是对于stm32G系列芯片来说,已经完全不需要做对应关系了。这个前期去芯片手册中查找清楚即可。 3,DMA优先级如何设置?答案是,一般不需要特殊配置,从LOW到HIGH,配置起来问题都不大。重点是,需要调用DMA的外设,尽量避免同时持续不断的进行数据传输,一般来说,串口或者ADC通过DMA转移到片内RAM的时间,是以指令数来计的,对于48M以上的stm32时间一般在us级以下,所以,优先级在使用少量DMA的时候,完全不是问题。只有在DMA使用超过5个以上,且外设数据持续不停、通信速率又非常高的时候,才会发生抢占优先级的问题。 三、程序解析1、串口中断,为什么把回调函数放在系统函数后面?答案是,为了避免寄存器异常。系统函数内的判断机制相对完善,寄存器的配置做了大量的处理,这里我们把回调函数放在前面,会在串口寄存器没有配置到合理状态时,就做了一系列操作,大部分时候不会出什么问题,但会经常性冒出一些串口接收异常出来,造成程序跑飞。 2、回调函数的详解。u16 ?t = USART_RX_DELAY_DMA_TRANSFER;? //这个参数定义的目的是为了让串口中断发生时,系统能停下来等一等DMA彻底完成。 ? __HAL_UART_CLEAR_IDLEFLAG(huart);? //此句清除IDLE串口空闲中断标志位,使得串口不会持续进入空闲中断(空闲中断的原理是检测带上升沿的高电平,一点点干扰就能引起,所以尽量接收完数据就先清除掉标志位 ?? ??? ?while(t--);? ? ? ? //等待DMA完成,这个数值可以自己设定,我选择的是300,相当于执行300个语句,64M主频,全程应该用不了10us ?? ??? ?HAL_UART_DMAStop(huart);? ? ? ? //这一句比较关键,这是停止DMA传输的命令,如果不做这个动作,你会发现,第一次接收的时候,可以完整接收数据,后续再接收时,每次只能接收到1个字节,这也是很多人使用DMA容易出现的错误 ?? ??? ?rec_len = (USART_RX_MAX - __HAL_DMA_GET_COUNTER(&USART_DMA_RX));? ? ? ? //获取接收到的数据长度,这个一般是用来后续判断使用的,接收到正常长度的数据,就可以认为完成了一次完整接收,否则就抛弃本次接收的数据 ?? ??? ?if( rec_len > 0?&& rec_len!= USART_RX_MAX)? //这里加了一个不等于全长的判断,避免很多时候明明没有接收到数据,异常导致的中断,结果使得程序一直向错误的方向飞奔 ?? ??? ??? ?rx_f = 1;? ? ? ? //接收完成标志,这个标志还可以添加更多判断条件,设置标志的目的是为了让中断尽快结束,同时,让主程序知道串口中断已经完成,方便调用处理函数。 ?? ??? ?HAL_UART_Receive_DMA(huart, rx_buf,USART_RX_MAX); ?//重新打开DMA接收,并且,只有在这个环节,才能重新打开DMA,使用其他的DMA指令都会造成DMA启动异常,查看一下原代码,能找到对应函数的问题及关键。 |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 8:57:12- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |