目录
前言
本期我们就开始学习DMA直接存储器存取,DMA是一个数据装运的小助手,执行数据的搬运处理,减少了CPU的负担,在stm32中担当重要的工作。在前面学习ADC的时候我们就提及过这个,那么本期就正式开始学习DMA,先从理论部分入手,下一期我们就进行关于DMA的相关项目实操。(视频:[8-1] DMA直接存储器存取_哔哩哔哩_bilibili)
DMA
1.简介
- DMA(Direct Memory Access)直接存储器存取
- DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源
- 12个独立可配置的通道: DMA1(7个通道), DMA2(5个通道)
- 每个通道都支持软件触发和特定的硬件触发
STM32F103C8T6 DMA资源:DMA1(7个通道)
2.存储器映像
存储器分为大类,分为ROM和RAM,其中ROM是一种掉电不丢失数据的存储器,而RAM是一种掉电就丢失数据的存储器,其实很类似我们的电脑ROM类似为硬盘里面的数据,RAM类似为电脑内存存储的临时数据。
类型 | 起始地址 | 存储器 | 用途 |
ROM | 0x0800 0000 | 程序存储器Flash | 存储C语言编译后的程序代码 |
0x1FFF F000 | 系统存储器 | 存储BootLoader,用于串口下载 | |
0x1FFF F800 | 选项字节 | 存储一些独立于程序代码的配置参数 | |
RAM | 0x2000 0000 | 运行内存SRAM | 存储运行过程中的临时变量 |
0x4000 0000 | 外设寄存器 | 存储各个外设的配置参数 | |
0xE000 0000 | 内核外设寄存器 | 存储内核各个外设的配置参数 |
3.DMA结构
下面是DMA的整体框架,这里我们可以看出是有三个DMA的(但是我们使用的STM32F103C8T6只有一个DMA1),这里的DMA是通过一个总线来去访问各个存储器的内容,但是总线是只有一个的,所以当出现多个通道都需要去访问的时候,不可能都去挤这一个总线,这时候有一个仲裁器去判断哪个通道优先去执行,类似于中断的优先级。
下图是DMA的基本结构,DMA的搬运方向是可以分为三个,分别是外设到存储器、存储器到外设、存储器到存储器,其中外设寄存器和存储器都是有三个参数的定义,也就是起始地址、数据宽度、地址是否自增。下面还有一个计数器,这个计数器是一个自减的计数器,是一个搬运次数计数意思是当开始设定一个数字这个数字减少到0的时候搬运就结束,后面还有一个自动重装,当我们开启自动重装的时候,计数器的值就会回归到我们开始设定的那个数字,然后就开始数据搬运的操作。下面还有一个触发方式的选择,M2M选择1的话是软件触发,选择0是硬件触发,软件触发一般用于存储器到存储器的数据搬运,比如程序里面的数组赋值到另外一个数组,二硬件触发一般用于外设到存储器之间的数据搬运,因为硬件触发要考虑到外设的触发条件,比如ADC转换结束或者中断等等。
注意事项
选择软件触发是不能使用自动重装的,不然就会一直搬运还是停不下来的那种,类似于死循环了
下面可以看出对于硬件触发的并不是每一个通道的都是一样的,是这个通道有特定的硬件信号才能触发。
4.数据宽度与对齐
这里就涉及到起始和目标二者之间数据宽度的问题,如果是二者的宽度都是一样的,比如8位,那么传输的话就会一一对应传输;如果起始的数据比目标的位宽要小,那么传输到目标后的数据是右对齐的方式,也就是高位的补零;如果起始的数据比目标的要大,那么传输到目标的数据是舍弃掉高位的数据。
5.DMA工作示例
(1)数据转运+DMA
下面是数据的转运,也就是把一个数据变量的值复制到另一个变量那里去,入下面所示,把第一个数组A复制到另外一个数组B,这里没有涉及到了相关外设条件,所以是用最快的方式来去进行也就是软件触发,另外就是需要执行7次,在转运的过程中还需要去对地址进行移位的操作,类似于指针地址移位,其实就是我们常见的数组++,要想实现下面一一对应的赋值,起始数组和目标数组都需要执行地址++操作。
(2)ADC扫描模式+DMA
下面是ADC扫描模式通过DMA来去搬运转换好的数据。在上一期我们就说过ADC的规则组的数据寄存器是只能存储一个转换结果的,但是列表中是有多个通道要进行转换,那么如果不及时拿走上一个通道转换的结果,那么下一个通道转换的结果就会覆盖掉上一个的值,所以这里就需要DMA来去搬运这些转换好的结果,每一个通道转换后切换到另外一个通道的时候,中间是可以继续DMA搬运操作的,所以ADC扫描模式和DMA就可以实现完美的配合操作,每完成一个转换,DMA就可以把这个结果拿走存起来,然后数据寄存器就可以继续放下一个通道转换的结果。
以上就是本期的全部内容了,我们下次见!
今日壁纸: