当前位置:   article > 正文

STM32特有的数据搬运方式--基于DMA外设的数据搬运_dma搬运64位

dma搬运64位
1.DMA 可以提供 外设寄存器(也是存储器的一种,只是可以用来读写,是软件和硬件的桥梁)和存储器 ,或者 存储器和存储器 之间的高速数据传输,无须 CPU 干预,节省了 CPU 的资源。
外设寄存器:一般指的是 DR 数据寄存器比如 ADC/ 串口的数据寄存器 存储器:运行内存 SRAM 和程序存储器 flash, 即存储变量数组和程序代码的地方。
2. STM32F103C8T6 DMA 资源: DMA1 7 个通道)每个通道都支持软件触发和特定的硬件
3.触发(每个 DMA 有特点的触发源)
软件触发:存储器转运到存储器(一次性转运完数据就结束)软件触发所有通道都可以使用
硬件触发: 外设的数据 转运到存储器(外设的数据有特定的时间节点的限制), 硬件触发要选择指定的 DMA 通道。

 

4.DMA的基本结构框图

DMA触发的条件:

  1. 传输计数器大于0
  2. 触发源有触发信号。若为软件触发,则一直都会有触发信号。
  3. DMA使能,使用DMACmd函数
  4. ps:若需要DMA搬运ADC的数据,则选择硬件触发源,还需开启ADC到DMA的硬件触发信号
5.使用DMA的步骤
DMA初始化函数:
第一步:开启DMA时钟:RCC_AHBPeriphClockCmd
第二步:使用结构体初始化DMA: 包括外设和存储器的起始地址,数据宽度,地址是否自增、传输方向、传输计数器(传输计数器是否需要自动重装)、选择触发源、通道优先级等
DMA转运执行函数(调用一次次函数就执行一次DMA转运):
第一步:先使得DMA使能
第二步:给传输计数器赋值
第三步:DMA使能
第四步:在while循环中使用DMA_GetITStatus获得DMA是否转运完成的标志位。
第五步:使用DMA_ClearFlag清除转运完成的标志位。
主函数:
第一步:调用DMA初始化函数
第二步:在while循环中调用DMA转运执行函数。
代码部分(使用DMA搬运数据---软件触发)
  1. //模块一:DMA初始化函数+DMA执行转运函数
  2. #include "stm32f10x.h" // Device header
  3. uint16_t MyDMA_Size;//传输计数器的值,全局变量
  4. /*初始化DMA:
  5. RCC开启DMA时钟
  6. 外设和存储器的起始地址,数据宽度,地址是否自增
  7. 传输方向
  8. 传输计数器(传输计数器是否需要自动重装)
  9. 选择触发源
  10. 通道优先级
  11. 开关控制
  12. 若为硬件触发需要调用XXX_DMACmd,开启触发信号输出。
  13. 如果需要DMA的中断,就需要调用DMA_ITConfig开启中断输出,并在NVIC配置相应的中断通道。*/
  14. void MyDMA_Init(uint32_t AddrA,uint32_t AddrB,uint16_t Size)//地址必须是32位的
  15. {
  16. MyDMA_Size=Size;//把初始化的Size赋值给全局变量MyDMA_Size
  17. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
  18. DMA_InitTypeDef DMA_InitStructure;
  19. //把地址提取成初始化函数的参数,在初始化时,想转运哪个数组,就把相应数组的地址传进来就可以了
  20. DMA_InitStructure.DMA_PeripheralBaseAddr=AddrA;//转运目标起始地址
  21. DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte; //外设的字节
  22. DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Enable;//外设地址是否自增
  23. //把地址提取成初始化函数的参数,在初始化时,想转运哪个数组,就把相应数组的地址传进来就可以了
  24. DMA_InitStructure.DMA_MemoryBaseAddr=AddrB; //被转运起始地址
  25. DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;//存储器字节
  26. DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable; //存储器地址是否自增
  27. DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC; //传输方向
  28. DMA_InitStructure.DMA_BufferSize=Size; //传输计数器的值,不同的传输数量传输的次数不同
  29. DMA_InitStructure.DMA_Mode=DMA_Mode_Normal; //数据传输的模式,即需不需要自动重装功能
  30. DMA_InitStructure.DMA_M2M=DMA_M2M_Enable; //触发方式,此处选择软件触发
  31. DMA_InitStructure.DMA_Priority=DMA_Priority_Medium; //配置优先级
  32. DMA_Init(DMA1_Channel1,&DMA_InitStructure); //DMA1,通道1,DMA初始化
  33. DMA_Cmd(DMA1_Channel1,DISABLE); //DMA失能,不让DMA初始化就开始转运,而放在DMA转运函数中
  34. /*DMA工作的条件:
  35. 1.传输计数器大于0
  36. 2.触发源有触发信号 若为软件触发,则一直都会有触发信号
  37. 3.DMA使能。
  38. */
  39. }
  40. //调用一次次函数就执行一次DMA转运
  41. void MyDMA_Transfer(void)
  42. {
  43. //若想给传输计数器再次赋值,需要将DMA失能:DMA_Cmd(DMA1_Channel1,DISABLE)
  44. DMA_Cmd(DMA1_Channel1, DISABLE);
  45. DMA_SetCurrDataCounter(DMA1_Channel1,MyDMA_Size); //给传输计数器再次赋值
  46. DMA_Cmd(DMA1_Channel1,ENABLE); //DMA使能
  47. while (DMA_GetITStatus(DMA1_FLAG_TC1)==RESET);//若未转运完成,则一直等待转运完成
  48. DMA_ClearFlag(DMA1_FLAG_TC1);
  49. }
  50. //主函数
  51. #include "stm32f10x.h" // Device header
  52. #include"Delay.h"
  53. #include"OLED.h"
  54. #include"MyDMA.h"
  55. uint8_t DataA[]={0x01,0x02,0x03,0x04};
  56. uint8_t DataB[]={0,0,0,0};
  57. int main(void)
  58. {
  59. //初始化OLED;
  60. OLED_Init();
  61. //调用此函数DateA数组的数据,立刻传输到DataB中
  62. MyDMA_Init((uint32_t)DataA,(uint32_t)DataB,4);
  63. OLED_ShowString(1,1,"DataA");
  64. OLED_ShowString(3,1,"DataB");
  65. OLED_ShowHexNum(1,8,(uint32_t)DataA,8);
  66. OLED_ShowHexNum(3,8,(uint32_t)DataB,8);
  67. while(1)
  68. {
  69. DataA[0]++;
  70. DataA[1]++;
  71. DataA[2]++;
  72. DataA[3]++;
  73. OLED_ShowHexNum(2,1,DataA[0],2);
  74. OLED_ShowHexNum(2,4,DataA[1],2);
  75. OLED_ShowHexNum(2,7,DataA[2],2);
  76. OLED_ShowHexNum(2,10,DataA[3],2);
  77. OLED_ShowHexNum(4,1,DataB[0],2);
  78. OLED_ShowHexNum(4,4,DataB[1],2);
  79. OLED_ShowHexNum(4,7,DataB[2],2);
  80. OLED_ShowHexNum(4,10,DataB[3],2);
  81. Delay_ms(1000);
  82. MyDMA_Transfer();
  83. OLED_ShowHexNum(2,1,DataA[0],2);
  84. OLED_ShowHexNum(2,4,DataA[1],2);
  85. OLED_ShowHexNum(2,7,DataA[2],2);
  86. OLED_ShowHexNum(2,10,DataA[3],2);
  87. OLED_ShowHexNum(4,1,DataB[0],2);
  88. OLED_ShowHexNum(4,4,DataB[1],2);
  89. OLED_ShowHexNum(4,7,DataB[2],2);
  90. OLED_ShowHexNum(4,10,DataB[3],2);
  91. Delay_ms(1000);
  92. }
  93. }

 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号