20_DMA数据转运
1、硬件
1.1DMA介绍
DMA可以提供外设(广义上也是存储器的一种)和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节省了CPU的资源。STM32F103C8T6的DMA资源为DMA1(7个通道),
每个通道都支持软件触发(用于存储器之间的数据转运)和特定的硬件触发(外设与存储器之间的数据传输)
1.2存储器影像

以上均能称为存储器
程序存储器Flash主要存储程序代码与常量数据。不需要修改所以是ROM
系统存储器存储Bootloader,一般为芯片出厂自动导入
选项字节存储读/写保护、看门狗等
SRAM为运行内存,是RAM的一种,存储临时变量例如变量、数组等
外设寄存器,也是RAM的一种,存储外设的配置参数,例如ADC1->DR,为ADC1的数据寄存器的结构体指针,对其取址可得到数据寄存器的地址
内核外设寄存器,包括NVIC和SYSTICK
1.3 DMA框图

步骤:1、开启DMA时钟
2、初始化DMA 结构体并配置结构体
包括设置外设与存储器(没有明确规定谁是外设谁是存储器,一般存储器也可以填入外设栏)的起始地址、数据宽度(分为字节,半字,字,分别为8位、16位、32位),与地址是否自增;设置方向(外设到存储器或是存储器到外设);设置传输寄存器(自减计数器,写入次数即为DMA转运次数,写数据时应该关闭DMA);设置自动重装寄存器(到传输寄存器到0后又恢复原值,不能与软件同时使用,否则会一直陷入DMA转运中;设置M2M(决定是硬件触发还是软件触发);设置优先级
3、使能DMA-cmd
DMA转运三大条件:1、cmd使能 2、传输计数器大于0 3、触发源有触发信号
数据宽度与对齐

当数据宽度不同时,
源端宽度数据小于目标宽度,目标数据前面补零;
源端宽度数据小于目标宽度,目标数据舍弃高位。
2、接线图

与OLED接线图相同,不涉及其他外设
3、软件程序
3.1存储器数据转运模块
不涉及外设,将其设置在系统文件夹中。
1 #include "stm32f10x.h" 2 3 void mydma_init(uint32_t DATA_A ,uint32_t DATA_B,uint16_t num) 4 { 5 /*开启DMA时钟*/ 6 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 7 /*初始化DMA结构体*/ 8 DMA_InitTypeDef DMA_InitStructure; 9 10 DMA_InitStructure.DMA_MemoryBaseAddr = DATA_B;//存储器起始地址 11 DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte ;//存储器数据宽度 12 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable ; //存储器地址自增 13 DMA_InitStructure.DMA_PeripheralBaseAddr = DATA_A ;//外设起始地址 14 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte ;//外设数据宽度 15 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable ;//外设地址自增 16 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;//不适用自动重装器,软件触发与自动重装器不兼容,本实验数据转运选择软件触发 17 DMA_InitStructure.DMA_BufferSize = num ;//传输计数器值,为自减计数器 18 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC ;//DMA传输方向,由外设传向存储器 19 DMA_InitStructure.DMA_M2M = DMA_M2M_Enable ;//设置为软件触发 20 DMA_InitStructure.DMA_Priority = DMA_Priority_High ;//设置转运优先级 21 DMA_Init( DMA1_Channel1, & DMA_InitStructure); 22 /*使能DMA*/ 23 DMA_Cmd(DMA1_Channel1, ENABLE);//由于是软件触发,通道不起作用,可随意选择通道 24 25 }
主函数程序
1 #include "stm32f10x.h" // Device header 2 #include "Delay.h" 3 #include "OLED.h" 4 #include "MYDMA.h" 5 6 uint8_t DATA_A[]={0x01,0x02,0x03,0x04}; 7 uint8_t DATA_B[]={0,0,0,0}; 8 int main(void) 9 { 10 /*模块初始化*/ 11 OLED_Init(); //OLED初始化 12 OLED_ShowHexNum(1,1,DATA_A[0],2); 13 OLED_ShowHexNum(1,4,DATA_A[1],2); 14 OLED_ShowHexNum(1,7,DATA_A[2],2); 15 OLED_ShowHexNum(1,10,DATA_A[3],2); 16 OLED_ShowHexNum(2,1,DATA_B[0],2); 17 OLED_ShowHexNum(2,4,DATA_B[1],2); 18 OLED_ShowHexNum(2,7,DATA_B[2],2); 19 OLED_ShowHexNum(2,10,DATA_B[3],2); 20 mydma_init((uint32_t)DATA_A,(uint32_t)DATA_B,4); 21 OLED_ShowHexNum(3,1,DATA_A[0],2); 22 OLED_ShowHexNum(3,4,DATA_A[1],2); 23 OLED_ShowHexNum(3,7,DATA_A[2],2); 24 OLED_ShowHexNum(3,10,DATA_A[3],2); 25 OLED_ShowHexNum(4,1,DATA_B[0],2); 26 OLED_ShowHexNum(4,4,DATA_B[1],2); 27 OLED_ShowHexNum(4,7,DATA_B[2],2); 28 OLED_ShowHexNum(4,10,DATA_B[3],2); 29 30 31 while (1) 32 { 33 34 } 35 36 }

浙公网安备 33010602011771号