STM32HAL库DMA和串口接收不定长字符串
Posted QWQ_DIODA
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32HAL库DMA和串口接收不定长字符串相关的知识,希望对你有一定的参考价值。
前言
前一阵子瞎搞,想整VS2019开发stm32,毕竟优雅的IDE界面谁能拒绝呐?
可是最后bug一堆。。。就先放弃了,于是就改回MDK5了。
瞎搞的时候就是搞得DMA串口接收不定长信息,既然搞了,总得有点收获吧
DMA部分
DMA就是一个有特权的搬运工,能在CPU管不着的情况下,自己吧数据从一个地址搬到另一个地址。
我们只需要知道告诉DMA:
要把数据从哪儿搬到哪儿,一次搬多少,不停的搬还是搬一次就行了
我们只需要设置DMA有货就搬,USART有多少搬多少就行了
即:循环模式,外设到内存,一次一字节,每次搬运数量必须大于自己定义的数组大小
USART部分
STM32的USART有很多个中断
平常我们接收数据一般所用为RXNE(读数据寄存器非空)中断
这种使用方式的缺点是只能接收定长的数据
但是,32的串口还有一个总线空闲中断IDLE!
也就是说,当你的接收缓冲寄存器里面完了没数据了就会产生一个中断
并且,他只会在RXNE被再次置高的时候,才能被置高,也就是说,你啥也不干导致总线空闲的时候,他也会很聪明的不打开中断。
步骤
- 定义一个接收缓冲的数组,不能低于你的最大传输数据量
- 初始化串口
- 初始化串口DMA(循环)
- 打开IDLE中断
- 开启DMA传输
- 在中断函数中判断IDLE中断是否执行
- 清空IDLE标志位
- 停止DMA传输(处理数据防止干扰)
- 获取数据长度
- 接收缓冲数组数据末尾加上 ‘\\0’
- 发送接收缓冲区数据,验证接收
- 重新打开DMA
代码
初始化
cubeMX
/*初始化全局变量*/
uint8_t Rx_buff[100];
uint32_t Rx_Length = 0;
usart.c
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
cubeMX自生成部分省略
/* USER CODE BEGIN USART1_MspInit 1 */
/* 打开DMA传输,地址为从USART_DR到Rx_Buff */
HAL_UART_Receive_DMA(&huart1,(uint8_t*)Rx_buff,100);
/* 打开串口IDLE中断 */
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
/* USER CODE END USART1_MspInit 1 */
中断部分
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(__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)!=RESET)
/* 清空IDLE标志位 */
__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_IDLE);
/* DMA传输停止 */
HAL_UART_DMAStop(&huart1);
/* 获取接收数据长度 */
Rx_Length = 100 - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
/* 在数据末尾添加 '\\0' 表示接收结束 */
Rx_buff[Rx_Length] = '\\0';
/* 像串口发送输出结果 */
printf("接受内容:%s\\n",Rx_buff);
printf("长度:%d\\n\\r",Rx_Length);
/* 重新打开DMA传输 */
HAL_UART_Receive_DMA(&huart1,(uint8_t*)Rx_buff,100);
/* USER CODE END USART1_IRQn 1 */
效果
接收的第一个数据无法接收,看了半天也不知道为啥,有懂的大佬可以说一下(真的感谢!!)
以上是关于STM32HAL库DMA和串口接收不定长字符串的主要内容,如果未能解决你的问题,请参考以下文章
STM32F103VET6基于STM32CubeMX创建串口中断+ DMA 不定长数据接收
STM32CubeMX HAL库串口+DMA数据发送不定长度数据接收