[其他ST产品] stm32 DMA理论+实践

[复制链接]
2173|82
 楼主| 范德萨发额 发表于 2023-11-25 12:19 | 显示全部楼层
代码如下
  1. const int num1=1;

  2. int main(void)
  3. {
  4.         int num=1;

  5.         Usart_Config();
  6.         TIM6_Init();
  7.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);               
  8.        
  9.     while(1)
  10.         {               
  11.                    if(time==1000)
  12.                          {
  13.                                   printf("num=%p num1=%p\r\n",&num,&num1);
  14.                                   time=0;
  15.                          }
  16.         }       
  17. }
 楼主| 范德萨发额 发表于 2023-11-25 12:19 | 显示全部楼层
定义了一个常量num1 和一个变量num,我们打印他们的地址,可以看出num是在2000开头的RAM区,常量则是在0800开头的FLASH,和刚刚给出的图一致,一般flash都会比ram大很多倍,所以不需要改变的数据可以存到flash去,节省ram'的空间
 楼主| 范德萨发额 发表于 2023-11-25 12:19 | 显示全部楼层
 楼主| 范德萨发额 发表于 2023-11-25 12:20 | 显示全部楼层
2)DMA传输框图

88256656175f931fdb.png
通过DMA将一个数据传输到另外一个地方,每次地址给他配置为自加,传输一位DMA的计数器就会自减一次,所以可以根据自己需要传输的数据大致算一下位数。
 楼主| 范德萨发额 发表于 2023-11-25 12:20 | 显示全部楼层
3)DMA单次传输代码
首先先把初始化代码放在这
  1. void MyDMA_Init(uint16_t size,uint32_t MAddr,uint32_t PAddr)
  2. {
  3.          DMA_InitTypeDef  DMA_InitStruct;
  4.        
  5.          RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  6.        
  7.         DMA_InitStruct.DMA_BufferSize=size;
  8.         DMA_InitStruct.DMA_DIR=DMA_DIR_PeripheralSRC;
  9.         DMA_InitStruct.DMA_M2M=DMA_M2M_Enable;
  10.         DMA_InitStruct.DMA_Mode=DMA_Mode_Normal;
  11.         DMA_InitStruct.DMA_Priority=DMA_Priority_High;
  12.         DMA_InitStruct.DMA_MemoryBaseAddr=MAddr;
  13.         DMA_InitStruct.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
  14.         DMA_InitStruct.DMA_MemoryInc=DMA_MemoryInc_Enable;
  15.         DMA_InitStruct.DMA_PeripheralBaseAddr=PAddr;
  16.         DMA_InitStruct.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
  17.         DMA_InitStruct.DMA_PeripheralInc=DMA_PeripheralInc_Enable;

  18.         DMA_Init(DMA1_Channel1,&DMA_InitStruct);
  19.        
  20.         DMA_Cmd(DMA1_Channel1,ENABLE);
  21. }
 楼主| 范德萨发额 发表于 2023-11-25 12:20 | 显示全部楼层
首先还是熟悉的写一个初始化,首先还是声明一个结构体变量,声明到第一行
7750665617618559d4.png
 楼主| 范德萨发额 发表于 2023-11-25 12:20 | 显示全部楼层
然后开启DMA1的时钟,前面说过DMA是挂载在AHB总线上的,1为互联型芯片的参数 2为其余的芯片  我们用的不是互联型的,所以这里去沾2 里面的DMA1

6465365617625d8d8f.png
 楼主| 范德萨发额 发表于 2023-11-25 12:21 | 显示全部楼层
之后是往刚刚声明的结构体对象里面写参数
124316561763224d7b.png
 楼主| 范德萨发额 发表于 2023-11-25 12:21 | 显示全部楼层
这里看着参数很多,其实可以对照前面说的流程,

 楼主| 范德萨发额 发表于 2023-11-25 12:21 | 显示全部楼层
DMA_BufferSize

配置传输计数器的大小BUFFerSize 说了是传一次减一个,所以这里你传几个数据你就写几,这里我们将参数作为了形参传进来,后期好调用。
814836561764abaafa.png
 楼主| 范德萨发额 发表于 2023-11-25 12:21 | 显示全部楼层
DMA_DIR

配置方向DIR 前面说过需要配置是存储器到存储器还是存储器到外设,或者外设到存储器,这个参数的意思是,指定外设地址是要传输的源或者目标,这里有两个参数可以选,一个是是后缀SRC(soure源头)一个是DST(destination目的地),我这里将方向配置为了存储器到外设
 楼主| 范德萨发额 发表于 2023-11-25 12:21 | 显示全部楼层
 楼主| 范德萨发额 发表于 2023-11-25 12:25 | 显示全部楼层
DMA_M2M

这个说过是配置我们是软件触发或者硬件触发 这里选择enable就是软件触发了,前面说过选1就是软件触发嘛,这里看一看一下位,很明显enble是填入的1
401626561773b07614.png
 楼主| 范德萨发额 发表于 2023-11-25 12:27 | 显示全部楼层
DMA_Mode

模式,其实是配置前面所说的,重载器的模式,我们可以配置为重载或者不重载

因为是软件触发所以我们不能开重载(前面说了,这个东西和软件触发效果冲突,一个想尽快减完一个又想减完让你重新减)我们这里就选第二个正常模式了 7160965617747c1e7f.png
 楼主| 范德萨发额 发表于 2023-11-25 12:27 | 显示全部楼层
DMA_Priority

优先级 :前面说过DMA有仲裁器,会判断优先级的,这里就是就算通道号在后面,你也可以给他高优先级

8702656177b4852c6.png
 楼主| 范德萨发额 发表于 2023-11-25 12:27 | 显示全部楼层
DMA_MemoryBaseAddr&DMA_PeripheralBaseAddr

存储器和外设地址:这里写形参的名字,方便等会传参进来
80268656177c1811d6.png
 楼主| 范德萨发额 发表于 2023-11-25 12:28 | 显示全部楼层
7 DMA_MemoryDataSize&DMA_PeripheralDataSize

这个是刚刚说的,数据传输的那点了,配置双方的字节大小,可以配置为8位16位32位,我配置为了8位

92430656177d12543c.png
 楼主| 范德萨发额 发表于 2023-11-25 12:28 | 显示全部楼层
8 DMA_PeripheralInc&DMA_MemoryInc

是否自增,就是传输完一个数据后,地址会不会自己+1

这里我们配置为开启
 楼主| 范德萨发额 发表于 2023-11-25 12:28 | 显示全部楼层
9 初始化结构体和使能DMA

将刚刚配置的参数,通过Init函数写入到DMA的配置中,之后开启cmd开启MDA传输数据,,这里随便选DMA通道都行,因为是软件触发,所以每个通道都能支持。 62049656177ebb3b88.png
 楼主| 范德萨发额 发表于 2023-11-25 12:28 | 显示全部楼层
10 主函数
  1. uint8_t Data1[]={0x01,0x02,0x03,0x14};
  2. uint8_t Data2[]={0,0,0,0};

  3. int main(void)
  4. {
  5.         Usart_Config();
  6.        
  7.         MyDMA_Init(4,(uint32_t)Data2,(uint32_t)Data1);
  8.        
  9.         printf("0x%02x 0x%02x 0x%02x 0x%02x\r\n",Data1[0],Data1[1],Data1[2],Data1[3]);
  10.         printf("0x%02x 0x%02x 0x%02x 0x%02x\r\n",Data2[0],Data2[1],Data2[2],Data2[3]);
  11.     while(1)
  12.         {               
  13.         }       
  14. }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部