HAL 库开发笔记 - DMA
DMA(Direct Memory Access,直接存储器访问)允许不同速度的硬件装置直接沟通,而不需要依赖于 CPU 的大量中断负载。
基本原理
DMA 是什么
DMA 提供外设 / 存储器或存储器 / 存储器之间的高速数据传输,其过程中无需占用 CPU 资源。
如上图所示,STM32F4 系列有两个 DMA 控制器,共 12 通道(DMA1 有 7 个,DMA2 有 5 个)。DMA 控制器与 Cortex-M3 核心共享系统的数据总线。
简单地理解,当 CPU 懒得把一大串数据转移到另一个地方,或者说它还有更重要的事情要做的时候,就可以把这个任务丢给 DMA 去干,DMA 干完 / 出问题了跟 CPU 说一声就行。
DMA 的使用场景
- 串口通讯:最常见的使用情况,当有大量数据从串口读入或者写入的时候,让 DMA 处理。这样可以将 CPU 解放出来,让 CPU 处理更重要的事情。
- ADC:一般在需要 ADC 时的通道扫描模式下,可以用 DMA 处理。
- SD 卡读写:需要往 SD 卡里面读写大量数据的时候,一般也用 DMA 来处理。
DMA 的传输方向
- P2P(Peripheral to Peripheral,从外设到外设)。
- P2M(Peripheral to Memory,从外设到内存):一般用于传感器通过串口发送读数回单片机。
- M2P(Memory to Peripheral,从内存到外设):一般用于单片机通过串口发送数据到执行器。
- M2M(Memory to Memory,从内存到内存):MCU 内部的数据转移,常见于 Buffer 之间互相转移数据,或者从 Buffer 读写数据。只有 DMA2 能够进行 M2M 操作。
DMA 的传输模式
- DMA_Mode_Normal:正常模式。任务完成后就停止 DMA,如果还需使用,要再次手动启动。
- DMA_Mode_Circular: 循环传输模式。当传输结束时,硬件自动会将传输数据量寄存器进行重装,进行下一轮的数据传输。
常用的 DMA 函数参考
串口 DMA 发送数据
功能:串口通过 DMA 发送指定长度的数据。
参数:
- UART_HandleTypeDef *huart:UATR 的别名(如 : UART_HandleTypeDef huart1 -> huart1)
- *pData:需要发送的数据
- Size:发送的字节数
例子:
串口 DMA 接收数据
功能:串口通过 DMA 接收指定长度的数据。
参数:
- UART_HandleTypeDef *huart:UATR 的别名(如 : UART_HandleTypeDef huart1 -> huart1)
- *pData:需要存放接收数据的数组
- Size:接收的字节数
例子:
串口 DMA 恢复函数
作用:恢复 DMA 的传输
返回值:0(正在恢复);1(已经完成恢复)
DMA 串口传输实验
在 CubeMX 内配置 DMA
串口部分的配置请跳转文章 HAL 库开发笔记 - 串口通信。
配置完 USART 引脚和 NVIC 中断后,切换到 DMA Settings
标签页,按照下图进行配置:
- 点击
Add
添加通道(USART1_RX 与 USART1_TX) - 将两个的优先级都设置为
Medium
(中优先级) - DMA 传输模式为
Normal
(正常模式) - DMA 内存地址自增,每次增加一个 Byte(字节)
随后,在 System Core
标签页找到 DMA
,增加一个 MEMTOMEM
栏目,如图:
在代码内配置 DMA
main.c
/* USER CODE BEGIN Init */
uint8_t Senbuff[] = "Serial Output Message by DMA \r\n"; // 自定义发送的字符串
/* USER CODE END Init */
......
/* USER CODE BEGIN 3 */
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
HAL_Delay(1000);
}
/* USER CODE END 3 */
烧录程序,打开串口助手,即可看见循环发送的自定义数组。
参考与致谢
原文地址:https://wiki-power.com/
本篇文章受 CC BY-NC-SA 4.0 协议保护,转载请注明出处。