GD32E103C8T6 ADC采集到的数据不稳定

[复制链接]
8900|12
手机看帖
扫描二维码
随时随地手机跟帖
ouyanglei92|  楼主 | 2021-5-15 18:19 | 显示全部楼层 |阅读模式
本帖最后由 ouyanglei92 于 2021-5-15 18:28 编辑

刚上手使用GD32E103C8T6的ADC功能,在参考电源比较稳定的情况下,ADC的值乱跳(尝试了各种方法,无法),有朋友遇到过这种情况吗
目前用的ADC0的一通道进行设置,代码在下楼

使用特权

评论回复
评论
ouyanglei92 2021-5-17 16:26 回复TA
下述代码已经调试可用,有需要的朋友可以直接粘贴到自己工程中使用 
ouyanglei92 2021-5-17 16:24 回复TA
原因已经找到。谢谢各位朋友的热心帮助! 问题原因: 3.3V LDO芯片输出电压纹波(最大有400mv,波形震荡式的)比较大导致了,重换一个就好了。因为之前一直用这个LDO芯片,没太留意是降压稳压的问题。目前看用电阻降压的方式输入给ADC还算稳定,如果条件允许尽量在ADC输入前端设置一个电压跟随器吧,减少输出阻抗,保证所有的输入电压都加到了ADC输入端。 
ouyanglei92|  楼主 | 2021-5-15 18:23 | 显示全部楼层
本帖最后由 ouyanglei92 于 2021-5-15 18:24 编辑

/* 定义ADC_TEST,只是用单个通道持续规则转换 */
#define ADC_TEST 1
#if ADC_TEST
static uint32_t adc_test_value = 0;
uint32_t get_adc_test_value(void)
{
        return adc_test_value;
}
#endif

//时钟引脚初始化
void adc_hw_init(void)
{
        rcu_periph_clock_enable(RCU_AF);   
        rcu_periph_clock_enable(RCU_DMA0);  
        rcu_periph_clock_enable(RCU_GPIOA);
        rcu_periph_clock_enable(RCU_ADC0);
        
        gpio_init(RCU_GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, GPIO_PIN_0);
        gpio_init(RCU_GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, GPIO_PIN_1);
        gpio_init(RCU_GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, GPIO_PIN_4);
        gpio_init(RCU_GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, GPIO_PIN_5);
        gpio_init(RCU_GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_2MHZ, GPIO_PIN_6);
}

//复位ADC和DMA外设
static void adc0_reset(void)
{
        rcu_periph_clock_enable(RCU_ADC0);
        adc_disable(ADC0);
        adc_deinit(ADC0);        
        
        adc_interrupt_disable(ADC0, ADC_INT_EOC);
        adc_interrupt_disable(ADC0, ADC_INT_EOIC);
        adc_interrupt_flag_clear(ADC0, ADC_INT_EOC);
        adc_interrupt_flag_clear(ADC0, ADC_INT_EOIC);
        
#if !ADC_TEST               
        dma_interrupt_disable(DMA0, DMA_CH0, DMA_INT_FTF|DMA_INT_ERR);
        dma_channel_disable(DMA0, DMA_CH0);        
        dma_interrupt_flag_clear(DMA0, DMA_CH0, DMA_INT_FLAG_FTF|DMA_INT_FLAG_ERR);
        dma_deinit(DMA0, DMA_CH0);
#endif        
}

void adc_init(void)
{               
        adc_hw_init();
        
        rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6);  //108/6=18Mhz
        adc0_reset();
        
        delay_1ms(10);
                        
        adc_mode_config(ADC_MODE_FREE);
        adc_resolution_config(ADC0, ADCBIT);      
        adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);  
               
#if !ADC_TEST        
        adc_dma_mode_enable(ADC0);
#endif                        
        adc_special_function_config(ADC0 , ADC_CONTINUOUS_MODE, ENABLE); //³ÖÐøģʽ
        
#if ADC_TEST
        adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1);
        adc_regular_channel_config(ADC0, 0,  ADC_CHANNEL_0,   ADC_SAMPLETIME_71POINT5);
        
#else
        adc_special_function_config(ADC0 , ADC_SCAN_MODE, ENABLE);   
        
        adc0_receive_dma_config();
        
        adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 5);
        adc_regular_channel_config(ADC0, 0,  ADC_CHANNEL_0,   ADC_SAMPLETIME_55POINT5);
        adc_regular_channel_config(ADC0, 1,  ADC_CHANNEL_1,   ADC_SAMPLETIME_55POINT5);
        adc_regular_channel_config(ADC0, 2,  ADC_CHANNEL_4,   ADC_SAMPLETIME_55POINT5);
        adc_regular_channel_config(ADC0, 3,  ADC_CHANNEL_5,   ADC_SAMPLETIME_55POINT5);
        adc_regular_channel_config(ADC0, 4,  ADC_CHANNEL_6,   ADC_SAMPLETIME_55POINT5);
#endif
        
        adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE);
        adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE);  
        
        adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC);
        adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOIC);

        adc_enable(ADC0);
        
        delay_1ms(2);
        adc_calibration_enable(ADC0);
        delay_1ms(10);
        first_cmp = 0;
        
        NVIC_SetPriority(ADC0_1_IRQn, 9);
        NVIC_EnableIRQ(ADC0_1_IRQn);
        
        NVIC_SetPriority(DMA0_Channel0_IRQn, 10);
        NVIC_EnableIRQ(DMA0_Channel0_IRQn);
        
        adc_interrupt_enable(ADC0, ADC_INT_EOC);  
               
        adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL);
}

//中断函数
void ADC0_1_IRQHandler(void)
{
        if( SET==adc_interrupt_flag_get(ADC0, ADC_INT_FLAG_EOC) )
        {
                adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_EOC);
#if ADC_TEST
                adc_test_value = ADC_RDATA(ADC0);//ADC_CONV(ADC_RDATA(ADC0));
#endif
        }               
        adc_interrupt_flag_clear(ADC0, ADC_INT_FLAG_WDE|ADC_INT_FLAG_EOIC);
}

使用特权

评论回复
ouyanglei92|  楼主 | 2021-5-15 18:26 | 显示全部楼层
ouyanglei92 发表于 2021-5-15 18:23
/* 定义ADC_TEST,只是用单个通道持续规则转换 */
#define ADC_TEST 1
#if ADC_TE ...

测试数据如下:(波动厉害)
ADC TEST: 854
ADC TEST: 774
ADC TEST: 843
ADC TEST: 777
ADC TEST: 834
ADC TEST: 806
ADC TEST: 832
ADC TEST: 857
ADC TEST: 815
ADC TEST: 776
ADC TEST: 844
ADC TEST: 865
ADC TEST: 791
ADC TEST: 842
ADC TEST: 808
ADC TEST: 853
ADC TEST: 771

使用特权

评论回复
lvyunhua| | 2021-5-16 15:50 | 显示全部楼层
适当降低ADC的采样频率,同时进行ADC采样值滤波。

使用特权

评论回复
ouyanglei92|  楼主 | 2021-5-16 20:40 | 显示全部楼层
lvyunhua 发表于 2021-5-16 15:50
适当降低ADC的采样频率,同时进行ADC采样值滤波。

频率降到9M试过,还是一样。这个波动挺大的,平均值滤波外加低通滤波数据还是不稳定。几十个LSB的误差,怎么滤都无法接受

使用特权

评论回复
sonicll| | 2021-5-17 09:08 | 显示全部楼层
采样周期换成239.5试试,还有你输入通道的管脚上有接电阻电容之类的东西吗,采样值波动大,有可能是输入阻抗不匹配

使用特权

评论回复
zeshoufx| | 2021-5-17 10:31 | 显示全部楼层
ouyanglei92 发表于 2021-5-15 18:26
测试数据如下:(波动厉害)
ADC TEST: 854
ADC TEST: 774

不应该吧,,,波动这么大,,,

使用特权

评论回复
ouyanglei92|  楼主 | 2021-5-17 13:31 | 显示全部楼层
sonicll 发表于 2021-5-17 09:08
采样周期换成239.5试试,还有你输入通道的管脚上有接电阻电容之类的东西吗,采样值波动大,有可能是输入阻 ...

1.5K的电阻直接分压输入ADC,已经是最大采样周期,采样时钟频率已经调到9Mhz

使用特权

评论回复
ouyanglei92|  楼主 | 2021-5-17 13:32 | 显示全部楼层
zeshoufx 发表于 2021-5-17 10:31
不应该吧,,,波动这么大,,,

是呀,现在排查中。我用开发板试试看是不是电路硬件的问题

使用特权

评论回复
ouyanglei92|  楼主 | 2021-5-17 16:24 | 显示全部楼层
ouyanglei92 发表于 2021-5-17 13:32
是呀,现在排查中。我用开发板试试看是不是电路硬件的问题

原因已经找到。谢谢各位朋友的热心帮助! 问题原因: 3.3V LDO芯片输出电压纹波(最大有400mv,波形震荡式的)比较大导致了,重换一个就好了。因为之前一直用这个LDO芯片,没太留意是降压稳压的问题。目前看用电阻降压的方式输入给ADC还算稳定,如果条件允许尽量在ADC输入前端设置一个电压跟随器吧,减少输出阻抗,保证所有的输入电压都加到了ADC输入端。

使用特权

评论回复
Lindaic| | 2021-9-14 16:34 | 显示全部楼层
请问,GD芯片ADC采样输入如果为0时,采样是多少?例如输入为0,ADC采样理论上应该为0,实际上会不会有超过10的跳动?谢谢!

使用特权

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

本版积分规则

2

主题

31

帖子

0

粉丝