当前位置:   article > 正文

STM32——DMA的使用_stm32 dma怎么用

stm32 dma怎么用

一、介绍

        MDA是英文Direct Memory Access的缩写,中文意思是直接存储器存取。它是单片机的一个外设,作用主要是用来数据传输。数据传输支持从外设到存储器或者存储器到存储器,这里的存储器可以是 SRAM 或者是 FLASH。 DMA 控制器包含了 DMA1 DMA2,其中 DMA1 7 个通道,DMA2 5 个通道,这里的通道 可以理解为传输数据的一种管道。

       STM32F103 DMA 有以下一些特性:
●每个通道都直接连接专用的硬件 DMA 请求,每个通道都同样支持软件触发。这些功能
通过软件来配置。
●在七个请求间的优先权可以通过软件编程设置 ( 共有四级:很高、高、中等和低 ) ,假如
在相等优先权时由硬件决定 ( 请求 0 优先于请求 1 ,依此类推 )
●独立的源和目标数据区的传输宽度 ( 字节、半字、全字 ) ,模拟打包和拆包的过程。源和
目标地址必须按数据传输宽度对齐。
●支持循环的缓冲器管理。
●每个通道都有 3 个事件标志 (DMA 半传输, DMA 传输完成和 DMA 传输出错 ) ,这 3
事件标志逻辑或成为一个单独的中断请求。
●存储器和存储器间的传输。
●外设和存储器,存储器和外设的传输。
●闪存、 SRAM 、外设的 SRAM APB1 APB2 AHB 外设均可作为访问的源和目标。
●可编程的数据传输数目:最大为 65536

二、功能框图

三、功能描述、

       DMA 控制器和 Cortex™-M3 核心共享系统数据总线,执行直接存储器数据传输。当 CPU DMA 同时访问相同的目标(RAM 或外设 ) 时, DMA 请求会暂停 CPU 访问系统总线达若干个周期,总线
仲裁器执行循环调度,以保证 CPU 至少可以得到一半的系统总线 ( 存储器或外设 ) 带宽。

四、DMA请求

       如果外设要想通过 DMA 来传输数据,必须先给 DMA 控制器发送 DMA 请求, DMA 收到请求信 号之后,控制器会给外设一个应答信号,当外设应答后且 DMA 控制器收到应答信号之后,就会
启动 DMA 的传输,直到传输完毕。
五、通道配置的过程
        
1. DMA_CPARx 寄存器中设置外设寄存器的地址。当外设数据传输请求时,这个地址将
是数据传输的源或目标。
2. DMA_CMARx 寄存器中设置数据存储器的地址。发生外设数据传输请求时,传输的数
据将从这个地址读出或写入这个地址。
3. DMA_CNDTRx 寄存器中设置要传输的数据量。在每个数据传输后,这个数值递减。
4. DMA_CCRx 寄存器的 PL[1:0] 位中设置通道的优先级。
5. DMA_CCRx 寄存器中设置数据传输的方向、循环模式、外设和存储器的增量模式、外
设和存储器的数据宽度、传输一半产生中断或传输完成产生中断。
6. 设置 DMA_CCRx 寄存器的 ENABLE 位,启动该通道。
六、实验
        M-->M(存储器传输到存储器)
        函数的解释:(实验并没有全部的函数都用到)
//初始化DMA默认重置值
void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx);
//DMA的通道的初始化
void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct);
//用默认值填充每个DMA_InitStruct成员。
void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct);
//DMA使能
void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState);
//启用或禁用指定的DMAy通道的中断。
void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);
//设置当前DMAy通道传输中的数据单元数。
void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber); 
//返回当前中剩余数据单元的数量
uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);
//控制DMA的标志位
FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);
void DMA_ClearFlag(uint32_t DMAy_FLAG);
ITStatus DMA_GetITStatus(uint32_t DMAy_IT);
void DMA_ClearITPendingBit(uint32_t DMAy_IT);
        DMA初始化函数的配置:
 
  1. void DMA_Config(void)
  2. {
  3. DMA_InitTypeDef DMA_InitStructure;
  4. // 开启DMA时钟
  5. RCC_AHBPeriphClockCmd(DMA_CLOCK, ENABLE);
  6. // 源数据地址
  7. DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)aSRC_Const_Buffer;
  8. // 目标地址
  9. DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)aDST_Buffer;
  10. // 方向:外设到存储器(这里的外设是内部的FLASH)
  11. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  12. // 传输大小
  13. DMA_InitStructure.DMA_BufferSize = BUFFER_SIZE;
  14. // 外设(内部的FLASH)地址递增
  15. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
  16. // 内存地址递增
  17. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  18. // 外设数据单位
  19. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
  20. // 内存数据单位
  21. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
  22. // DMA模式,一次或者循环模式
  23. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal ;
  24. //DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  25. // 优先级:高
  26. DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  27. // 使能内存到内存的传输
  28. DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
  29. // 配置DMA通道
  30. DMA_Init(DMA_CHANNEL, &DMA_InitStructure);
  31. //清除DMA数据流传输完成标志位
  32. DMA_ClearFlag(DMA_FLAG_TC);
  33. // 使能DMA
  34. DMA_Cmd(DMA_CHANNEL,ENABLE);
  35. }

        数据源设置

  1. const uint32_t aSRC_Const_Buffer[BUFFER_SIZE]= {
  2. 0x01020304,0x05060708,0x090A0B0C,0x0D0E0F10,
  3. 0x11121314,0x15161718,0x191A1B1C,0x1D1E1F20,
  4. 0x21222324,0x25262728,0x292A2B2C,0x2D2E2F30,
  5. 0x31323334,0x35363738,0x393A3B3C,0x3D3E3F40,
  6. 0x41424344,0x45464748,0x494A4B4C,0x4D4E4F50,
  7. 0x51525354,0x55565758,0x595A5B5C,0x5D5E5F60,
  8. 0x61626364,0x65666768,0x696A6B6C,0x6D6E6F70,
  9. 0x71727374,0x75767778,0x797A7B7C,0x7D7E7F80};

        接收设置

  1. int32_t aDST_Buffer[BUFFER_SIZE];
  2. #define SOFT_DELAY Delay(0x0FFFFF);
  3. void Delay(__IO u32 nCount);
  4. uint8_t Buffercmp(const uint32_t* pBuffer, uint32_t* pBuffer1, uint16_t BufferLength);
  5. void DMA_Config(void);

        通过LED的颜色来判断数据是否正确发送,红色为错误,蓝色为正确

  1. int main(void)
  2. {
  3. /* 定义存放比较结果变量 */
  4. uint8_t TransferStatus;
  5. /* LED 端口初始化 */
  6. LED_GPIO_Config();
  7. /* 设置RGB彩色灯为紫色 */
  8. LED_PURPLE;
  9. /* 简单延时函数 */
  10. Delay(0xFFFFFF);
  11. /* DMA传输配置 */
  12. DMA_Config();
  13. /* 等待DMA传输完成 */
  14. while(DMA_GetFlagStatus(DMA_FLAG_TC)==RESET)
  15. {
  16. }
  17. /* 比较源数据与传输后数据 */
  18. TransferStatus=Buffercmp(aSRC_Const_Buffer, aDST_Buffer, BUFFER_SIZE);
  19. /* 判断源数据与传输后数据比较结果*/
  20. if(TransferStatus==0)
  21. {
  22. /* 源数据与传输后数据不相等时RGB彩色灯显示红色 */
  23. LED_RED;
  24. }
  25. else
  26. {
  27. /* 源数据与传输后数据相等时RGB彩色灯显示蓝色 */
  28. LED_BLUE;
  29. }
  30. while (1)
  31. {
  32. }
  33. }

        

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/584437
推荐阅读
相关标签
  

闽ICP备14008679号