STM32一文通(9) DMA

发布者:RadiantJourney最新更新时间:2025-01-20 来源: jianshu关键字:STM32  DMA  直接存储器访问 手机看文章 扫描二维码
随时随地手机看文章

一. DMA简介

  • DMA(Direct Memory Access,直接存储器访问)  传输将数据从一个地址空间复制到另外一个地址空间。而且不占用CPU

  • 数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。

  • 我们把外设简称为: P, 把寄存器简称为: M

  • DMA 控制器包含了 DMA1 和 DMA2,其中 DMA1 有 7 个通道,DMA2 有 5 个通道,这里的通道可以理解为传输数据的一种管道。要注意的是 DMA2 只存在于大容量的单片机中。

1. DMA功能框图

关键角色:

  1. DMA请求 : 发送方向MCU请求使用DMA通道发送数据

  2. 通道 : 传输数据的管道
    具体通道分配方法:

但是通道表里并没有 存储器到存储器 (M →M的)请求映像, 因为: 它每个通道都可以用!!!!

  1. 仲裁器 :
    当多个DMA请求一起来怎么办?
    使用仲裁器来管理
    ①. 软件优先级 :  DMA_CCRx : PL[1:0]寄存器配置其优先级 , 分为: 低, 中, 高, 最高
    ②. 硬件优先级 :  DMA1>DMA2 , 通道号小的优先

二. DMA相关结构体

1. DMA_ InitTypeDef 初始化结构体

typedef struct{
 uint32_t DMA_PeripheralBaseAddr; // 外设地址
 uint32_t DMA_MemoryBaseAddr; // 存储器地址
 uint32_t DMA_DIR; // 传输方向
 uint32_t DMA_BufferSize; // 传输数目
 uint32_t DMA_PeripheralInc; // 外设地址增量模式
 uint32_t DMA_MemoryInc; // 存储器地址增量模式
 uint32_t DMA_PeripheralDataSize; // 外设数据宽度
 uint32_t DMA_MemoryDataSize; // 存储器数据宽度
 uint32_t DMA_Mode; // 模式选择
 uint32_t DMA_Priority; // 通道优先级
 uint32_t DMA_M2M; // 存储器到存储器模式} DMA_InitTypeDef;

参数详解 :

(1). 数剧从哪来到哪去
  • 外设地址 : 配置的是DMA_CPAR 寄存器, 一般设置为外设的数据寄存器地址,如果是存储器到存储器模式则设置为其中一个存储器地址。

  • 存储器地址 : 设定DMA_CMAR 寄存器值;一般设置为我们自定义存储区的首地址。

  • 传输方向 : 传输方向选择, 可选外设到存储器、存储器到外设。它设定DMA_CCR 寄存器的DIR[1:0]位的值。这里并没有存储器到存储器的方向选择,当使用存储器到存储器时,只需要把其中一个存储器当作外设使用即可。

(2). 数剧传多少, 传的单位是什么?
  • 传输数目 : 设定待传输数据数目,初始化设定DMA_CNDTR 寄存器的值

  • 外设地址增量模式 : 外设地址是否自动递增 (比如外设是个串口寄存器,那就不要递增, 如果是个存储单元则要递增)

  • 存储器地址增量模式存储器地址是否自动递增,我们自定义的存储区一般都是存放多个数据的,所以要使能存储器地址自动递增功能

  • 外设数据宽度 : 可选字节(8 位)、半字(16 位)和字(32位),它设定DMA_CCR 寄存器的PSIZE[1:0]位的值。

  • 存储器数据宽度 : 可选字节(8 位)、半字(16 位)和字(32位),它设定DMA_CCR 寄存器的MSIZE[1:0]位的值。当外设和存储器之间传数据时,两边的数据宽度应该设置为一致大小。

(3). 什么时候传输结束?
  • 模式选择 : DMA 传输模式选择, 可选一次传输或者循环传输

(4). 其他设置
  • 通道优先级 : 设置通道优先级

  • 存储器到存储器模式 : 当M2M时设置

三. DMA相关库函数

1. DMA初始化    DMA_Init

例如: DMA_Init(DMA1_Channel7, &DMA_InitStruct)

2. DMA使能 DMA_Cmd

3. DMA状态查询   FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);

DMAy_FLAG可以传入以下值:

  *   This parameter can be one of the following values:
  *     @arg DMA1_FLAG_GL1: DMA1 Channel1 global flag.
  *     @arg DMA1_FLAG_TC1: DMA1 Channel1 transfer complete flag.
  *     @arg DMA1_FLAG_HT1: DMA1 Channel1 half transfer flag.
  *     @arg DMA1_FLAG_TE1: DMA1 Channel1 transfer error flag.
  *     @arg DMA1_FLAG_GL2: DMA1 Channel2 global flag.
  *     @arg DMA1_FLAG_TC2: DMA1 Channel2 transfer complete flag.
  *     @arg DMA1_FLAG_HT2: DMA1 Channel2 half transfer flag.
  *     @arg DMA1_FLAG_TE2: DMA1 Channel2 transfer error flag.
  *     @arg DMA1_FLAG_GL3: DMA1 Channel3 global flag.
  *     @arg DMA1_FLAG_TC3: DMA1 Channel3 transfer complete flag.
  *     @arg DMA1_FLAG_HT3: DMA1 Channel3 half transfer flag.
  *     @arg DMA1_FLAG_TE3: DMA1 Channel3 transfer error flag.
  *     @arg DMA1_FLAG_GL4: DMA1 Channel4 global flag.
  *     @arg DMA1_FLAG_TC4: DMA1 Channel4 transfer complete flag.
  *     @arg DMA1_FLAG_HT4: DMA1 Channel4 half transfer flag.
  *     @arg DMA1_FLAG_TE4: DMA1 Channel4 transfer error flag.
  *     @arg DMA1_FLAG_GL5: DMA1 Channel5 global flag.
  *     @arg DMA1_FLAG_TC5: DMA1 Channel5 transfer complete flag.
  *     @arg DMA1_FLAG_HT5: DMA1 Channel5 half transfer flag.
  *     @arg DMA1_FLAG_TE5: DMA1 Channel5 transfer error flag.
  *     @arg DMA1_FLAG_GL6: DMA1 Channel6 global flag.
  *     @arg DMA1_FLAG_TC6: DMA1 Channel6 transfer complete flag.
  *     @arg DMA1_FLAG_HT6: DMA1 Channel6 half transfer flag.
  *     @arg DMA1_FLAG_TE6: DMA1 Channel6 transfer error flag.
  *     @arg DMA1_FLAG_GL7: DMA1 Channel7 global flag.
  *     @arg DMA1_FLAG_TC7: DMA1 Channel7 transfer complete flag.
  *     @arg DMA1_FLAG_HT7: DMA1 Channel7 half transfer flag.
  *     @arg DMA1_FLAG_TE7: DMA1 Channel7 transfer error flag.
  *     @arg DMA2_FLAG_GL1: DMA2 Channel1 global flag.
  *     @arg DMA2_FLAG_TC1: DMA2 Channel1 transfer complete flag.
  *     @arg DMA2_FLAG_HT1: DMA2 Channel1 half transfer flag.
  *     @arg DMA2_FLAG_TE1: DMA2 Channel1 transfer error flag.
  *     @arg DMA2_FLAG_GL2: DMA2 Channel2 global flag.
  *     @arg DMA2_FLAG_TC2: DMA2 Channel2 transfer complete flag.
  *     @arg DMA2_FLAG_HT2: DMA2 Channel2 half transfer flag.
  *     @arg DMA2_FLAG_TE2: DMA2 Channel2 transfer error flag.
  *     @arg DMA2_FLAG_GL3: DMA2 Channel3 global flag.
  *     @arg DMA2_FLAG_TC3: DMA2 Channel3 transfer complete flag.
  *     @arg DMA2_FLAG_HT3: DMA2 Channel3 half transfer flag.
  *     @arg DMA2_FLAG_TE3: DMA2 Channel3 transfer error flag.
  *     @arg DMA2_FLAG_GL4: DMA2 Channel4 global flag.
  *     @arg DMA2_FLAG_TC4: DMA2 Channel4 transfer complete flag.
  *     @arg DMA2_FLAG_HT4: DMA2 Channel4 half transfer flag.
  *     @arg DMA2_FLAG_TE4: DMA2 Channel4 transfer error flag.
  *     @arg DMA2_FLAG_GL5: DMA2 Channel5 global flag.
  *     @arg DMA2_FLAG_TC5: DMA2 Channel5 transfer complete flag.
  *     @arg DMA2_FLAG_HT5: DMA2 Channel5 half transfer flag.
  *     @arg DMA2_FLAG_TE5: DMA2 Channel5 transfer error flag.
  * @retval The new state of DMAy_FLAG (SET or RESET).

返回值 SET RESET

4. DMA中断设置 DMA_ITConfig

void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);

参数2 DMA_IT 可选以下参数

5. 中断状态查询

ITStatus DMA_GetITStatus(uint32_t DMAy_IT);

参数: 和上一节的一样
返回值 SET RESET

四. M→M 传输


关键字:STM32  DMA  直接存储器访问 引用地址:STM32一文通(9) DMA

上一篇:stm32修改外部晶振频率的方法
下一篇:STM32新建汇编工程2

推荐阅读最新更新时间:2026-03-25 11:10

STM32笔记(十)---DMA直接存储器访问
一、 DMA简介 DMA(Data Memory Access),直接存储器访问。主要功能是可以把数据从一个地方搬到另外一个地方,而且不占用CPU。通常为以下传输方式: M- M,存储器到存储器,一般指内部存储器(Flash)与外部存储器(SRAM)的传输。 P- M, 外设到存储器,一般指外设(Periph)与外部存储器的传输。 M- P, 存储器到外设,一般指外部存储器与外设(Periph)的传输。 STM32系列一般分为DMA1、DMA2,两者均可以实现 P- M, M- P,M- M 。 区别:DMA1有7个通道、DMA2有5个通道,同时DMA2在大容量、互联型的芯片上配备。 二、 DMA功能框图 功能框图
[单片机]
<font color='red'>STM32</font>笔记(十)---<font color='red'>DMA</font>(<font color='red'>直接</font><font color='red'>存储器</font><font color='red'>访问</font>)
STM32Cube-直接存储器访问DMA
在USART章节讲解了串口的轮询和中断模式,这一章介绍一下通过DMA模式控制串口传输。 直接存储器访问 (DMA) 用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其它操作使用。说白了DMA就是一个搬运工,将数据从一个地方搬到另一个地方而不需要CPU处理。 作为一个搬运工,要他正常工作必须要确定几个重要的参数。 1.传输模式:数据从哪里搬到哪里。三种可能的传输方向:存储器到外设、外设到存储器或存储器到存储器。 2.通道选择:就是数据传输的是走那条道路 3.仲裁器:多个DMA传输是优先级高的优先传输。 4
[单片机]
STM32Cube-<font color='red'>直接</font><font color='red'>存储器</font><font color='red'>访问</font>(<font color='red'>DMA</font>)
STM32F429 >> 10. DMA_直接存储器访问
本工程板级支持包文件适用于野火stm32f429 开发板。 DMA 传输实现高速数据移动过程无需任何CPU 操作控制 其支持以下三种传输方式: 外设到存储器传输; 存储器到外设传输; 存储器到存储器传输。 功能框图: ① 外设通道选择 外设通道选择所解决的问题是决定哪一个外设作为数据传输的源地址或目标地址。 DMA1 请求映射: DMA2 请求映射: 每个外设请求都占用一个数据流通道,相同外设请求可以占用不同数据流通道。 ② 仲裁器 仲裁器管理数据流方法分为两个阶段。 第一阶段属于软件阶段,我们在配置数据流时可以通过寄存器设定其优先级别,具体配置DMA_SxCR 寄存器PL 位,可以设置为
[单片机]
STM32F429 >> 10. <font color='red'>DMA</font>_<font color='red'>直接</font><font color='red'>存储器</font><font color='red'>访问</font>
STM32外设DAC实战指南:使用DMA输出正弦波
一,方法思路 DAC 的一个常见应用是产生任意波形,比如平滑的正弦波。如果让 CPU 频繁计算正弦值并手动更新 DAC 输出,会非常耗费 CPU 资源且难以保证输出频率的精确和稳定。这时,再次请出我们的老朋友:定时器 和 DMA。 思路与 ADC 的定时器触发采样类似,但方向相反: 1,生成波形查找表 (Lookup Table – LUT): 在内存中预先计算并存储一个完整周期的正弦波对应的离散数字值(例如 100 个点),形成一个数组。 2,定时器作为 节拍器 : 配置一个定时器(如 TIM6 或 TIM7,它们通常有连接到 DAC 的触发输出)以固定的频率产生触发信号 (TRGO)。这个频率决定了输出正弦波的频率。 3,
[单片机]
<font color='red'>STM32</font>外设DAC实战指南:使用<font color='red'>DMA</font>输出正弦波
STM32 SPI DMA通信详解
今天被要求做了实验,要求提升SPI读写数据速度,那首先想到的就是提升SPI的速率以及添加DMA了,很简单,跟着做就好。 芯片: STM32F103,我是HKF103国产的,大差不差。 软件:STM32CUBEMX,非常方便的配置软件 编译IDE:KEIL和vscode均可 1.参数配置 2.DMA配置,全部默认就行 3.中断,三个都打开 4.生成代码后添加代码 定义两个标志位,用来表示接收完成。 添加回调函数,在回调函数里置标志位。 我用SPI来读写W25QXX的芯片,而我用到了SFUD,我在底层里这样实现。如果你用W25的库函数可以参照着改一下,大差不大的都。 最终速率比较客观,读取16m的F
[单片机]
<font color='red'>STM32</font> SPI <font color='red'>DMA</font>通信详解
STM32 多通道ADC连续采集之数据到内存 DMA传输
DMA的英文Direct memory access,意思就是传输将数据从一个地址空间复制到另一个地址空间,设置好后自动传输而不需要处理器参与。STM32F030F4只有DMA1,DMA1有5个通道,要想使用必须进行一些设置。 下面以ADC多通道采集为例,大致分3步: 1. GPIO的配置。该配置主要设置ADC采集涉及的IO口,本例设置ADC连接9个IO口进行模拟量采集。 2. ADC的配置。设置多通道采集速率、连续转换模式、使能和DMA通道的连接等。注意该芯片只有ADC1。 3. DMA的配置。设置DMA的开启、源地址、目标地址等。该芯片只有DMA1,但有5个通道,本例用通道1。 下面是mai
[单片机]
STM32 SPI+DMA刷LCD屏
STM32---SPI通信的总结(库函数操作) 参考代码: 1 void SPI_GPIO_Init(void) 2 { 3 GPIO_InitTypeDef GPIO_InitStructure; 4 SPI_InitTypeDef SPI_InitStructure; 5 6 NVIC_InitTypeDef NVIC_InitStructure; 7 8 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );//PORTB时钟使能 9 RCC_APB1PeriphClockCm
[单片机]
<font color='red'>STM32</font> SPI+<font color='red'>DMA</font>刷LCD屏
【调试记录】STM32 HAL库硬件I2C从机Seq DMA方式不定长接收和发送
序言 久闻STM32硬件I2C坑多,之前做的项目浅尝主机通信就偶尔遇到总线锁死的bug,网上解决方案也很多,用着也还行。然而作为从机就是另一个大坑了,官方例程少,网上资料少,api也说的不明不白。本文整合各位博主分享的资料,记录和分享调试linux主机与STM32的I2C通信过程中遇到的问题和解决方案,最终在STM32L051C8T单片机实现DMA方式的I2C从机。 单片机资源紧张,性能低但是实时性高。要充分发挥单片机实时特性,在处理低速IO时应该尽量用硬件方式实现,尽可能利用硬件处理数据。DMA就是解放CPU负载的利器。 HAL库API分析 一般来说HAL库的通信io类API分为polling阻塞,IT和DMA方式。而I2C分
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved