Bootstrap

STM32 第21章 DMA--直接存储器访问

时间:2024.10.31-11.2

参考资料:

《零死角玩转STM32》“DMA--直接存储器访问”章节

编程部分的代码基于12-GPIO输出-使用固件库点亮LED灯

一、学习内容

1、DMA功能框图和DMA初始化结构体

1.1DMA功能框图

1.1.1DMA简介
DMA:

Data Memory Access,直接存储器访问。和GPIO、串口等一样都是外设。

主要功能:

把数据从一个地方搬到另外一个地方,而且不占用CPU。

DMA1:

有7个通道(搬运数据的管道),可以实现P(外设)->M(存储器),M->P,M->M

DMA2(只存在大容量/互联型的产品中):

有5个通道,可以实现P->M,M->P,M->M

霸道和指南者是512K的,所以都有两个DMA控制器

1.1.2DMA功能框图

1-DMA请求

如果外设想要通过DMA来传输数据,必须先向DMA控制器发送DMA请求,DMA收到请求信号以后,控制器会给外设一个应答信号,当外设应答且DMA控制器收到应答信号之后,就会启动DMA的传输,直到传输完毕。

2-通道

传输数据的管道

2.1DMA请求+通道
DMA1请求映射

 DMA2请求映射

TIPS:

1、ADC3/SDIO/TIM8的DMA请求只有大容量的单片机才有

2、当使用M->M模式时,所有通道均可使用,无硬性规定,P->M和M->P都需要根据实际需要的功能选择不同的通道

3-仲裁器

多个DMA请求一起来,怎么办?

1、软件阶段,DMA_CCPx:PL[1:0]。
2、硬件阶段,通道编号小的优先级大,DMA1的优先级高于DMA2的优先级。

1.1.3DMA处理

 

1.2DMA相关库函数

1.2.1DMA初始化结构体

初始化结构体在固件库头文件中:stm32f10x_dma.h

/** 
  * @brief  DMA Init structure definition
  */

typedef struct
{
  uint32_t DMA_PeripheralBaseAddr; /*!< Specifies the peripheral base address for DMAy Channelx. */

  uint32_t DMA_MemoryBaseAddr;     /*!< Specifies the memory base address for DMAy Channelx. */

  uint32_t DMA_DIR;                /*!< Specifies if the peripheral is the source or destination.
                                        This parameter can be a value of @ref DMA_data_transfer_direction */

  uint32_t DMA_BufferSize;         /*!< Specifies the buffer size, in data unit, of the specified Channel. 
                                        The data unit is equal to the configuration set in DMA_PeripheralDataSize
                                        or DMA_MemoryDataSize members depending in the transfer direction. */

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

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

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

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

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

  uint32_t DMA_Priority;           /*!< Specifies the software priority for the DMAy Channelx.
                                        This parameter can be a value of @ref DMA_priority_level */

  uint32_t DMA_M2M;                /*!< Specifies if the DMAy Channelx will be used in memory-to-memory transfer.
                                        This parameter can be a value of @ref DMA_memory_to_memory */
}DMA_InitTypeDef;
1.数据从哪里来,要到哪里去
1.1外设地址,DMA_CPAR

地址从外设得来,一般情况下是从外设的数据寄存器而来

1.2存储器地址,DMA_CMAR

1.3传输方向,DMA_CCR:DIR

 

uint32_t DMA_PeripheralBaseAddr;     //外设地址

  uint32_t DMA_MemoryBaseAddr;       //存储器地址

  uint32_t DMA_DIR;                  //传输方向

 

 M-->M的控制位

2.结构体成员取值

 在固件库头文件中:stm32f10x_dma.h

/** @defgroup DMA_data_transfer_direction 
  * @{
  */

#define DMA_DIR_PeripheralDST              ((uint32_t)0x00000010)
#define DMA_DIR_PeripheralSRC              ((uint32_t)0x00000000)
#define IS_DMA_DIR(DIR) (((DIR) == DMA_DIR_PeripheralDST) || \
                         ((DIR) == DMA_DIR_PeripheralSRC))
3.数据要传多少,传的单位是什么
 uint32_t DMA_BufferSize;            //传输数目
                                        

  uint32_t DMA_PeripheralInc;        //外设地址增量模式

  uint32_t DMA_MemoryInc;            //存储器地址增量模式

  uint32_t DMA_PeripheralDataSize;   //外设数据宽度

  uint32_t DMA_MemoryDataSize;       //存储器数据宽度
3.1传输数目,DMA_CNDTR

3.2外设地址是否递增,DMA_CCRx:PINC
3.3存储器地址是否递增,DMA_CCRx:MINC

 

3.4外设数据宽度,DMA_CCRx:PSIZE 

;