10、DMA直接存储器存取
10、DMA直接存储器读取
1、DMA(Direct Memory Access)直接存储器存取
- 数据转运小助手,协助CPU完成数据转运工作,DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源
- 外设:一般指的是外设的数据计算器DR,data register,比如ADC的数据寄存器、串口的数据寄存器等等,
- 存储器:运行内存SRAM和程序存储器Flash,是存储变量数组和程序代码的地方
2、12个独立可配置的通道:
- DMA1(7个通道), DMA2(5个通道)
- 从一个地方移动到另一个地方,需要占用一个通道,DMA多通道进行运转时候,之间可以各转各的互不干扰
3、每个通道都支持软件触发和特定的硬件触发
- 若是存储器到存储器的数据转运,比如把flash里的一批数据转运到SRAM中去,就需要软件触发,触发后,DMA就会一股脑的转运,以最快的速度全部转运好
- 若是外设到存储器的数据转运,不能一股脑的转运,因为外设的数据是有一定时机的,需要硬件触发。比如转运ADC的数据,就得ADC每个通道AD转换完成后,硬件触发一次DMA,之后DMA再转运,触发一次转运一次,才能保证数据正确
- 特定的硬件触发:每个DMA的通道,它的硬件出发源是不一样的,当使用某个外设的硬件出发源,就得使用它连接的那个通道,而不能任意选择通道
4、STM32F103C8T6 DMA资源:DMA1(7个通道)
5、存储器映像
(1)ROM(只读存储器)
一种非易失性、掉电不丢失的存储器
程序存储器flash(主闪存)的用途:存储c语言编译后的程序代码,也是下载程序的位置,运行程序一般也是从主闪存里面开始运行的,数据地址以0800开头的,为主闪存地址
- 系统存储器:BootLoader程序是芯片出厂自动写入的,一般不允许我们修改
- 选项字节:用于存储一些独立于程序代码的配置参数,位置是在ROM区的最后面,下载程序可以不刷新选项字节的内容,这样选项字节的配置就可以保持不变,选项字节里,存的主要是flash的读保护、写保护,还有看门狗等等的配置
(2)RAM(随机存储器)
- 一种易失性、掉电丢失的存储器
- 内核外设寄存器:内核外设就是NVIC和SysTick,内核外设和其他外设不是同个厂家设计的,所以地址被分开
6、寄存器读写
CPU/DMA直接访问Flash,是可以读不可写
SRAM是运行内存,可以任意读写
- 外设寄存器:看数据手册(数据寄存器是可以读写的)
7、DMA基本结构
(1)两个站点
外设寄存器站点(也是存储器,但是一般被叫做外设)
flash和SRAM存储器站点(stm32中存储器一般指flash和SRAM,不包含外设寄存器)
- 由于flash是只读的,所以只能是flash到SRAM的运转
(2)外设和存储器的三个参数
第一个是起始地址,有外设端的起始地址和存储器端的起始地址,这两个参数决定了数据是从哪里来,到哪里去的
第二个参数是数据宽度,指定一次转运要按多大的数据宽度来进行
- 字节Byte(8位,uint8_t)
- 半字节HalfWord(16位,uint16_t)
- 字Wold(32位,uint32_t)
- 第三个参数:地址是否自增,指定一次转运完成后,下一次转运是不是要把地址移动到下一个位置去,相当于是指针p++
- 比如ADC扫描模式用DMA进行数据转运,外设地址是ADC_DR寄存器,
- 外设寄存器地址不用自增,若自增,下次转运就跑到别的寄存器里了
- 存储器地址需要自增,没转运一个数据后,就往后挪,否则会把上次的数据覆盖掉
(3)两个站点的使用
- 如果是存储器到存储器的数据转运,需要把其中一个存储器的地址放在外设寄存器站点
- 外设寄存器只是个名字而已,可以写寄存器,如果写flash的地址,它就会去flash里找,写SRAM就会去SRAM里找
- 甚至可以两个站点换过来使用
(4)传输计数器
- 指定总共需要转运几次的,自减,例如写5,
- DMA就只能进行5次数据转运,每转运一次减1,为0时,不再转运,之前自增的地址,会恢复到起始位置
(5)自动重装器
- 传输计数器减到0之后,是否要自动恢复到最初的值
- 若不使用,5次后结束,若使用,5次后,数据等于0时,立马重装成5,决定了单次还是循环模式,即重装则为循环(扫描模式加连续转换),不重装为单次
(6)DMA的触发控制
触发就是决定DMA需要在什么时机进行转运的。触发源有硬件触发和软件触发,
由M2M参数决定,1为软件触发,0为硬件触发
软件触发
以最快的速度,连续不断地触发DMA,争取早日把传输计数清0,完成这一轮转换(和循环模式同时使用,因为软件触发是清0,循环模式是清0后自动重装,同时用,DMA停不下来)
适用于存储器到存储器的转运,因为存储器到存储器的触发时软件启动、不需要时机、并且想尽快完成任务
硬件触发
硬件触发源可以选择ADC、串口收到数据、定时时间到等等,所以需要硬件触发
硬件达到时机时,传一个信号,来触发DMA进行转运
开关控制,给DMA使能后,DMA就准备就绪,可以进行转运
(7)DMA进行转运的条件
1、开关控制,DMA_Cmd必须使能
2、传输计数器必须大于0
3、触发源必须有触发信号,触发一次转运一次,传输计数器自减一次。当传输计数器等于0,且没有自动重装时,这时无论是否触发,DMA都不会再进行转运了
- 此时就需要DMA_Cmd给DISABLE,关闭DMA,再为传输计数器写一个大于0的数,在DMA_Cmd给Elable开启DMA,DMA才能继续工作,注意下写传输计数器时
- 必须要先关闭DMA再进行,不能在DMA开启时写传输计数器,这是手册里的规定
(8)DMA选择映象
(9) 数据传输
小的写到大的,补0,大的写到小的,高位舍弃掉
8、数据转运+DMA
转运时,两边都要自增,要转运7次,所以传输计数器给7,自动重装暂时不需要,是存储器到存储器,要软件触发
(1)MyDMA.c
1 |
|
(2)main.c
1 |
|
9、ADC扫描模式+DMA
触发后,7个通道依次进行AD转换,转换后的结果放在DC_DR数据寄存器中,在每个单独的通道转换完成后,进行一次DMA数据转运,并且目的地址进行自增,这样数据才不会覆盖
- 此时DMA的配置:
- 外设地址写着ADC_DR这个寄存器的地址
- 存储器的地址可以在SRAM中定一个数组ADValue
- 然后把ADValue的地址当做存储器的地址,之后数据宽度
- 因为ADValue和SRAM数组要的是unit16_t的数据,所以数据宽度都是16位的,即半字传输
- 外设地址不自增,存储器地址自增,传输方向为外设站点到存储器站点
- 传输计数器:计次7次,因为由7个通道
- 计数器是否自动重装,取决ADC的配置,ADC如果是单次扫描,DMA不自动重装,连续扫描,DMA就自动重装
- 在ADC启动下一轮转换的时候,DMA也启动下一轮的转运,ADC和DMA同步工作
- 触发选择:这里ADValue的值是在ADC单个通道转换完成后才会有效,所以转运DMA时机,需要和ADC单个通道转换完成同步,故DMA的触发要选择ADC的硬件触发
- 硬件触发:在每个单独的通道转换完成后,没有任何标志位也不会触发中断,程序不太好判断某一个通道转换完成的时间
- 但虽然单个通道转换完成后,不产生任何标志位和中断。但是可能会产生DMA请求,去触发DMA转运
(1)AD.c
1 |
|
(2)main.c
1 |
|