DMA
一、简介
- 使用场景:DMA可以提供外设(指外设的寄存器,一般是数据寄存器DR)和存储器(运行内存SRAM和程序存储器Flash)或者存储器与存储器之间的高速数据传输
- 优点:无需CPU干预,节省CPU资源
- DMA通道:STM32一共有12个DMA通道,DMA1(7个),DMA2(5个),STM32F103C8T6的DMA资源只有DMA1
- DMA触发条件:每个通道都支持软件触发和特定的硬件触发
- 软件触发:存储器与存储器
- 硬件触发:外设和存储器,每次数据的转运都需要触发,每个DMA通道的硬件触发源是不同的
二、STM32存储器映像
计算机系统由运算器、控制器、存储器、输入设备和输出设备五部分组成,运算器和控制器合一起称为CPU,所以计算机的核心组成就是CPU和存储器。存储器最重要的就是存储器的内容和地址,存储器总共分为ROM和RAM
- ROM:只读存储器(read only memory),是一种非易失性、掉电不丢失的存储器,分为3块,ROM的储存介质都是Flash,一般说的Flash都是说主闪存Flash
- 程序存储器Flash:就是主闪存,起始地址是0x0800 0000,存储C语言编译后的程序代码
- 系统存储器:起始地址是0x1FFF F000,存储BootLoader,用于串口下载,BootLoader程序由芯片出厂自动写入,一般不允许用户自己写入
- 选项字节:起始地址是0x1FFF F800,存储C语言编译后的程序代码,主要存的是Flash的读保护、写保护和看门狗等配置
- RAM:随机存储器,是一种易失性、掉电丢失的存储器,分为3块
-
运行内存SRAM:对于电脑来说运行内存就是内存条,起始地址是0x2000 0000,存储运行过程中的临时变量也就是我们在程序中定义变量、数组、结构体的地方
-
外设寄存器:起始地址是0x4000 0000,存储各个外设的配置参数
-
内核外设寄存器:起始地址是0xE000 0000,存储内核各个外设的配置参数
-
三、DMA框图
总线矩阵的左端是主动单元,拥有存储器的访问权;右端是被动单元,它们的存储器只能被左边的主动单元读写;由于DMA需要转运数据,那就必须能够访问被动单元的存储器,所以DMA也必须有访问的主动权,那主动单元除了内核CPU,剩下的就是DMA总线了
- 主动单元:内核有DCode和系统总线,DCode专门访问Flash,系统总线访问其他的被动单元
- 被动单元:在图中就是单片机上的各种外设,它们作为DMA的硬件触发源可以触发DMA请求
DMA总线:从图中能看出总线矩阵右端总共有3条DMA总线,分别是DMA1、DMA2和以太网的DMA,从DMA1和DMA2的框图中能看见它们分别有7个通道和5个通道,其中的每一条通道都可以单独设置转运数据的原地址和目的地址。
DMA框图中有一个仲裁器和AHB从设备,仲裁器:虽然DMA有多条通道,但是每个DMA最终都只有一条总线,也就是一个DMA同一时间只能转运一个数据,那么仲裁器的作用就是选择通道,如果同一条DMA总线的通道产生了冲突, 那么就由仲裁器根据通道的优先级来决定数据转运的顺序;AHB从设备:DMA本身作为一个外设,他也会有相应的配置寄存器,在图中它连接在了AHB总线上,所以DMA既是总线的矩阵的主动单元可以读写各种存储器,也是被动单元,CPU可以通过系统总线经过总线矩阵和AHB总线对DMA进行配置。
DMA数据转运程序
一、程序功能
主程序定义两个数组DataA和DataB,使用DMA将DataA的数据转运到DataB中
uint8_t DataA[] = {
0x01, 0x02, 0x03,0x04};
uint8_t DataB[] = {
0, 0, 0, 0};
二、程序实现
1.复制OLED的工程文件,重命名为08_1DMA数据转运
2.在工程的System目录下新建DMA的.c文件和.h文件
因为DMA不涉及外围硬件电路,所以建在System目录下
3.在MyDMA.c文件中编写DMA初始化函数
由DMA的基本结构图得到初始化步骤
- RCC开启DMA时钟
- 配置DMA,初始化结构体
- 开启DMA
#include "stm32f10x.h" // Device header
//一、RCC开启DMA时钟
//二、配置DMA,初始化结构体
//三、开启DMA,如果想要在初始化之后就立刻使用DMA,就可以在初始化DMA函数中开启DMA
uint16_t MyDMA_Size = 0;
void MyDMA_Init(uint32_t AddrA, uint32_t AddrB, uint16_t Size)
{