打印
[其他ST产品]

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

[复制链接]
293|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
七毛钱|  楼主 | 2024-7-27 18:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我用的单片机是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的软件转换启动功能  

}

使用特权

评论回复
沙发
LOVEEVER| | 2024-7-28 10:44 | 只看该作者
DMA接收后的数据与实际ADC的结果不一致???原因是什么?扫描时间不一样嘛

使用特权

评论回复
板凳
光辉梦境| | 2024-8-24 19:36 | 只看该作者
在使用STM32F103VC单片机进行ADC转换并通过DMA传输数据时,如果发现DMA接收到的数据与实际ADC的结果不一致,可能是DMA配置错误

使用特权

评论回复
地板
一秒落纱| | 2024-8-24 21:00 | 只看该作者
确保DMA通道、数据宽度(8位、16位或32位)、传输方向(从外设到内存)、内存地址增量模式、外设地址增量模式等配置正确。

使用特权

评论回复
5
淡漠安然| | 2024-8-24 22:00 | 只看该作者
检查ADC的采样时间、分辨率、转换模式(单次或连续)、触发源等配置是否正确。

使用特权

评论回复
6
暖了夏天蓝了海| | 2024-8-25 01:00 | 只看该作者
保证DMA传输的目标内存地址是有效的,并且有足够的空间来存储所有ADC转换结果。

使用特权

评论回复
7
江河千里| | 2024-8-25 02:00 | 只看该作者
建议确保ADCDMA的时钟配置正确,ADC的时钟频率不应超过其最大支持频率。

使用特权

评论回复
8
冰春彩落下| | 2024-8-25 04:00 | 只看该作者
如果DMA传输过程中有中断发生,可能会影响DMA的正常工作。确保中断处理程序不会干扰DMA传输

使用特权

评论回复
9
三生万物| | 2024-8-25 05:00 | 只看该作者
检查DMA传输完成后的数据处理代码,确保没有逻辑错误或数据覆盖问题。

使用特权

评论回复
10
别乱了阵脚| | 2024-8-25 07:00 | 只看该作者
需要检查硬件连接是否正确,ADC输入引脚是否有正确的信号输入。

使用特权

评论回复
11
夜阑风雨| | 2024-8-25 09:00 | 只看该作者
确保系统电源稳定,电压符合STM32F103VC的要求。

使用特权

评论回复
12
远山寻你| | 2024-8-25 10:00 | 只看该作者
一定要检查并确认DMAADC的配置代码。使用调试工具(如ST-Link调试器)单步执行代码,观察DMAADC的寄存器状态。在DMA传输完成后,立即读取内存中的数据,并与预期结果进行比较。尝试简化代码,例如先只配置一个ADC通道进行转换,看是否能得到正确的结果。检查是否有其他外设或中断干扰了DMA传输

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

325

主题

2271

帖子

4

粉丝