DMA介绍

本文介绍了DMA(直接存储器访问)在STM32中的应用,包括其工作原理、优点(速度快、CPU解耦)、特点(多个通道、优先级、FIFO模式等),以及基于STM32的DMA控制器使用HAL库的配置示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.简介

DMA介绍

  DMA是Direct Memory Access(直接存储器访问)的首字母缩写:是一种完全由硬件执行数据交换的工作方式。DMA控制器由CPU接管对总线的控制,不经过CPU直接在存储器和外设之间进行批量数据交换。
  在硬件系统中,主要有CPU(内核)、外设、内设(SRAM)、总线(如图1所示)等结构组成,数据经常要在存储器与外设直接转移,或是从外设A转移到外设B。在不使用DMA的情乱下,内核通过系统总线经过总线矩阵协调,使用AHB把外设例如ADC采集的数据读取到内核,然后内核再通过总线矩阵协调,把数据存放到内存SRAM中。而DMA可以取代这样的工作,由DMA控制器的DMA总线与总线矩阵协调,使用AHB把外设的数据经由DMA通道存放到内存SRAM,好处是提高数据的搬运速度。比如,使用DMA为多通道采集、采样频率高、连续输出数据的AD采集提供了更高效的办法。
在这里插入图片描述图1

  这里的外设一般是指外设的数据寄存器,比如ADC、SPI、I2C等外设的数据寄存器。存储器一般是指片内SRAM、外部存储器、片内Flash等。一句话概括就是使用DMA传输不需要占用CPU的资源,让CPU有足够的时间处理其他事情。

DMA传输的三大要素

  1. 传输源:DMA控制器从传输源读出数据;
  2. 传输目标:DMA控制器将数据传输的目标地址;
  3. 触发信号:用于触发一次数据传输的动作,执行一个单位的传输源至传输目标的数据传输;可以用来控制传输的时机。

DMA的优缺点:

  速度快是其主要有点,由于CPU根本不参加传送操作,省去了CPU取指令、取数、送数等操作。在数据传输过程中,没有保存现场、恢复现场之类的工作。存储器地址修改、传输字个数的计数等等,不需要有软件实现,直接由内部硬件线路实现。DMA方式能满足高速I/O设备的要求,传输数据量较大时,有利于CPU效率的发挥。
  配置起来相对复杂。如果传输数据少,可以直接由软件来实现,不需要使用DMA。在DMA传输中,如果有中断或者其他操作访问读写地址,会造成CPU卡死。

2.STM32的DMA特色

  1. 两个DMA控制器DMA1DMA2,每个DMA控制器有8个数据流,每个数据流有多达8个通道;

  2. 软件编程设置优先级:非常高、高、中或低;硬件优先级可避免由于软件等级相同而引发的冲突;低通道优先高。

  3. 每个数据流有单独的四级32位先进先出存储器缓冲区(FIFO),DMA有两种运行模式:
      FIFO模式:可通过软件将该阈值级别选取位FIFO大小的1/4,1/2或3/4.当FIFO存储器存储的数据大小超过FIFO大小的1/4,1/2或3/4,DMA将会传输FIFO里的数据。
      直接模式:每个DMA请求会立即启动对存储器的传输。当在直接模式(禁止FIFO)下将DMA请求配置为以存储器到外设模式传输数据时,DMA仅会将一个数据从存储器预加载到内部FIFO,从而确保一旦外设触发DMA请求时则立即传输数据。

  4. 可编程和独立的源和目标的传输数据宽度:字节(8bit)、半字(16bit)、字(32bit);

  5. 内存到内存外设到内存内存到外设的传输;

  6. 每个数据流也支持通过软件触发存储器到存储器的传输,只有DMA2控制器才可以进行存储器到存储器传输数据

  7. 可编程设置传输数目:最大可达65535;

  8. 支持循环缓冲(循环模式)管理:对源和目标的增量或非增量寻址;

  9. 每个通道有5个事件标志:DMA传输一般、DMA传输完成、DMA传输出错、DMA FIFO错误、直接模式错误。

DMA事务

  DMA可以实现外设寄存器、存储器之间三种模式,主要是DMA控制器采用AHB主总线,它可以控制AHB总线矩阵来启动AHB事务。
  DMA事务由给定数据的数据传输序列组成。要传输的数据项的数目及其宽度(8位、16位或32位)可用软件编程。
1.DMA控制器产生事件。
2.外设会向DMA控制器发送请求信号。
3.DMA控制器收到该请求信号后,根据通道优先级处理该请求。
4.DMA控制器访问外设,DMA控制器向外设发送确认信号。
5.外设获得DMA控制器的确认信号后,会立即释放其请求。一旦外设请求失效,DMA控制器就释放确认信号。如果有更多请求,外设可以启动下一个事务。

在这里插入图片描述 图2
在这里插入图片描述
在这里插入图片描述
图3
在这里插入图片描述
图4

基于STM32的DMA应用

HAL库


```c
typedef struct __DMA_HandleTypeDef
{
  DMA_Stream_TypeDef         *Instance;                                                        /*!< DMA寄存器基地址                  */
  DMA_InitTypeDef            Init;                                                             /*!< DMA通信参数           */ 
  HAL_LockTypeDef            Lock;                                                             /*!< 对资源型操作增加操作锁                     */  
  __IO HAL_DMA_StateTypeDef  State;                                                            /*!< DMA传输状态,通过不同状态的设定,实现各种方式的传输                     */
  void                       *Parent;                                                          /*!< 指向DMA通道外设句柄                    */ 
  void                       (* XferCpltCallback)( struct __DMA_HandleTypeDef * hdma);         /*!< DMA 传输完成回调函数        */
  void                       (* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);     /*!< DMA 传输完成一半回调函数    */
  void                       (* XferM1CpltCallback)( struct __DMA_HandleTypeDef * hdma);       /*!< Memory1传输完成回调函数  */
  void                       (* XferM1HalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);   /*!< Memort1传输完成一半回调函数 */
  void                       (* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma);        /*!< DMA 传输错误回调函数            */
  void                       (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma);        /*!< DMA 传输终止回调函数            */  
  __IO uint32_t              ErrorCode;                                                        /*!< DMA 错误代码                          */
  uint32_t                   StreamBaseAddress;                                                /*!< DMA 流基地址               */
  uint32_t                   StreamIndex;                                                      /*!< DMA 索引号                       */
}DMA_HandleTypeDef;
typedef struct
{
  uint32_t Channel;              /*!< Specifies the channel used for the specified stream. 
                                      This parameter can be a value of @ref DMA_Channel_selection                    */

  uint32_t Direction;            /*!< Specifies if the data will be transferred from memory to peripheral, 
                                      from memory to memory or from peripheral to memory.
                                      This parameter can be a value of @ref DMA_Data_transfer_direction              */

  uint32_t PeriphInc;            /*!< Specifies whether the Peripheral address register should be incremented or not.
                                      This parameter can be a value of @ref DMA_Peripheral_incremented_mode          */

  uint32_t MemInc;               /*!< Specifies whether the memory address register should be incremented or not.
                                      This parameter can be a value of @ref DMA_Memory_incremented_mode              */

  uint32_t PeriphDataAlignment;  /*!< Specifies the Peripheral data width.
                                      This parameter can be a value of @ref DMA_Peripheral_data_size                 */

  uint32_t MemDataAlignment;     /*!< Specifies the Memory data width.
                                      This parameter can be a value of @ref DMA_Memory_data_size                     */

  uint32_t Mode;                 /*!< Specifies the operation mode of the DMAy Streamx.
                                      This parameter can be a value of @ref DMA_mode
                                      @note The circular buffer mode cannot be used if the memory-to-memory
                                            data transfer is configured on the selected Stream                        */

  uint32_t Priority;             /*!< Specifies the software priority for the DMAy Streamx.
                                      This parameter can be a value of @ref DMA_Priority_level                       */

  uint32_t FIFOMode;             /*!< Specifies if the FIFO mode or Direct mode will be used for the specified stream.
                                      This parameter can be a value of @ref DMA_FIFO_direct_mode
                                      @note The Direct mode (FIFO mode disabled) cannot be used if the 
                                            memory-to-memory data transfer is configured on the selected stream       */

  uint32_t FIFOThreshold;        /*!< Specifies the FIFO threshold level.
                                      This parameter can be a value of @ref DMA_FIFO_threshold_level                  */

  uint32_t MemBurst;             /*!< Specifies the Burst transfer configuration for the memory transfers. 
                                      It specifies the amount of data to be transferred in a single non interruptible
                                      transaction.
                                      This parameter can be a value of @ref DMA_Memory_burst 
                                      @note The burst mode is possible only if the address Increment mode is enabled. */

  uint32_t PeriphBurst;          /*!< Specifies the Burst transfer configuration for the peripheral transfers. 
                                      It specifies the amount of data to be transferred in a single non interruptible 
                                      transaction. 
                                      This parameter can be a value of @ref DMA_Peripheral_burst
                                      @note The burst mode is possible only if the address Increment mode is enabled. */
}DMA_InitTypeDef;
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值