前期准备:

  1. STM32CubeMX
  2. STM32RCT6核心板
  3. IDE Keil(MDK-ARM)

关于DMA

1. 什么是DMA?

DMA(Direct Memory Access,直接存储器访问) 提供在外设与存储器存储器和存储器外设与外设之间的高速数据传输使用。它允许不同速度的硬件装置来沟通,而不需要依赖于CPU,在这个时间中,CPU对于内存的工作来说就无法使用。

这里的外设指的是spi、usart、iic、adc等基于APB1 、APB2或AHB时钟的外设,而这里的存储器包括自身的闪存(flash)或者内存(SRAM)以及外设的存储设备都可以作为访问地源或者目的。

2. DMA的意义

传感器A获取到了数据,我需要把获取到的数据交给传感器B使用,正常来说,需要CPU控制,把A获取到的数据赋给B。但如果使用DMA,我可以将A与B之间建立一个专门传输数据的通道,CPU无需介入,对于非常大的数据需要转移时,DMA无疑大大节省了CPU的资源

优点: 控制简单,它适用于数据传输率很高的设备进行成组传送。
缺点: 在DMA控制阶段,CPU无法访问内存,内存的效能没有充分发挥,相当一部分内存工作周期是空闲的。这是因为,外围设备传送两个数据之间的间隔一般总是大于内存存储周期,因此许多空闲的存储周期不能被CPU利用。

3. DMA的结构器

2个DMA控制器,DMA1有7个通道


DMA2有5个通道

1个通道同一时间只能进行一个,例如通道 1 的几个 DMA1 请求(ADC1、TIM2_CH3、TIM4_CH1),这几个是通过逻辑或到通道 1 的,这样我们在同一时间,就只能使用其中的一个。其他通道也是类似的

3. DMA的传输方式

  • DMA_Mode_Normal(正常模式)
    一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次
  • DMA_Mode_Circular(循环传输模式)
    当传输结束时,硬件自动会将传输数据量寄存器进行重装,进行下一轮的数据传输。 也就是多次传输模式

4. DMA及通道的优先级

优先级管理采用软件+硬件:

  • 软件:每个通道的优先级可以在DMA_CCRx寄存器中设置,有4个等级
    最高级>高级>中级>低级

  • 硬件:如果2个请求,它们的软件优先级相同,则较低编号的通道比较高编号的通道有较高的优先权。比如:如果软件优先级相同,通道2优先于通道4

在大容量产品和互联型产品中,DMA1控制器拥有高于DMA2控制器的优先级。

5. DMA中断

DMA的每个通道都有 3 个事件标志(DMA 半传输,DMA 传输完成和 DMA 传输出错),这 3 个事件标志逻辑或成为一个单独的中断请求
可以通过设置寄存器的不同位来打开这些中断

6.指针递增模式

外设和存储器指针在每次传输后可以自动向后递增或保持常量。当设置为增量模式时,下一个要传输的地址将是前一个地址加上增量值

STM32CubeMX部分

1.配置时钟

选择STM32F103RCTx系列芯片,配置时钟的同时会自动配置IO口引脚

将HCLK设置为最大频率72MHz

2.配置USART和DMA

配置USART,【STM32】HAL库 CubeMX例程三—串口中断通信(2)(附工程源码)文章有讲解过,这里就不再赘述

DMA Settings ——> Add


然后选择USART1_RX,接着同样步骤再把USART1_TX添加进来

  • DMA Request(DMA请求): USART1_RX、USART1_TX
  • Channel(通道): 通道5、通道4
  • Dirction (DMA传输方向): Peripheral To Memory(外设到内存)、Memory To Peripheral(内存到外设 )
  • Priority(优先级): 低、低
  • Mode(模式): 正常、正常
  • Increment Address(地址指针递增): 1.这里因我们是一直往固定外设地址&USART1发送数据,所以地址不递增 2.这里我们的场景是将内存中连续存储单元的数据发送到串口,毫无疑问内存地址是需要递增的
  • Data Width(数据宽度): 字节、字节

    USART1使能中断

3.工程生成



工程管理依旧是这几个选项,然后GENERATE CODE,STM32CubeMX部分完成

MDK 5部分

//DMA函数
· HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);串口DMA模式发送
· HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);串口DMA模式接收
· HAL_UART_DMAResume(&huart1); 恢复串口DMA
· HAL_UART_DMAPause(&huart1) 暂停串口DMA
· HAL_UART_DMAStop(&huart1); 结束串口DMA

1. DMA串口发送

在main.c中添加

 /* USER CODE BEGIN Init */uint8_t Senbuff[] = "Q大帅のUART DMA Test Success ! \r\n";   /* USER CODE END Init */

在while里写入

  while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));HAL_Delay(1000);     }

编译下载时需要选择相对应的下载器,勾选以下

效果如图

2. IDLE接收(串口空闲中断接收)

当DMA串口接收开始后,DMA通道会不断的将发送来的数据转移到内存,那该如何判断串口接收是否完成从而及时关闭DMA通道?如何知道接收到数据的长度?答案便是使用串口空闲中断
思路流程:

  1. 开启串口DMA接收
  2. 串口收到数据,DMA不断传输数据到内存
  3. 一帧数据发送完毕,串口暂时空闲,触发串口空闲中断
  4. 在中断服务函数中,可以计算刚才收到了多少个字节的数据
  5. 存储接收到的数据,清除标志位,开始下一帧接收

在原有代码上更改

//在main.c定义3个全局变量
/* USER CODE BEGIN Includes */
uint8_t rx_buffer[100];   //接收数据的数组
volatile uint8_t rx_len = 0; //接收数据的长度
volatile uint8_t recv_end_flag = 0; //接收结束标志位
/* USER CODE END Includes */
  /* USER CODE BEGIN 2 */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);  //开启空闲中断
HAL_UART_Receive_DMA(&huart1,rx_buffer,100);  //开启DMA接收中断/* USER CODE END 2 */

在stm32f1xx_it.c文件中

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 */uint8_t tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE状态if((tmp_flag != RESET))//判断接收是否结束{ // recv_end_flag = 1; //接收结束__HAL_UART_CLEAR_IDLEFLAG(&huart1);//清楚标志位HAL_UART_DMAStop(&huart1); uint8_t temp=__HAL_DMA_GET_COUNTER(&hdma_usart1_rx);                 rx_len =100-temp; //计算数据长度HAL_UART_Transmit_DMA(&huart1, rx_buffer,rx_len);//发送数据HAL_UART_Receive_DMA(&huart1,rx_buffer,100);//开启DMA}/* USER CODE END USART1_IRQn 1 */
}

效果如图

本期工程文档——>Gitee

【STM32】HAL库——串口DMA通信(三)相关推荐

  1. STM32 HAL库 串口DMA接收不定长数据

    STM32 HAL库 串口DMA接收不定长数据 整体思路:我是用的CUBEMX软件生成的工程,使能了两个串口,串口2用来接收不定长的数据,串口1用来发送串口2接收到的数据:串口2我找了一个UBLOX卫 ...

  2. STM32 HAL库 串口DMA(收发)和STM32串口中断接收(接收时间管理机制)+ESP8266 wifi模组通信问题

    一.HAL库 串口 DMA+ESP8266模组通信问题 用STM32 HAL库串口的DMA发送和空闲中断接收处理数据,单片机发送AT指令给ESP8266 wifi模组问题:单片机连续几次给wifi模组 ...

  3. STM32 HAL库串口同时收发,接收卡死?

    STM32 使用 HAL库串口同时收发,使用踩坑史 = =!......by 矜辰所致 目录 前言 一. HAL 库串口收发 1.1 串口发送 1.2 串口接收 1.2.1 标准库接收 1.2.1 H ...

  4. STM32 HAL库串口收发数据

    STM32 HAL库串口收发数据 许多传感器的使用方法是:单片机给传感器发送一帧数据,然后传感器返回单片机一帧有用数据,所以串口的收发功能十分重要. STM32cubeMX的配置 时钟和下载方式就不讲 ...

  5. STM32CubeMX HAL库串口+DMA数据发送不定长度数据接收

    参考资料:1.ST HAL库官网资料 2.https://blog.csdn.net/u014470361/article/details/79206352#comments 一.STM32CubeM ...

  6. STM32 hal库串口空闲中断最新用法

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.串口空闲中断是什么? 二.使用步骤 1.hal库空闲中断接收函数 2.使用方法 3.最终效果 实际效果 总结 前言 ...

  7. hal库串口dma卡死_STM32 HAL库 串口DMA发送完成中断

    近期使用STM32驱动MAX3485进行485通信,发现STM32F103C8并不自带硬件485首发功能,需要软件上控制IO高低来驱动MAX3485进行485接收.485发送. 根据MAX3485手册 ...

  8. hal库串口dma卡死_HAL库版DMA循环模式串口数据收发

    在<STM32CubeMX初识与工程创建>的基础上,首先对串口进行设置,以实现通过串口对数据的收发.STM32CubeMX生成的HAL库中,提供了三类串口数据收发的接口,分别为阻塞模式,非 ...

  9. STM32 HAL库ADC+DMA(非定时器)代码和遇到的问题

    目录 一.整体说明 二.部分知识点预览 三.代码部分 四.遇到的问题及现象 (1)仿真进入错误 (2)非连续模式软件触发时adcbuf里面的数据不对 (3)HAL库的ADC DMA相关中断的嵌套实现 ...

最新文章

  1. laravel5.6 数组传递到前端
  2. python开发的比较知名的游戏-游戏排行榜-Python实现
  3. JSP EL表达式 格式化日期
  4. EOJ_1017_座位分配
  5. 文本文档TXT每行开头结尾加内容批处理代码
  6. P4323-[JSOI2016]独特的树叶【换根dp,树哈希】
  7. 25--最后一个单词的长度
  8. 2017 年十大网页设计趋势
  9. bzoj 1078 [SCOI2008]斜堆 —— 斜堆
  10. Atitit prj tek dfkt 项目常见技术难点目录第一章 开发效率 2第一节 更加简单的语言 2第二节 简单
  11. 【回归预测】基于matlab离群鲁棒极限学习机(ORELM)求解回归预测问题【含Matlab源码 1441期】
  12. Vector原理与基本使用
  13. python机器学习 | 入门介绍
  14. 如何下载酷家乐的3D全景图效果图,并生成本地离线版vr全景漫游
  15. http://95u.free.fr/index.php,Electronic Software Distribution Service
  16. 数学建模国赛论文latex代码汇总
  17. 今夜酒店特价:订得早,不如订得好
  18. 【CodeForces】【状压DP】1155F-Delivery Oligopoly
  19. 常见的请求错误HTTP状态码
  20. 黑鹰的VIP数据库(一)

热门文章

  1. Redis从青铜到王者,从环境搭建到熟练使用,看这一篇就够了,超全整理详细解析,赶紧收藏吧
  2. 游戏陪玩平台源码开发中阿里云云存储OSS功能介绍
  3. android hmac加密,android hmacSha256 加密
  4. js报未定义_JS的未定义和undefined
  5. jsplumb应用场景快速开发
  6. 如何设置小型企业服务器机房
  7. mealy machine和moore machine
  8. linux中如何递归搜索文件,关于linux:递归查找具有特定扩展名的文件
  9. 数字货币如何影响货币体系_如何加入数字货币行业
  10. Excel(WPS部分功能不适用)技巧:快速找出重复值