tags: [source-summary] type: source source: "尚硅谷嵌入式技术之STM32单片机(进阶篇)V1.0.1 — DMA章节 + 配套代码28~31" author: "尚硅谷研究院" date: 2026-07-15
用生活理解:DMA 就像公司里的快递员——以前你要自己去取文件(CPU 轮询/中断读外设),现在快递员帮你送了(DMA 控制器自动搬运),你就可以专心做其他重要工作。快递送到后喊你一声(完成中断)即可。
DMA(Direct Memory Access)允许外设与存储器之间直接传输数据,不需要 CPU 参与。
传统方式(无 DMA):
CPU 读取外设数据寄存器 → CPU 写入内存 → CPU 继续下一字节
DMA 方式:
CPU 配置 DMA 通道后 → DMA 控制器自动搬运 → 搬运完成通知 CPU
| DMA1 通道 | 外设请求 |
|---|---|
| CH1 | ADC1、TIM2_CH3、TIM4_CH1 |
| CH2 | USART1_TX、SPI1_RX、TIM1_CH1 |
| CH3 | USART1_RX、SPI1_TX、TIM1_CH2 |
| CH4 | SPI2_RX、SPI1_RX、USART1_TX |
| CH5 | SPI2_TX、USART2_TX、TIM1_CH4 |
| CH6 | USART2_RX、ADC3、TIM1_CH1 |
| CH7 | USART3_TX、ADC3、TIM1_CH2 |
文件:stm32_base/28_dma_mem2mem_register/Hardware/DMA/dma.c
#include "dma.h"
#define SRC_ADDR ((uint32_t)0x20000000) // 源地址(SRAM)
#define DST_ADDR ((uint32_t)0x20000010) // 目的地址(SRAM偏移)
void DMA_Init(void)
{
// 1. 开启DMA1时钟
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
// 2. 清除通道1的所有标志
DMA1->IFCR |= DMA_IFCR_CGIF1; // |= 写1清除所有标志
// 3. 配置DMA通道1
DMA1_Channel1->CPAR = SRC_ADDR; // 外设地址 = 源地址
DMA1_Channel1->CMAR = DST_ADDR; // 存储器地址 = 目的地址
DMA1_Channel1->CNDTR = 10; // 传输次数 = 10(10个32位字)
// 4. 配置控制寄存器CCR
DMA1_Channel1->CCR |= DMA_CCR1_MEM2MEM; // MEM2MEM=1: 内存到内存模式
DMA1_Channel1->CCR |= DMA_CCR1_PL; // PL[1:0]=11: 最高优先级
DMA1_Channel1->CCR |= DMA_CCR1_MSIZE; // MSIZE=10: 存储器数据宽度32位
DMA1_Channel1->CCR |= DMA_CCR1_PSIZE; // PSIZE=10: 外设数据宽度32位
DMA1_Channel1->CCR |= DMA_CCR1_MINC; // MINC=1: 存储器地址递增
DMA1_Channel1->CCR |= DMA_CCR1_PINC; // PINC=1: 外设地址递增
DMA1_Channel1->CCR |= DMA_CCR1_CIRC; // CIRC=1: 循环模式
DMA1_Channel1->CCR |= DMA_CCR1_TCIE; // TCIE=1: 传输完成中断使能
// 5. 使能通道
DMA1_Channel1->CCR |= DMA_CCR1_EN;
// 6. NVIC使能DMA中断
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}
// DMA传输完成中断
void DMA1_Channel1_IRQHandler(void)
{
if (DMA1->ISR & DMA_ISR_TCIF1) // 检查传输完成标志
{
DMA1->IFCR |= DMA_IFCR_CTCIF1; // 清除完成标志
// 传输完成:目的地址已包含源数据的副本
}
}
| DMA寄存器 | 功能 |
|---|---|
| CCR.EN | 通道使能 |
| CCR.PL[1:0] | 通道优先级 |
| CCR.MSIZE[1:0] / PSIZE[1:0] | 数据宽度(8/16/32位) |
| CCR.MINC / PINC | 地址递增使能 |
| CCR.CIRC | 循环模式 |
| CCR.DIR | 传输方向(外设→内存 / 内存→外设) |
| CCR.MEM2MEM | 内存到内存模式(无视外设请求) |
| CNDTR | 传输次数(每次传输后自减) |
| CPAR | 外设地址 |
| CMAR | 存储器地址 |
| ISR | 中断状态寄存器(TCIF/HTIF/TEIF等) |
| IFCR | 中断标志清除寄存器(写1清除) |