IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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接收(不定长)汇总

先提供一份测试完全没问题的代码,后面详解一下,以下是在中断文件中的回调函数。

void usart_rx_cb(UART_HandleTypeDef* huart)
{
		u16  t = USART_RX_DELAY_DMA_TRANSFER;
		__HAL_UART_CLEAR_IDLEFLAG(huart);  
		while(t--);
		HAL_UART_DMAStop(huart);
		rec_len = (USART_RX_MAX - __HAL_DMA_GET_COUNTER(&USART_DMA_RX));
		if( rec_len > 5 && rec_len!= USART_RX_MAX) 
		{			rx_f = 1;	}
		HAL_UART_Receive_DMA(huart,rx_buf,USART_RX_MAX);  //重新打开DMA接收
}

下面是串口中断函数配置

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 */
  if(0 != __HAL_UART_GET_FLAG(&USART_BUS, UART_FLAG_IDLE))
	  usart_rx_cb(&USART_BUS);
  /* USER CODE END USART1_IRQn 1 */
}

然后,我们从头开始说起。

一、串口配置问题

串口配置属于比较基础的,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中断
?? ?HAL_UART_Receive_DMA(&USART,rx_buf,USART_RX_MAX);

二、串口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例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-12 19:45:23  更:2021-11-12 19:46:10 
 
开发: 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-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码