STM32单片机C语言DMA传输:DMA原理、配置和数据传输的专业级解析
发布时间: 2024-07-02 20:52:56 阅读量: 88 订阅数: 39
![STM32单片机C语言DMA传输:DMA原理、配置和数据传输的专业级解析](https://img-blog.csdnimg.cn/direct/b207022bc1a4422b84f70a6d786224f2.png)
# 1. DMA原理和架构**
DMA(直接存储器访问)是一种硬件机制,允许外设直接与内存进行数据传输,而无需CPU的干预。这可以大大提高数据传输速度,减少CPU负载。
STM32单片机中的DMA控制器具有以下主要架构:
- **DMA通道:**每个DMA控制器有多个通道,每个通道可以独立配置和控制。
- **DMA请求源:**DMA通道可以响应各种外设或内部事件的请求,触发数据传输。
- **DMA传输控制器:**传输控制器负责管理数据传输,包括源地址、目标地址、传输大小和传输类型。
- **DMA中断控制器:**中断控制器用于处理DMA传输完成或错误等事件。
# 2. DMA配置和初始化
### 2.1 DMA通道配置
DMA通道配置是DMA初始化过程中的关键步骤。它定义了DMA传输的源和目标地址、传输数据类型和传输方向。STM32单片机有多个DMA通道,每个通道都可以配置为传输不同的数据流。
DMA通道配置通常通过DMA控制寄存器(DMA_CNDTRx)来完成。该寄存器包含以下字段:
- **DIR**:传输方向,0表示从外设到内存,1表示从内存到外设
- **M2M**:内存到内存传输标志,0表示外设到内存或内存到外设传输,1表示内存到内存传输
- **PL**:优先级,0-3表示优先级,优先级高的通道优先传输
- **PSIZE**:外设数据大小,0表示8位数据,1表示16位数据,2表示32位数据
- **MSIZE**:内存数据大小,0表示8位数据,1表示16位数据,2表示32位数据
- **CIRC**:循环传输标志,0表示非循环传输,1表示循环传输
- **PINC**:外设地址递增标志,0表示外设地址不递增,1表示外设地址递增
- **MINC**:内存地址递增标志,0表示内存地址不递增,1表示内存地址递增
以下代码示例展示了如何配置DMA通道:
```c
/* 配置DMA通道1,从外设传输32位数据到内存 */
DMA_CNDTR1 = 100; // 传输100个32位数据
DMA_CNDTR1 |= DMA_DIR_0to1; // 从外设到内存
DMA_CNDTR1 |= DMA_PSIZE_32bit; // 外设数据大小为32位
DMA_CNDTR1 |= DMA_MSIZE_32bit; // 内存数据大小为32位
```
### 2.2 DMA中断配置
DMA中断配置允许在DMA传输完成或发生错误时触发中断。中断配置通常通过DMA中断控制寄存器(DMA_CCR1)来完成。该寄存器包含以下字段:
- **TCIE**:传输完成中断使能标志,0表示传输完成中断禁用,1表示传输完成中断使能
- **HTIE**:半传输中断使能标志,0表示半传输中断禁用,1表示半传输中断使能
- **TEIE**:传输错误中断使能标志,0表示传输错误中断禁用,1表示传输错误中断使能
- **DMEIE**:直接模式错误中断使能标志,0表示直接模式错误中断禁用,1表示直接模式错误中断使能
以下代码示例展示了如何配置DMA中断:
```c
/* 配置DMA通道1中断,使能传输完成中断 */
DMA_CCR1 |= DMA_TCIE;
```
### 2.3 DMA传输数据类型配置
DMA传输数据类型配置定义了DMA传输数据的类型。STM32单片机支持多种数据类型,包括8位、16位和32位数据。数据类型配置通常通过DMA控制寄存器(DMA_CNDTRx)来完成。该寄存器包含以下字段:
- **PSIZE**:外设数据大小,0表示8位数据,1表示16位数据,2表示32位数据
- **MSIZE**:内存数据大小,0表示8位数据,1表示16位数据,2表示32位数据
以下代码示例展示了如何配置DMA传输数据类型:
```c
/* 配置DMA通道1传输32位数据 */
DMA_CNDTR1 |= DMA_PSIZE_32bit;
DMA_CNDTR1 |= DMA_MSIZE_32bit;
```
# 3. DMA数据传输
### 3.1 DMA单次传输
DMA单次传输是最基本的传输模式,它允许一次性传输一个数据块。在单次传输模式下,DMA控制器会在传输完成时产生一个中断。
**配置单次传输:**
```c
/* 使能DMA通道 */
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
/* 设置传输方向 */
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_MEMORY_TO_MEMORY);
/* 设置源地址 */
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&source_buffer);
/* 设置目标地址 */
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&destination_buffer);
/* 设置传输大小 */
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_1, sizeof(source_buffer) / sizeof(uint32_t));
/* 启动传输 */
LL_DMA_EnableStream(DMA1, LL_DMA_CHANNEL_1);
```
**逻辑分析:**
* `LL_DMA_EnableChannel()`:使能指定的DMA通道。
* `LL_DMA_SetDataTransferDirection()`:设置传输方向,从内存到内存。
* `LL_DMA_SetMemoryAddress()`:设置源地址。
* `LL_DMA_SetPeriphAddress()`:设置目标地址。
* `LL_DMA_SetDataLength()`:设置传输大小,以字为单位。
* `LL_DMA_EnableStream()`:启动传输。
### 3.2 DMA循环传输
DMA循环传输允许在不产生中断的情况下连续传输多个数据块。在循环传输模式下,DMA控制器会在传输完成时自动重新启动传输。
**配置循环传输:**
```c
/* 使能DMA通道 */
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1);
/* 设置传输方向 */
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_1, LL_DMA_DIRECTION_MEMORY_TO_MEMORY);
/* 设置源地址 */
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_1, (uint32_t)&source_buffer);
/* 设置
```
0
0