当前位置: 首页 > news >正文

STM32 DMA通信详解

STM32 DMA通信详解

DMA(Direct Memory Access,直接内存访问)是STM32微控制器中一种重要的数据传输机制,它允许外设与内存之间或内存与内存之间直接传输数据,而无需CPU的干预。这种机制可以显著提高系统性能,特别是在需要高速数据传输或大量数据处理的场景中。

一、DMA基础概念

1. DMA工作原理

DMA控制器是一种专门设计用于在系统内不同组件之间高效传输数据的硬件模块。其核心工作原理是:

  1. 初始化阶段:CPU配置DMA控制器,设置源地址、目标地址、传输长度等参数

  2. 传输阶段:当外设或软件触发DMA请求时,DMA控制器接管总线控制权

  3. 数据搬运:DMA控制器直接在源地址和目标地址之间搬运数据

  4. 完成通知:传输完成后,DMA控制器可以产生中断通知CPU1

2. STM32 DMA特性

STM32系列MCU的DMA控制器具有以下特点:

  • 多通道设计:如STM32F1系列有2个DMA控制器(DMA1和DMA2),DMA1有7个通道,DMA2有5个通道1

  • 优先级管理:每个通道有可编程优先级,通过仲裁器处理多个同时请求

  • 多种传输模式:支持单次传输(Normal)和循环传输(Circular)

  • 灵活的数据宽度:支持字节(8位)、半字(16位)和字(32位)传输7

二、DMA配置与使用

1. 使用STM32CubeMX配置DMA

STM32CubeMX工具可以简化DMA的配置过程:

  1. 启用DMA控制器:在"System Core"→"DMA"中启用所需的DMA控制器

  2. 配置DMA通道

    • 选择请求源(如USART1_TX/USART1_RX)

    • 设置优先级(低/中/高/非常高)

    • 选择传输模式(Normal或Circular)

    • 配置地址递增(外设地址通常不递增,内存地址通常递增)

    • 设置数据宽度(通常与相关外设匹配)37

  3. 配置相关外设:如USART、SPI等,并启用其DMA功能1

2. DMA编程接口

HAL库提供了简洁的DMA API:

// 启动DMA传输
HAL_UART_Transmit_DMA(&huart1, txBuffer, length);
HAL_UART_Receive_DMA(&huart1, rxBuffer, length);// DMA传输完成回调函数
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

三、常见DMA应用场景

1. 串口DMA通信

串口使用DMA可以显著降低CPU负载,特别适合高速或大数据量通信:

  • 发送数据:将数据从内存传输到USART_TDR寄存器

  • 接收数据:将数据从USART_RDR寄存器传输到内存

  • 不定长数据接收:结合IDLE中断实现不定长数据接收5

示例代码

// 启用IDLE中断
__HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);// IDLE中断处理
void USART1_IRQHandler(void) {if(__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE)) {__HAL_UART_CLEAR_IDLEFLAG(&huart1);HAL_UART_DMAStop(&huart1);uint16_t len = BUFFER_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx);// 处理接收到的数据...HAL_UART_Receive_DMA(&huart1, rxBuffer, BUFFER_SIZE);}HAL_UART_IRQHandler(&huart1);
}

2. SPI DMA通信

SPI接口使用DMA可以高效传输大量数据,特别适合与ADC、DAC、存储器等外设通信:

  • 配置SPI DMA

    c

    // SPI TX DMA配置
    hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi1_tx.Init.PeriphInc = DMA_PERRIPH_INC_DISABLE;
    hdma_spi1_tx.Init.MemInc = DMA_MEM_INC_ENABLE;
    // ...其他配置
  • 启动SPI DMA传输

    HAL_SPI_Transmit_DMA(&hspi1, txData, length);
    HAL_SPI_Receive_DMA(&hspi1, rxData, length);
    // 或同时收发
    HAL_SPI_TransmitReceive_DMA(&hspi1, txData, rxData, length);

3. 内存到内存DMA传输

DMA也可以用于高效的内存拷贝操作:

// 配置内存到内存DMA
hdma_memtomem.Init.Direction = DMA_MEMORY_TO_MEMORY;
// ...其他配置// 启动传输
HAL_DMA_Start(&hdma_memtomem, (uint32_t)src, (uint32_t)dest, length);

四、DMA优化技巧

  1. 双缓冲技术:使用两个缓冲区交替工作,提高吞吐量

  2. 数据对齐:确保DMA缓冲区地址与数据宽度对齐

  3. 缓存一致性:在Cortex-M7等有缓存的核心上,注意维护缓存一致性

  4. 合理设置优先级:根据实时性要求为不同DMA通道设置适当优先级

  5. 使用循环模式:对于连续数据流,使用循环模式避免频繁重新配置7

五、常见问题与调试

  1. DMA传输不启动

    • 检查DMA和外设时钟是否使能

    • 验证DMA配置参数是否正确

    • 确保DMA请求源与通道映射正确2

  2. 数据损坏或丢失

    • 检查缓冲区大小是否足够

    • 验证地址递增设置是否正确

    • 确保在传输完成前不访问缓冲区9

  3. 性能优化

    • 使用DMA突发传输

    • 合理设置FIFO阈值

    • 考虑使用LL库以获得更精细的控制4

六、高级应用

1. DMAMUX (DMA请求复用器)

新型STM32系列(如STM32G0/G4/H7)引入了DMAMUX模块,它提供了:

  • 更灵活的DMA请求映射

  • 更多触发源选择(如GPIO中断、定时器等)

  • 可配置的请求发生器4

配置示例

// 使能DMAMUX请求发生器
HAL_DMAEx_EnableMuxRequestGenerator(&hdma_muxgen);// 配置GPIO外部中断触发DMA
HAL_DMAEx_ConfigMuxRequestGenerator(&hdma_muxgen, &muxgen_config);

2. 分散/聚集DMA

某些高级STM32支持分散/聚集DMA,允许非连续内存区域的传输:

// 配置链表描述符
DMA_LinkNodeTypeDef node;
node.Init.Request = DMA_REQUEST_MEM2MEM;
node.Init.BlkHWRequest = DMA_HWREQUEST_SINGLEBURST;
// ...其他配置
HAL_DMAEx_List_BuildNode(&node, &node_config);// 创建链表
HAL_DMAEx_List_InsertNode(&list, &node);

总结

STM32的DMA功能为高效数据搬运提供了强大支持,合理使用DMA可以:

  1. 显著降低CPU负载,提高系统整体性能

  2. 实现更高带宽的数据传输

  3. 改善实时性,使CPU能更专注于关键任务

  4. 降低功耗,特别适合电池供电设备

通过STM32CubeMX工具和HAL库,开发者可以快速实现各种DMA应用场景,从简单的内存拷贝到复杂的外设数据流处理。

http://www.lryc.cn/news/590843.html

相关文章:

  • 求解偏微分方程的傅里叶积分解
  • ThreadLocal使用详解-从源码层面分析
  • Python 网络爬虫 —— requests 库和网页源代码
  • 智能体开发工具链全景图:IDE、调试器与监控平台
  • Fair-code介绍(Fair code)(一套新型软件模型:旨在“开源”“商业可持续性”中找到平衡)
  • Windows 11清理C盘方法大全:磁盘清理/禁用休眠/系统还原点/优化大师使用教程
  • Android默认背光亮度配置说明
  • 纯前端html实现图片坐标与尺寸(XY坐标及宽高)获取
  • SegNet:一种用于图像分割的深度卷积编码器解码器架构
  • RocketMQ 高可用集群架构与一致性机制解析
  • 【3D目标检测】Livox Tele-15采集的.lvx数据转.bag再转.pcd
  • 鲍威尔去留风波的AI量化解析:基于多模态数据驱动的金融市场脉冲响应研究
  • 达梦数据守护集群搭建(1主1实时备库1同步备库1异步备库)
  • 时序数据库选型指南 —— 为什么选择 Apache IoTDB?
  • javaweb学习开发代码_HTML-CSS-JS
  • Java面试(基础篇) - 第二篇!
  • slot=“trigger“ 覆盖了组件内部的 ref=“trigger“【详细来龙去脉版 5min】
  • Web开发 01
  • Python的“__name__“属性
  • visual freebasic教程-菜单栏
  • 视频码率是什么?视频流分辨率 2688x1520_25fps采用 h264格式压缩,其码率为
  • 线上协同办公时代:以开源AI大模型等工具培养网感,拥抱职业变革
  • Vim多列打开不同文件操作指南
  • Dijkstra 算法求解多种操作
  • 【真·CPU训模型!】单颗i7家用本,4天0成本跑通中文小模型训练!Xiaothink-T6-mini-Preview 技术预览版开源发布!
  • 腾讯云服务上下载docker以及使用Rabbitmq的流程
  • 闭包的两种设计模式
  • 【Android】ViewBinding(视图绑定)
  • OpenCV中常用特征提取算法(SURF、ORB、SIFT和AKAZE)用法示例(C++和Python)
  • YOLOv3 技术深度解析:从理论到实践的完整指南