这一章在干嘛?

DMA 实验:DMA 控制器架构、通道映射、数据流 vs FIFO、Memory-to-Memory 与外设到内存模式、UART DMA 收发。从此 CPU 从搬运工解放出来。

25.1 DMA 简介

25.2 硬件设计

25.3 程序设计

25.4 下载验证

25.1 DMA 简介

DMA(Direct Memory Access)= 直接存储器访问。

  • 硬件在 RAM 与外设之间直接搬运数据;
  • 不经过 CPU,不打断程序运行;
  • 传输完成触发中断。

F407 有 2 个 DMA 控制器,共 16 个数据流,每个数据流 8 个通道。

DMAx数据流用途
DMA10~7USART/RCC/ADC/TIM/I2C/SPI 等
DMA20~7USART/SDIO/ADC/DCMI/Hash 等

原书图 25.1.1:DMA 控制器框图原书图 25.1.1:DMA 控制器框图

通道优先级:软件 4 档(低/中/高/超高),相同时硬件编号小优先。

DMA ≠ 中断:中断需要 CPU 保存现场恢复现场;DMA 完全在硬件完成,CPU 完全可以睡大觉。

25.2 硬件设计

本实验:USART1 DMA 发送一段字符串,DMA 接收固定长度数据。

25.3 程序设计

25.3.1 CubeMX 配置

  • USART1 → DMA Settings → Add
  • RX: DMA1 Stream0, Channel 4 (USART1_RX)
  • TX: DMA1 Stream7, Channel 4 (USART1_TX)
  • NVIC: USART1 global interrupt + DMA1 stream0 global interrupt

25.3.2 关键代码

// 启动 DMA 接收
HAL_UART_Receive_DMA(&huart1, rx_buf, RX_LEN);

// 发送一段数据
HAL_UART_Transmit_DMA(&huart1, tx_buf, TX_LEN);

// 接收完成回调
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart->Instance == USART1) {
        // 处理 rx_buf
        HAL_UART_Receive_DMA(&huart1, rx_buf, RX_LEN);  // 重启
    }
}

原书图 25.3.2.1:USART DMA 收发流程图原书图 25.3.2.1:USART DMA 收发流程图

原书图 25.3.3.1:DMA 数据流通道映射原书图 25.3.3.1:DMA 数据流通道映射

25.3.3 Memory-to-Memory

DMA 也可在 RAM 内部搬运(如 memcpy 加速):

HAL_DMA_Start(&hdma, src, dst, len);
HAL_DMA_PollForTransfer(&hdma, HAL_DMA_FULL_TRANSFER, 100);

25.4 下载验证

串口助手输入字符串 → MCU 自动 DMA 接收 → 回环发送;同时开发板 LCD 显示 DMA 进度条。

原书图 25.4.1:DMA 串口回环测试原书图 25.4.1:DMA 串口回环测试