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 }

 

 

  

  

 

posted @ 2023-12-07 19:38  菜腿慕  阅读(89)  评论(0)    收藏  举报