STM32 DMA直接存储器存取

打印 上一主题 下一主题

主题 1661|帖子 1661|积分 4983

一、DMA简介



  • DMA(Direct Memory Access)直接存储器存取
  • DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输,无须CPU干预,节流了CPU的资源
  • 12个独立可设置的通道: DMA1(7个通道), DMA2(5个通道)
  • 每个通道都支持软件触发(存储器和存储器)和特定的硬件触发(外设和存储器)
  • STM32F103C8T6 DMA资源:DMA1(7个通道)
二、存储器所在


三、DMA框图

 

四 、DMA基本结构


五、两种转运模式


六、代码部分
  1. void DMA_DeInit(DMA_Channel_TypeDef* DMAy_Channelx);//恢复缺损配置
  2. void DMA_Init(DMA_Channel_TypeDef* DMAy_Channelx, DMA_InitTypeDef* DMA_InitStruct);//初始化
  3. void DMA_StructInit(DMA_InitTypeDef* DMA_InitStruct);//结构体初始化
  4. void DMA_Cmd(DMA_Channel_TypeDef* DMAy_Channelx, FunctionalState NewState);//使能
  5. void DMA_ITConfig(DMA_Channel_TypeDef* DMAy_Channelx, uint32_t DMA_IT, FunctionalState NewState);//中断输出使能
  6. //设置当前数据寄存器
  7. void DMA_SetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx, uint16_t DataNumber);
  8. //获取当前数据寄存器,返回传输寄存器的值
  9. uint16_t DMA_GetCurrDataCounter(DMA_Channel_TypeDef* DMAy_Channelx);
  10. FlagStatus DMA_GetFlagStatus(uint32_t DMAy_FLAG);//获取标志位状态
  11. void DMA_ClearFlag(uint32_t DMAy_FLAG);//清除标志位
  12. ITStatus DMA_GetITStatus(uint32_t DMAy_IT);//获取中断状态
  13. void DMA_ClearITPendingBit(uint32_t DMAy_IT);//清除中断挂起位
复制代码
数据转运整体代码:
  1. #include "stm32f10x.h"                  // Device header
  2. //DMA转运的3个条件:
  3. //1:传输计数器大于0
  4. //2:触发源有触发信号(软件触发,所以一直都有触发信号)
  5. //3:DMA使能
  6. uint16_t MyDMA_size;
  7. void MyDMA_init(uint32_t AddrA,uint32_t AddrB,uint16_t Size)
  8. {
  9.         MyDMA_size = Size;
  10.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//DMA是AHB总线设备
  11.        
  12.         DMA_InitTypeDef DMA_InitStruct;
  13.         DMA_InitStruct.DMA_PeripheralBaseAddr = AddrA; //外设站点的起始地址,写一个32位的地址
  14.         DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  15.         //外设站点的数据宽度,这里是以字节的方式传输
  16. // DMA_PeripheralDataSize_Byte     字节,就是uint8_t   
  17. // DMA_PeripheralDataSize_HalfWord    半字,就是uint16_t
  18. // DMA_PeripheralDataSize_Word        字,就是uint32_t
  19.                                                                             
  20.         DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Enable;      //外设站点的是否自增
  21.        
  22.         DMA_InitStruct.DMA_MemoryBaseAddr = AddrB;     //存储器站点的起始地址
  23.         DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;     //存储器站点的数据宽度
  24.         DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;          //存储器站点的是否自增,选择自增。
  25.        
  26.        
  27.         DMA_InitStruct.DMA_DIR  = DMA_DIR_PeripheralSRC;               //传输方向
  28. // DMA_DIR_PeripheralDST         外设站点作为DST,destination,目的地,传输方向是存储器站点到外设站点     
  29. // DMA_DIR_PeripheralSRC         外设站点作为        SRC,source,源头,外设站点到存储器站点的传输方向     
  30.         DMA_InitStruct.DMA_BufferSize = Size;         //缓冲区大小,也就是传输计数器,传输次数
  31.         DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;    //传输模式,是否使用自动重装
  32.         DMA_InitStruct.DMA_M2M = DMA_M2M_Enable;      
  33.         //选择是否是存储器到存储器,也就是选择硬件触发还是软件触发,这里选择软件触发
  34.         DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;    //优先级,按照参数要求,给一个优先级
  35.          
  36.         DMA_Init(DMA1_Channel1,&DMA_InitStruct);
  37.        
  38.        
  39.         DMA_Cmd(DMA1_Channel1,DISABLE);
  40. }
  41. void MyDMA_Transfer(void)  //DMA传输函数
  42. {
  43.          //需要给传输计数器赋值,需要先给DMA失能!!!!!!!!!!
  44.         DMA_Cmd(DMA1_Channel1,DISABLE);
  45.        
  46.         DMA_SetCurrDataCounter(DMA1_Channel1,MyDMA_size);
  47.         DMA_Cmd(DMA1_Channel1,ENABLE);
  48.        
  49.         //等待转运完成
  50. while        (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);         //这里选择转运完成标志位
  51. DMA_ClearFlag(DMA1_FLAG_TC1);
  52. //DMA1_FLAG_GL1  全局标志位
  53. //DMA1_FLAG_TC1  转运完成标志位
  54. //DMA1_FLAG_HT1  转运过半标志位
  55. //DMA1_FLAG_TE1  转运错位标志位
  56. }
复制代码
AD多通道加DMA转运代码:
  1. #include "stm32f10x.h"                  // Device header
  2. uint16_t AD_Value[4];
  3. void AD_init(void)
  4. {
  5.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
  7.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);//DMA是AHB总线设备
  8.        
  9.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  10.        
  11.         GPIO_InitTypeDef GPIO_InitStruct;                     //第一个是结构体类型,后面是它的名字
  12.         GPIO_InitStruct.GPIO_Mode= GPIO_Mode_AIN;         //模式为模拟输入
  13.         GPIO_InitStruct.GPIO_Pin= GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;            //开启所有端口  
  14.         GPIO_InitStruct.GPIO_Speed= GPIO_Speed_50MHz;         //选择50mhz
  15.         GPIO_Init(GPIOA, &GPIO_InitStruct);
  16.        
  17.        
  18.         //配置序列里的通道((1:ADCX,2:指定的通道,3:序列几的位置,4:指定通道的采样时间))
  19.         ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_55Cycles5);
  20.         ADC_RegularChannelConfig(ADC1,ADC_Channel_1,2,ADC_SampleTime_55Cycles5);
  21.         ADC_RegularChannelConfig(ADC1,ADC_Channel_2,3,ADC_SampleTime_55Cycles5);
  22.         ADC_RegularChannelConfig(ADC1,ADC_Channel_3,4,ADC_SampleTime_55Cycles5);
  23.         ADC_InitTypeDef ADC_InitStruct;
  24.         ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;//ADC转换模式,这里选择独立模式,ADC1和ADC2各自转换
  25.         ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;//左对齐还是右对齐
  26.   ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  27.         //外部触发转换选择,触发控制的触发源选择,这里的参数是外部触发none,也就是不使用外部触发,使用内部触发
  28.         ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;//连续转换模式,非扫描模式
  29.         ADC_InitStruct.ADC_ScanConvMode =  ENABLE;      //扫描转换模式,单次转换
  30.   ADC_InitStruct.ADC_NbrOfChannel =  4;           //通道数目,
  31.   ADC_Init(ADC1,&ADC_InitStruct);
  32.        
  33.         //中断和看门狗如果有需要可以在下面配置//
  34.        
  35.        
  36.         //*******************//
  37.        
  38.        
  39.         //****************DMA配置***************//
  40.        
  41.         DMA_InitTypeDef DMA_InitStruct;
  42.         DMA_InitStruct.DMA_PeripheralBaseAddr =(uint32_t)&ADC1->DR; //外设站点的起始地址,写一个32位的地址
  43.         DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  44.         //外设站点的数据宽度,这里是以字节的方式传输
  45. // DMA_PeripheralDataSize_Byte     字节,就是uint8_t   
  46. // DMA_PeripheralDataSize_HalfWord    半字,就是uint16_t
  47. // DMA_PeripheralDataSize_Word        字,就是uint32_t
  48.                                                                             
  49.         DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;      //外设站点的是否自增
  50.        
  51.         DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)AD_Value;     //存储器站点的起始地址
  52.         DMA_InitStruct.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;     //存储器站点的数据宽度
  53.         DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;          //存储器站点的是否自增,选择自增。
  54.        
  55.        
  56.         DMA_InitStruct.DMA_DIR  = DMA_DIR_PeripheralSRC;               //传输方向
  57. // DMA_DIR_PeripheralDST         外设站点作为DST,destination,目的地,传输方向是存储器站点到外设站点     
  58. // DMA_DIR_PeripheralSRC         外设站点作为        SRC,source,源头,外设站点到存储器站点的传输方向     
  59.         DMA_InitStruct.DMA_BufferSize = 4;         //缓冲区大小,也就是传输计数器,传输次数
  60.         DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;    //传输模式,是否使用自动重装
  61.         DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;      
  62.         //选择是否是存储器到存储器,也就是选择硬件触发还是软件触发,这里选择软件触发
  63.         DMA_InitStruct.DMA_Priority = DMA_Mode_Circular;    //优先级,按照参数要求,给一个优先级
  64.          
  65.         DMA_Init(DMA1_Channel1,&DMA_InitStruct);
  66.        
  67.         ADC_DMACmd(ADC1,ENABLE);
  68.         DMA_Cmd(DMA1_Channel1,ENABLE);
  69.        
  70.        
  71.        
  72.         //*****************************************//
  73.        
  74.         ADC_Cmd(ADC1,ENABLE);
  75.        
  76.         //***********对ADC进行校准*****************//
  77.         ADC_ResetCalibration(ADC1);//复位校准
  78.   while (ADC_GetResetCalibrationStatus(ADC1) == SET);//返回复位校准的状态,一直循环等它硬件清0.说明复位校准完成
  79.   ADC_StartCalibration(ADC1);//启动校准,内部电路自动进行校准
  80.   while (ADC_GetCalibrationStatus(ADC1) == SET);//获取校准状态,等待校准是否完成
  81.         ADC_SoftwareStartConvCmd(ADC1,ENABLE); //软件触发转换的函数,ADC开始转换。
  82. }
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

灌篮少年

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表