历史上的今天
返回首页

历史上的今天

今天是:2025年02月12日(星期三)

正在发生

2019年02月12日 | STM32—DMA使用

2019-02-12 来源:eefocus

DMA简介

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


}


推荐阅读

史海拾趣

Hi-Tech Resistors Pvt Ltd公司的发展小趣事

机顶盒,全称为数字视频变换盒,是现代家庭娱乐不可或缺的重要设备。从广义上讲,任何与电视机连接的网络终端设备均可视为机顶盒,它们不仅限于接收和转换电视信号,还承载着丰富的娱乐与信息服务功能。

机顶盒的核心功能在于接收并转换来自有线电缆、卫星天线、宽带网络及地面广播的数字电视信号,将其转换为电视机可识别的视频和音频流。这一转换过程确保了观众能够享受到高清乃至4K超高清的画质和震撼的音效,极大地提升了观看体验。此外,机顶盒还集成了诸如电子节目指南、因特网网页浏览等增值服务,让电视机不再仅仅是单向接收信息的设备,而是成为一个能够与用户进行互动的智能终端。

随着技术的发展,机顶盒的种类日益丰富,按主要功能可分为数字卫星机顶盒、有线电视数字机顶盒、IPTV机顶盒等。这些机顶盒不仅满足了用户多样化的观看需求,还通过连接互联网,提供了在线购物、视频点播、游戏娱乐等多元化服务。未来,随着高清、超高清技术的普及以及人工智能、云计算等技术的应用,机顶盒将向智能化、多功能化方向发展,为用户提供更加便捷、个性化的使用体验。

总之,机顶盒作为连接电视与互联网的桥梁,在丰富家庭娱乐生活、提升观看体验方面发挥着重要作用。随着技术的不断进步和市场需求的持续增长,机顶盒行业将迎来更加广阔的发展前景。

Good-Ark公司的发展小趣事
如蜂鸣器、LED灯等,用于在触发报警时发出声音或光信号。
Gang Song Electronics Co Ltd公司的发展小趣事

并购完成后,GainSpan的技术与Telit的物联网平台实现了深度融合。Telit利用GainSpan的低功耗WiFi模组技术,推出了更加高效、节能的物联网解决方案。这些方案不仅降低了物联网设备的能耗,还延长了设备的使用寿命,提高了整体系统的稳定性和可靠性。同时,GainSpan的技术也为Telit的物联网平台带来了更多创新应用的可能性。

上海晶岳(AFSEMI)公司的发展小趣事

在半导体行业中,供应链的稳定性和可靠性对于企业的生存和发展至关重要。晶岳电子深知这一点,因此一直致力于与流片及封装厂建立长期稳定的合作关系。公司的晶圆流片合作伙伴包括大陆的CSMC、ASMC,台湾的世界先进等公司;封装的合作伙伴则包括长电科技、上海芯哲等大陆上市企业。通过与这些合作伙伴的紧密合作,晶岳电子确保了产品质量的稳定性和交货期的可靠性,为公司的持续发展提供了有力保障。

这五个故事只是上海晶岳(AFSEMI)公司发展历程中的一部分,但它们充分展示了晶岳电子在电子行业中的崛起和成长。凭借对技术的执着追求和对市场的敏锐洞察,晶岳电子在激烈的市场竞争中脱颖而出,成为了行业内的一支重要力量。

HTSEMI( Jin Yu Semiconductor )公司的发展小趣事

金宇半导体成立于2005年,由一群来自国内外顶尖高校的半导体专家共同创立。在成立初期,公司面临着资金短缺和技术瓶颈的双重挑战。创始人团队凭借在微处理器设计领域的深厚积累,成功研发出了一款低功耗、高性能的嵌入式处理器芯片,迅速获得了市场的关注。这款芯片不仅在国内智能手机市场占据了一席之地,还成功打入国际市场,为公司的后续发展奠定了坚实基础。

振华(CEC)公司的发展小趣事

随着企业规模的不断扩大和市场竞争的加剧,振华意识到单纯的自我发展已经难以满足企业的长远发展需求。因此,公司开始积极探索并购与资源整合的道路。通过并购具有技术优势和市场潜力的企业,振华不仅获得了更多的技术资源和市场份额,还实现了产业链的延伸和拓展。同时,公司还注重内部资源的整合和优化,提高资源的利用效率和管理水平。

问答坊 | AI 解惑

别让你的简历15秒后被扔掉

今天帮公司筛选简历,感受颇多!我所在的是一家大型企业。从收到的简历数量可以看出来 1200+份简历,从中选出150+份进行笔试。   比例:8选1  机缘凑巧去帮老总们筛选简历,感受颇多。   觉得有必要跟还在找工作的师弟师妹们说说一些需要注 ...…

查看全部问答>

周公M0新原理图

周公的M0开发板的原理图终于更新了…

查看全部问答>

关于控制USB外设的问题

我是第一次作这方面的东西: 我感觉:首先要判断次外设的存在(包括他的插入于拔除)         向外设发送控制命令(包括向他提供数据)。 不知道思路是不是有问题,请各位给个思路。 …

查看全部问答>

EmbestSTM32板(199元)不包含的模块

8MB SPI FlashIC卡读卡控制芯片和卡座由于成本控制原因,199元销售的板子里不包含上述模块,对于此消息发布较晚,给部分网友造成了误解,我们深表歉意,希望大家能够继续给我们指正,谢谢!…

查看全部问答>

LaunchPAD新配件-音频电容触摸套件

C5000音频电容触摸套件套件具体指标如下:MP3 Encode & DecodeSD Card File SystemUSB Mass Storage ClassOLED, CodecUART client interface可使用该套件配合launchpad制作音乐播放器:MP3 PlayerVoice RecorderFire Alarm – MSP430 detects tem ...…

查看全部问答>

MSP430F149的定时器A的连续计数模式的CCR0

MSP430F149的定时器A的连续计数模式的CCR0的作用?增计数模式是从0增加到CCR0就复位,增减计数模式是从0增加到CCR0,在减到0。可是连续计数模式呢?CCR0的作用?…

查看全部问答>

大学堂新课上线:《 CC1120 Sub1G 开发套件动手实践》

大学堂有新课程上线啦! 《 CC1120 Sub1G 开发套件动手实践》:https://www.eeworld.com.cn/training/2014/wuxian_0117/382.html 该视频系列基于芯威科技CC1120开发套件,演示了如何使用SmartRF控制软件实现简单的数据包收发,如何理解和 ...…

查看全部问答>

【已出】出港版ipad mini2 16G

本帖最后由 shower.xu 于 2014-1-24 11:03 编辑 港版ipad mini2 16G,2300未拆封,包邮顺丰。支付宝交易。 …

查看全部问答>

【R7F0C089】+虽有小缺憾,但认真努力过

本帖最后由 人民币的幻想 于 2015-11-24 10:36 编辑 视频里演示测量心率时,使用手腕部分更能快速得到准确值。因此,后期考虑将心率做成手表形式。 …

查看全部问答>

CCS5.3调试28335烧写注意事项

1.安装ccs5.3,下载破解序列号,复制到C:\\ti\\ccsv5\\ccs_base\\DebugServer\\license下 2.我使用的是合众达的560plus仿真器,去其官网下载ccs4.1的驱动,兼容ccs5,安装路径一定要设置在C:\\ti\\ccsv5\\ccs_base否则无法识别其仿真器(我一开始 ...…

查看全部问答>