×
单片机 > 单片机程序设计 > 详情

STM32—DMA使用

发布时间:2020-08-24 发布时间:
|

DMA简介

  DMA:Direct memory access controller,直接存储器存储。DMA可以实现数据在外设与存储器、存储器与存储器之间的快速转换,且不需要CPU的干预,这样就可以释放CPU的资源,让CPU干其他的事情,提高效率。有的STM32芯片有两个DMA,有的就只有一个DMA,这个要查具体的芯片手册。


DMA 的主要特性


DMA参数与函数解析


上一篇文章(链接)中利用USART DMA 实现接收任意长度数据,下面分析下DMA里面的参数和函数。首先查看DMA的结构体定义。


DMA_HandleTypeDef hdma_usart1_rx;


  * @brief  DMA handle Structure definition

  */

typedef struct __DMA_HandleTypeDef

{

  DMA_Stream_TypeDef         *Instance;                                                        /*!< Register base address                  */  //DMA的寄存器基地址


  DMA_InitTypeDef            Init;                                                             /*!< DMA communication parameters           */ // 初始化结构体


  HAL_LockTypeDef            Lock;                                                             /*!< DMA locking object                     */  


  __IO HAL_DMA_StateTypeDef  State;                                                            /*!< DMA transfer state                     */


  void                       *Parent;                                                          /*!< Parent object state                    */ 


  void                       (* XferCpltCallback)( struct __DMA_HandleTypeDef * hdma);         /*!< DMA transfer complete callback         */


  void                       (* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);     /*!< DMA Half transfer complete callback    */


  void                       (* XferM1CpltCallback)( struct __DMA_HandleTypeDef * hdma);       /*!< DMA transfer complete Memory1 callback */


  void                       (* XferM1HalfCpltCallback)( struct __DMA_HandleTypeDef * hdma);   /*!< DMA transfer Half complete Memory1 callback */


  void                       (* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma);        /*!< DMA transfer error callback            */


  void                       (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma);        /*!< DMA transfer Abort callback            */  


  __IO uint32_t              ErrorCode;                                                        /*!< DMA Error code                          */


  uint32_t                   StreamBaseAddress;                                                /*!< DMA Stream Base Address                */


  uint32_t                   StreamIndex;                                                      /*!< DMA Stream Index                       */


}DMA_HandleTypeDef;


typedef struct

{

  __IO uint32_t CR;     /*!< DMA stream x configuration register      */

  __IO uint32_t NDTR;   /*!< DMA stream x number of data register     */

  __IO uint32_t PAR;    /*!< DMA stream x peripheral address register */

  __IO uint32_t M0AR;   /*!< DMA stream x memory 0 address register   */

  __IO uint32_t M1AR;   /*!< DMA stream x memory 1 address register   */

  __IO uint32_t FCR;    /*!< DMA stream x FIFO control register       */

} DMA_Stream_TypeDef;


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;


  USART的tx和rx的DMA 配置在串口的初始化函数中进行了配置,下面分析在配置的参数。


void HAL_UART_MspInit(UART_HandleTypeDef* huart)

{


  GPIO_InitTypeDef GPIO_InitStruct;

  if(huart->Instance==USART1)

  {

  /* USER CODE BEGIN USART1_MspInit 0 */


  /* USER CODE END USART1_MspInit 0 */

    /* Peripheral clock enable */

    __HAL_RCC_USART1_CLK_ENABLE();


    /**USART1 GPIO Configuration    

    PA9     ------> USART1_TX

    PA10     ------> USART1_RX 

    */

    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_PULLUP;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);


    /* USART1 DMA Init */

    /* USART1_RX Init */

    hdma_usart1_rx.Instance = DMA2_Stream2;//DMA2通道2

    hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;//不明白这个CHANNEL4通道4是什么意思,有知道的请告知一下

    hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;//rx,从外设到存储器

    hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;//外设地址增量失能

    hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;//存储器地址增强使能

    hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//数据宽度:byte 8位

    hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;//数据宽度:byte 8位

    hdma_usart1_rx.Init.Mode = DMA_NORMAL;//正常模式,非循环模式

    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;//低优先级

    hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;//FIFO失能

    if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)

    {

      _Error_Handler(__FILE__, __LINE__);

    }


    __HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx);


    /* USART1_TX Init */ //通道与RX不一样, 其余一样

    hdma_usart1_tx.Instance = DMA2_Stream7;//DMA2 通道7

    hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;

    hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;//tx, 存储器到外设

    hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;

    hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;

    hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

    hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

    hdma_usart1_tx.Init.Mode = DMA_NORMAL;

    hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;

    hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

    if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)// 初始化函数, 主要对DMA的寄存器中配置上面的参数

    {

      _Error_Handler(__FILE__, __LINE__);

    }


    __HAL_LINKDMA(huart,hdmatx,hdma_usart1_tx);


    /* USART1 interrupt Init */

    HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);

    HAL_NVIC_EnableIRQ(USART1_IRQn);

  /* USER CODE BEGIN USART1_MspInit 1 */


  /* USER CODE END USART1_MspInit 1 */

  }


}


  MX_DMA_Init的初始化函数中开始了DMA2的时钟和设置了DMA 通道的中断优先级,使能对应中断。


static void MX_DMA_Init(void) 

{

  /* DMA controller clock enable */

  __HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能


  /* DMA interrupt init */

  /* DMA2_Stream2_IRQn interrupt configuration */

  HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0);//设置中断优先级

  HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);//使能中断

  /* DMA2_Stream7_IRQn interrupt configuration */

  HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 0, 0);

  HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);


}


关键字:STM32  DMA使用 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
C51 特殊功能寄存器SFR的名称和地址