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

20、DMA----释放CPU压力,加快传输

1、DMA介绍

DMA,全称为:Direct Memory Access,即直接存储器访问。DMA传输方式无需CPU直接控制传输,也没有中断处理方式那样保留现场和恢复现场的过程,通过硬件为RAM与I/O设备开辟一条直接传送数据的通路,能使CPU的效率大为提高。

STM32F103内部有2个DMA控制器(DMA2仅存大容量产品中),DMA1有7个通道,DMA2有5个通道。每个通道专门用来管理来自于一个或多个外设对存储器访问的请求,一个仲裁器来协调各个DMA请求的优先权。

DMA有以下特性

  • 每个通道都直接连接专用的硬件DMA请求,每个通道都支持软件触发。通过软件来配置。
  • 优先权可以通过软件编程设置,有四个等级:很高、高、中、低,优先权相同时由硬件决定。
  • 独立源和目标数据区的传输宽度,可以根据字节、半字、全字,模拟打包和拆包过程。源和目标地址必须按照数据传输宽度对齐。
  • 支持循环的缓冲器管理。
  • 每个通道有3个事件标志:DMA半传输、DMA传输完成、DMA传输出错,3个事件标志逻辑或成为一个独立中断请求。
  • 存储器和存储器间的传输。
  • 外设和存储器,存储器和外设的传输。
  • 闪存、SRAM、外设SRAM、APB1、APB2、AHB外设都可以作为访问的源和目标。
  • 最大传输数目:65536

1.1、DMA框图

STM32F103ZET6有两个DMA控制器,DMA1和DMA2。

  • ①DMA请求: 外设想要通过DMA来传输数据,必须先给DMA控制器发送DMA请求,DMA收到请求信号后,控制器会给外设一个应答信号,当外设应答后且DMA控制器收到应答信号后,就会启动DMA传输,直到传输完毕。
  • ②通道:DMA具有12个独立可编程的通道,其中DMA1有7个通道,DMA2有5个通道,每个通道对应不同的外设的DMA请求。虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个,不能同时接收多个。
  • ③仲裁器:当发生多个DMA通道请求时,就会由仲裁器管理,仲裁器管理DMA通道请求分为两个阶段。第一阶段属于软件阶段,可以在DMA_CCRx寄存器中设置,有4个等级:非常高,高,中和低四个优先级。第二阶段属于硬件阶段,两个或以上的DMA通道请求设置的优先级一样,则他们优先级取决于通道编号,编号越低优先权越高,比如通道0高于通道1。DMA1控制器拥有高于DMA2控制器的优先级。

1.2、DMA请求映射表

2、DMA函数

DMA_HandleTypeDef结构体类型指针变量:

typedef struct __DMA_HandleTypeDef
{void                                *Instance;      /* 寄存器基地址 */DMA_InitTypeDef                     Init;           /* DAM 通信参数 */HAL_LockTypeDef                     Lock;           /* DMA 锁对象 */ __IO HAL_DMA_StateTypeDef           State;          /* DMA 传输状态 */ void                                *Parent;        /* 父对象状态,HAL库处理的中间变量 */ void(*XferCpltCallback)( struct __DMA_HandleTypeDef *hdma);    /*DMA传输完成回调*/ void(* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);/* DMA一半传输完成回调 */void(* XferM1CpltCallback)( struct __DMA_HandleTypeDef * hdma); /* DMA传输完整的Memory1回调 */void(* XferM1HalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);/* DMA传输半完全内存回调 */void(* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma);/*DMA传输错误回调*/void(* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma);/* DMA传输中止回调 */__IO uint32_t                       ErrorCode;              /* DMA存取错误代码 */DMA_TypeDef                         *DmaBaseAddress;        /* DMA通道基地址 */uint32_t                            ChannelIndex;           /* DMA通道索引 */ 
}DMA_HandleTypeDef;

  • Instance:是用来设置寄存器基地址,如果设置的对象是串口1的发送,串口1的DMA传输需要用到的是DMA1的通道4,即DMA1_Channel4。
  • Parent:是HAL库处理中间变量,用来指向DMA通道外设句柄。
  • XferCpltCallback:传输完成回调函数入口地址
  • XferHalfCpltCallback:半传输完成回调函数入口地址
  • XferM1CpltCallback:Memory1传输完成回调函数入口地址
  • XferErrorCallback:传输错误回调函数入口地址
  • Init:它是DMA_InitTypeDef结构体类型变量
typedef struct 
{    uint32_t Direction;               /* 传输方向,例如存储器到外设DMA_MEMORY_TO_PERIPH */  uint32_t PeriphInc;               /* 外设(非)增量模式,非增量模式DMA_PINC_DISABLE */   uint32_t MemInc;                  /* 存储器(非)增量模式,增量模式DMA_MINC_ENABLE */   uint32_t PeriphDataAlignment;     /* 外设数据大小:8/16/32位 */ uint32_t MemDataAlignment;        /* 存储器数据大小:8/16/32位 */ uint32_t Mode;                    /* 模式:循环模式/普通模式 */     uint32_t Priority;                /* DMA优先级:低/中/高/非常高 */  
}DMA_InitTypeDef;
  • HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma);DMA的初始化函数
  • __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA1时钟使能 */ __HAL_RCC_DMA2_CLK_ENABLE(); /* DMA2时钟使能 */
  • __HAL_LINKDMA(&g_uart1_handler, hdmatx, g_dma_handle);连接DMA和外设句柄。
  • 外设的DMA发送、启动传输函数。
  • __HAL_DMA_GET_FLAG(&g_dma_handle, DMA_FLAG_TC4);查询DMA传输通道的状态
  • __HAL_DMA_GET_COUNTER(&g_dma_handle);获取当前传输剩余数据量
  • __HAL_DMA_SET_COUNTER (&g_dma_handle, 1000);设置对应的DMA数据流传输的数据量大小
  • DMA中断函数
    • DMA中断对于每个通道都有一个中断服务函数
    • HAL库提供了通用DMA中断处理函数HAL_DMA_IRQHandler, 在该函数内部,会对DMA传输状态进行分析,然后调用相应的中断处理回调函数:
      • 发送完成回调函数
      • 发送一般回调函数
      • 接收完成回调函数
      • 接收一半回调函数
      • 传输错误回调函数
http://www.xdnf.cn/news/18888.html

相关文章:

  • 无人机航拍数据集|第30期 无人机腰果成熟度目标检测YOLO数据集3098张yolov11/yolov8/yolov5可训练
  • Day8--HOT100--160. 相交链表,206. 反转链表,234. 回文链表,876. 链表的中间结点
  • 艾利特石油管道巡检机器人:工业安全的智能守护者
  • 高通平台wifi--p2p issue
  • leetcode 17.04 消失的数字
  • 理解Vuex的辅助函数,分析mapState、mapGetters、mapMutations和mapActions各个应用场景
  • SQL 语句拼接在 C 语言中的实现与安全性分析
  • 大模型应用实战:构建企业知识库 RAG 系统(含权限控制 + 多轮对话)
  • 无线USB转换器TOS-WLink网盘更新--TOS-WLink使用帮助V1.0.pdf
  • 【C++游记】List的使用和模拟实现
  • 矩阵系统源代码开发,支持OEM贴牌
  • 5G与6G技术演进与创新对比分析
  • 我们为你连接网络,安装驱动程序
  • 车载诊断架构 --- DTC Event与DTC Status的对应关系
  • AWS ECS 成本优化完整指南:从分析到实施的最佳实践
  • CVPR 2025端到端自动驾驶新进展:截断扩散模型+历史轨迹预测实现精准规划
  • Frida 加密解密算法实现与应用指南
  • 【Linux】协议的本质
  • 基于深度学习的翻拍照片去摩尔纹在线系统设计与实现
  • Java基础第4天总结(继承)
  • 小明的Java面试奇遇之发票系统相关深度实战挑战
  • 论文阅读:VACE: All-in-One Video Creation and Editing
  • 纯净Win11游戏系统|24H2专业工作站版,预装运行库,无捆绑,开机快,游戏兼容性超强!
  • Linux应急响应一般思路(二)
  • 【Docker基础】Docker-compose多容器协作案例示例:从LNMP到分布式应用集群
  • 同步阻塞和异步非阻塞是什么?
  • 学习做动画1.简易行走
  • springBoot如何加载类(以atomikos框架中的事务类为例)
  • MIT 6.5840 (Spring, 2024) 通关指南——入门篇
  • MYSQL-表的约束(下)