OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3299|回复: 6

用GD32F103 ADC多通道采集数据错位 非DMA

[复制链接]

11

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2012-7-28
在线时间
6 小时
发表于 2023-5-19 11:00:08 | 显示全部楼层 |阅读模式
1金钱
最近用GD32F103 遇到这个问题,单个通道采集都正常,开了2个以上数据就错位了,本来应该是通道0的数据给adcx_speed ,通道5的数据给adcx_temp ,通道7的数据给adcx_M1V ,结果通道0的数据给了adcx_temp ,通道5的数据给了adcx_M1V ,通道7的数据给了adcx_speed ,求各位大神指正
ADC.C
#include "adc.h"
#include "delay.h"

//初始化ADC
//这里我们仅以规则通道为例
                                                                                                                          
void  Adc_Init(void)
{        
        ADC_InitTypeDef ADC_InitStructure;
  GPIO_InitTypeDef  GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1        , ENABLE );          //使能ADC1通道时钟


        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

        //PA0,PA5,PA7 AD端口配置
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_5 | GPIO_Pin_7;// //PA0 端口配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                                          //模拟输入
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                         //IO口速度为50MHz
  GPIO_Init(GPIOA, &GPIO_InitStructure);                                                                     //初始化GPIO


        ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
        ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描模式设置
        ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//连续转化模式设置
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 1;//需要扫描的通道数
        ADC_Init(ADC1,&ADC_InitStructure);



        ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1
       
   ADC_RegularChannelConfig(ADC1,ADC_Channel_0,1,ADC_SampleTime_1Cycles5);
         ADC_RegularChannelConfig(ADC1,ADC_Channel_5,2,ADC_SampleTime_1Cycles5);
         ADC_RegularChannelConfig(ADC1,ADC_Channel_7,3,ADC_SampleTime_1Cycles5);

        ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1

        delay_ms(1);
        ADC_ResetCalibration(ADC1);        //使能复位校准
        while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束
        ADC_StartCalibration(ADC1);         //开启AD校准
        while(ADC_GetCalibrationStatus(ADC1));         //等待校准结束
}                                  
//获得ADC1值
//ch:通道值
u16 Get_Adc1(u8 ch)   
{
          //设置指定ADC的规则组通道,一个序列,采样时间
        ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_1Cycles5 );        //ADC1,ADC通道,采样时间为1.5周期
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
        return ADC_GetConversionValue(ADC1);        //返回最近一次ADC1规则组的转换结果
}

u16 Get_Adc1_Average(u8 ch,u8 times)
{
        u32 temp_val=0;
        u8 t;
        for(t=0;t<times;t++)
        {
                temp_val+=Get_Adc1(ch);
                delay_us(10);
        }
        return temp_val/times;
}          


MAIN.C
#include "stm32f10x.h"
#include "timer.h"
#include "GPIO.h"
#include "delay.h"       
#include "sys.h"
#include "adc.h"


#define speed_off  0

//u16 speed_lev=0;
u16 adcx_speed = 0;//速度
u16 adcx_temp = 0;//温度
u16 adcx_M1V = 0;
u16 adcx_M2V = 0;
u16 adcx_M1M2V = 0;




/************************************************

************************************************/
int main(void)
{
//                NVIC_Configuration();
                delay_init();                     //延时函数初始化          
                GPIOx_Init();
                Adc_Init();                                  //ADC初始化

  while(1)
        {
                adcx_speed = Get_Adc1(ADC_Channel_0);
                delay_ms(10);
               
                adcx_temp = Get_Adc1(ADC_Channel_5);
                delay_ms(10);
               
                adcx_M1V = Get_Adc1(ADC_Channel_7);
                delay_ms(10);
       
        }

}








最佳答案

查看完整内容[请看2#楼]

已解决,加了一句指令,不知道为什么 u16 Get_Adc1(u8 ch) { ADC_ClearFlag(ADC1,ADC_FLAG_EOC); ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_1Cycles5 ); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )); return ADC_GetConversionValue(ADC1); }
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

11

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2012-7-28
在线时间
6 小时
 楼主| 发表于 2023-5-19 11:00:09 | 显示全部楼层
已解决,加了一句指令,不知道为什么
u16 Get_Adc1(u8 ch)   
{
         
        ADC_ClearFlag(ADC1,ADC_FLAG_EOC);
        ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_1Cycles5 );
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));       
        return ADC_GetConversionValue(ADC1);               
}
回复

使用道具 举报

10

主题

3281

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8206
金钱
8206
注册时间
2020-5-11
在线时间
3700 小时
发表于 2023-5-19 11:19:06 | 显示全部楼层
试一下切换通道后,转换两次,取第二次结果。
专治疑难杂症
回复

使用道具 举报

11

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2012-7-28
在线时间
6 小时
 楼主| 发表于 2023-5-19 11:23:31 | 显示全部楼层
LcwSwust 发表于 2023-5-19 11:19
试一下切换通道后,转换两次,取第二次结果。

这样是正常了,那这是哪里设置有问题吗
回复

使用道具 举报

10

主题

3281

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8206
金钱
8206
注册时间
2020-5-11
在线时间
3700 小时
发表于 2023-5-19 11:28:47 | 显示全部楼层
本帖最后由 LcwSwust 于 2023-5-19 11:36 编辑
wanghy0119 发表于 2023-5-19 11:23
这样是正常了,那这是哪里设置有问题吗

具体原因我也没研究过,建议ADC_SampleTime整大些。
估计是切换通道后立即转换,采样保持电容上的电压还没来得及更新,转换就完成了。
如果ADC引脚串了电阻,电阻与采样保持电容形成RC电路,电阻越大,反应越慢,所以一般建议ADC脚并联电容,这样切换通道后等效串联电阻就很小了,反应能快些。

找了个资料:
https://www.eet-china.com/mp/a25298.html
傲游截图20230519113609.jpg
专治疑难杂症
回复

使用道具 举报

11

主题

31

帖子

0

精华

初级会员

Rank: 2

积分
120
金钱
120
注册时间
2012-7-28
在线时间
6 小时
 楼主| 发表于 2023-5-19 13:33:40 | 显示全部楼层
LcwSwust 发表于 2023-5-19 11:28
具体原因我也没研究过,建议ADC_SampleTime整大些。
估计是切换通道后立即转换,采样保持电容上的电压还 ...

ADC_SampleTime整到ADC_SampleTime_239Cycles5了也是一样
回复

使用道具 举报

10

主题

3281

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8206
金钱
8206
注册时间
2020-5-11
在线时间
3700 小时
发表于 2023-5-19 15:12:26 | 显示全部楼层
wanghy0119 发表于 2023-5-19 13:33
ADC_SampleTime整到ADC_SampleTime_239Cycles5了也是一样

加了一句清标志就好了?
手册中说EOC标志在读数据后就自动清除了,不知是不是写错了,手动清除标志也是个好习惯。
傲游截图20230519151005.jpg
专治疑难杂症
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 08:59

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表