你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

用DMA传输ADC转换结果, 数据不正确

[复制链接]
cpev 提问时间:2018-3-15 09:39 /
  我用的单片机是STM32F103VC,扫描ADC1的8个通道,用DMA1传输转换结果。DMA接收后的数据与实际ADC的结果不一致。
部分代码如下:
void CSL_ADC_Init(void)
{   
     GPIO_InitTypeDef GPIO_InitStructure;         
         ADC_InitTypeDef ADC_InitStructure;

         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC|RCC_APB2Periph_ADC1,ENABLE);         
         RCC_ADCCLKConfig(RCC_PCLK2_Div6);         //设置ADC分频因子6 72M/6=12M,ADC最大时间不能超过14M
         
         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;         
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                  //模拟输入引脚
         GPIO_Init(GPIOA,&GPIO_InitStructure);            
         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;         
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                  //模拟输入引脚
         GPIO_Init(GPIOC,&GPIO_InitStructure);         

         //ADC1初始化
         ADC_DeInit(ADC1);         //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值         
         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1工作在独立模式
         ADC_InitStructure.ADC_ScanConvMode = ENABLE; //模数转换工作在扫描模式
         ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //模数转换工作在单次转换模式
         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//转换由软件而不是外部触发启动
         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
         ADC_InitStructure.ADC_NbrOfChannel = 8; //顺序进行规则转换的ADC通道的数目
         ADC_Init(ADC1,&ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器            
         ADC_Cmd(ADC1,ENABLE);  //使能指定的ADC1
         
         //ADC1校准
         ADC_ResetCalibration(ADC1); //使能复位校准           
         while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束  
         ADC_StartCalibration(ADC1);  //开启AD校准
         while(ADC_GetCalibrationStatus(ADC1));   //等待校准结束

         //配置每个通道的转换次序和采样时间
         ADC_RegularChannelConfig(ADC1,ADC_Channel_1, 1,ADC_SampleTime_71Cycles5); //TC1                                  
         ADC_RegularChannelConfig(ADC1,ADC_Channel_2, 2,ADC_SampleTime_71Cycles5); //TC2                                  
         ADC_RegularChannelConfig(ADC1,ADC_Channel_3, 3,ADC_SampleTime_71Cycles5); //TC3                                  
         ADC_RegularChannelConfig(ADC1,ADC_Channel_4, 4,ADC_SampleTime_71Cycles5); //TC4          
         ADC_RegularChannelConfig(ADC1,ADC_Channel_5, 5,ADC_SampleTime_71Cycles5); //TC5                                  
         ADC_RegularChannelConfig(ADC1,ADC_Channel_6, 6,ADC_SampleTime_71Cycles5); //TC6                                  
         ADC_RegularChannelConfig(ADC1,ADC_Channel_10,7,ADC_SampleTime_71Cycles5); //Current1                                  
         ADC_RegularChannelConfig(ADC1,ADC_Channel_11,8,ADC_SampleTime_71Cycles5); //Current2                                           
}
void CSL_DMA_Init(void)
{      
        DMA_InitTypeDef DMA_InitStructure;
       
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);        //使能DMA传输
    DMA_DeInit(DMA1_Channel1);   //将DMA的通道1寄存器重设为缺省值
    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&ADC1->DR); //DMA外设ADC1转换结果基地址
    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC1Result;  //DMA内存基地址  ADC1Result 为数组
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //数据传输方向,从外设读取数据到内存
        DMA_InitStructure.DMA_BufferSize = 32; //DMA通道的DMA缓存的大小
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;  //内存地址寄存器递增
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; //数据宽度为32位
        DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Word; //数据宽度为32位
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//工作在正常缓存模式
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA1通道1拥有中优先级
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x没有设置为内存到内存传输
        DMA_Init(DMA1_Channel1,&DMA_InitStructure);   
        DMA_Cmd(DMA1_Channel1,ENABLE);
}


void APP_Measure_Temperature_Current(void)  //扫描ADC1 8个通道,用DMA传输数据  100ms周期调用
{             

         ADC_DMACmd(ADC1,ENABLE);          //开启ADC1 DMA传输         
         ADC_SoftwareStartConvCmd(ADC1,ENABLE); //使能指定的ADC1的软件转换启动功能           
         DMA_Cmd(DMA1_Channel1, ENABLE);          
         DMA_SetCurrDataCounter(DMA1_Channel1,32);         
         while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); //等待转换结束  大约56us
         while(DMA_GetFlagStatus(DMA1_FLAG_TC1) != RESET)
         {
            DMA_ClearFlag(DMA1_FLAG_TC1);    //清除通道1传输完成标志
            break;
         }
         ADC_DMACmd(ADC1,DISABLE);                     //关闭ADC1 DMA传输         
         DMA_Cmd(DMA1_Channel1,DISABLE);
         ADC_SoftwareStartConvCmd(ADC1,DISABLE); //关闭指定的ADC1的软件转换启动功能  

}


是配置问题,还是其他。请赐教,第一次使用DMA。
收藏 评论22 发布时间:2018-3-15 09:39

举报

22个回答
回答时间:2018-3-15 09:44:52
楼主能否描述一下数据是怎么样的不对,我们一般使用DMA中断方式处理。配置上看是一样的。可以只测试一路ADC,保证采集正确后,再增加其他路。
toofree 回答时间:2018-3-15 09:58:13
怎么个不对法?
函数固件库中样例程序走起,有用DMA来ADC的样例。我第一次用ADC就是DMA的,非常省事。 傲游截图20180315095854.png
bargagebaobei 回答时间:2018-3-15 10:00:31
看不出来什么问题  请教一下楼主用的vref是多少 采集的信号量超过vref了没有 还有就是可以直接将采集信号连接到地或者上限 看看数值对不对 还有也可以试试将采样时间设置到最大 这样也可以增加采样的稳定性
cpev 回答时间:2018-3-15 10:21:17
安 发表于 2018-3-15 09:44
楼主能否描述一下数据是怎么样的不对,我们一般使用DMA中断方式处理。配置上看是一样的。可以只测试一路ADC ...

只测试一路的话,数据也不对。DMA_InitStructure.DMA_BufferSize DMA_InitStructure.DMA_PeripheralDataSize         DMA_InitStructure.DMA_MemoryDataSize 这三个该怎么设置, ADC转换结果寄存器是32位的.
回答时间:2018-3-15 10:26:15
DMA_InitStructure.DMA_BufferSize = 缓冲区的大小;

        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_HalfWord;
cpev 回答时间:2018-3-15 10:35:10
安 发表于 2018-3-15 10:26
DMA_InitStructure.DMA_BufferSize = 缓冲区的大小;

        DMA_InitStructure.DMA_PeripheralDataSize = DMA_Pe ...

为什么是DMA_PeripheralDataSize_HalfWord,ADC转换结果寄存器是32位的,应该是DMA_PeripheralDataSize_Word的吧,如果只转一路的话,DMA_InitStructure.DMA_BufferSize 为4个字节吗?
回答时间:2018-3-15 10:54:36
ADC的数据最大是12位,用16位存储即可。如图:
微信截图_20180315105341.png
MrJiu 回答时间:2018-3-15 10:58:16
Cube走起。。。初始化配置一般直接OK!!!
cpev 回答时间:2018-3-15 11:04:58
安 发表于 2018-3-15 10:54
ADC的数据最大是12位,用16位存储即可。如图:

嗯 我改成16位的,但得到的结果只有低8位,高8位传不过来。
123下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版