文章内容
:
学习STM32 串口 DMA 通信原理和编程方法。使用 STM32CubeMX 和 HAL 库分别完成编程练习:
STM32 采用串口 DMA 方式,用 115200bps 或更高速率向上位机连续发送数据。
目录
1 何为DMA
1.1 DMA 概念
- 直接存储器访问 ( DMA ) :用于在外设与存储器之间以及存储器与存储器之间进行高速数据传输。 DMA 传输过程的初始化和启动由 CPU 完成,传输过程由 DMA 控制器来执行,无需 CPU 参与,从而节省 CPU 资源,提高利用率。
- 两个 DMA 控制器有12个通道( DMA1 有7个通道,DMA2 有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个 DMA 请求的优先权。
1.2 DMA 特性
- STM32 具备两个 DMA 控制器:DMA1 和 DMA2 ,每个控制器有8个数据流,每个数据流可以映射到8个通道(或请求);
- 每一个 DMA 控制器用于管理一个或多个外设的存储器访问请求,并通过总线仲裁器来协调各个DMA 请求的优先级;
- 数据流( stream )是用于连接传输源和传输目标的数据通路,每个数据流可以配置为不同的传输源和传输目标,这些传输源和传输目标称为通道( Channel );
- 具备16字节的 FIFO 。使能 FIFO 功能后,源数据先送入 FIFO,达到 FIFO 的触发阈值后,再传送到目标地址。
具体特性可以查看文章末尾的资料:《STM32中文参考手册_V10》的第10节 DMA 控制器。
1.3 DMA 数据传输方式
- 普通模式
传输结束后(即要传输数据的数量达到零),将不再产生 DMA 操作。若开始新的 DMA 传输,需在关闭 DMA 通道情况下,重新启动 DMA 传输。 - 循环模式
可用于处理环形缓冲区和连续数据流(例如 ADC 扫描模式)。当激活循环模式后,每轮传输结束时,要传输的数据数量将自动用设置的初始值进行加载, 并继续响应 DMA 请求。
1.4 HAL 库 DMA 函数
- 串口DMA方式发送函数:HAL_UART_Transmit_DMA
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size
- 功能:串口通过 DMA 发送指定长度的数据。
- 参数:
UART_HandleTypeDef *huart:UATR 的别名,串口句柄的地址;
*pData :需要发送的数据;
Size :发送的字节数; - 返回值:
HAL 状态值:HAL_OK 表示发送成功;HAL_ERROR 表示参数错误;HAL_BUSY 表示串口被占用。
2.串口DMA方式接收函数:HAL_UART_Receive_DMA
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size)
-
功能:串口通过DMA接受指定长度的数据。
-
参数:
UART_HandleTypeDef *huart :UATR 的别名,串口句柄的地址;
*pData :需要存放接收数据的数组;
Size :接受的字节数; -
返回值:
HAL 状态值:HAL_OK 表示发送成功;HAL_ERROR 表示参数错误;HAL_BUSY 表示串口被占用。
3.串口DMA恢复函数
HAL_UART_DMAResume(&huart1)
- 作用: 恢复DMA的传输。
- 返回值: 0 表示正在恢复;1 表示完成DMA恢复。
2 STM32CubeMX 配置 DMA
2.1 创建 CubeMX 工程
- 点击
File->New Pioject
,创建新工程 - 选择
STM32F103C8
芯片,点击 Start Project 进入工程即可 - 配置外设
RCC
,选择 HSE (外部高速时钟)为Crystal/Ceramic Resonator
(晶振/陶瓷谐振器)
- 设置串口
点击USATR1
;
设置 MODE 为Asynchronous
(异步通信);
基础参数:波特率为115200 Bits/s、传输数据长度为8 Bit、奇偶检验无、停止位1 接收和发送都使能;
GPIO 引脚自动设置USART1_RX / USART_TX
,不用处理;
NVIC Settings 一栏使能接收中断;
- 设置 DMA
USART1 的TX 、RX 分别对应DMA1 的通道 4 和通道 5
点击DMASettings
;
点击Add
添加通道;
选择USART_RX
、USART_TX
传输速率设置为中速;
DMA 传输模式为Normal
(正常模式);
DMA内存地址
自增,每次增加一个 Byte (字节);
- DMA 基础设置
点击System Core
;
点击DMA
;
在 DMA 设置界面添加 DMA 而没有开启对应外设的话 ,默认为MENTOMEN
;
DMA 传输模式为Normal
(正常模式);
DMA内存地址
自增,每次增加一个 Byte (字节); - 时钟配置
- 项目文件设置
- 点击
GENERATE CODE
生成工程
2.2 添加代码
- 在 main.c文件里添加:
/* USER CODE BEGIN Init */
uint8_t Senbuff[] = "\n\r\0 Congratulations, you did it! "; //定义数据发送数组
/* USER CODE END Init */
- while 循环里添加:
while (1)
{
/* USER CODE END WHILE */
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
HAL_Delay(1000);
/* USER CODE BEGIN 3 */
}
2.3 编译烧录
- 编译生成 hex 文件
- 烧录
注意
:烧录前将板子上的 BOOT0 置1,BOOT1 置0;烧录后,将板子断电,将 BOOT0 置0,BOOT1 置0,再上电才可连接串口。
2.4 串口调试
打开串口调试助手,设置好参数,打开 hex 文件,打开串口,即可看到如下效果。
3 总结
本文是关于 STM32 串口 DMA 通信编程,文章中对 DMA 通信进行了简要介绍,完成了一个简单的 DMA 实例。读者可以在下面的资料里,继续了解学习 DMA 通讯模式。
文章如有疑问或错误,敬请读者指正。
4 参考资料
1.《STM32中文参考手册_V10》提取码:luha
2.《第九章__串口通信(new).pdf》提取码:luha
3.【STM32】HAL库 STM32CubeMX教程十一—DMA (串口DMA发送接收)
4.【STM32】 DMA原理,步骤超细详解,一文看懂DMA