打印

百思不得其解的GD32F150的ADC采集问题

[复制链接]
3504|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
siliconnect|  楼主 | 2021-6-4 16:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 siliconnect 于 2021-6-4 16:36 编辑

void adc_base_config(void)
{
    /* 复位ADC外设 */
    adc_deinit();
    adc_disable();
        
    /* 温度传感器和Vrefint通道禁能 */        
    adc_tempsensor_vrefint_disable();
               
    /* 使能ADC 时钟*/
    rcu_periph_clock_enable(RCU_ADC);
        
    /* 配置ADC 时钟*/
    rcu_adc_clock_config(RCU_ADCCK_APB2_DIV8);
        
    /* ADC 扫描模式禁止*/
    adc_special_function_config(ADC_SCAN_MODE,DISABLE);
    /* ADC 连续模式使能*/
    adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE);
               
    /* ADC 数据对齐配置:右对齐*/
    adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
        
    /* ADC 通道长度配置:1 */
    adc_channel_length_config(ADC_REGULAR_CHANNEL, 1);
    adc_channel_length_config(ADC_INSERTED_CHANNEL, 1);
               
   /* ADC 规则通道: CPU内部温度,规则组软件触发*/
    adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_SWRCST);
   /* ADC 注入通道:ADC采集,注入组软件触发*/
    adc_external_trigger_source_config(ADC_INSERTED_CHANNEL, ADC_EXTTRIG_INSERTED_SWRCST);
        
    /* ADC 规则通道配置:规则组0、ADC通道16、采样时间*/
    adc_regular_channel_config(0, ADC_CHANNEL_16, ADC_SAMPLETIME_55POINT5);
   /* ADC 注入通道配置:注入组0、ADC通道1、采样时间*/
    adc_inserted_channel_config(ADC_INSERTED_CHANNEL_0, ADC_CHANNEL_1, ADC_SAMPLETIME_28POINT5);

    /* ADC 使能触发允许:规则组 */
    adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
   /* ADC 使能触发允许:注入组 */
   adc_external_trigger_config(ADC_INSERTED_CHANNEL, ENABLE);
               
    /* 温度传感器和Vrefint通道使能 */
    adc_tempsensor_vrefint_enable();
    adc_enable();
    delay_1ms(10);  //wait≥1ms
    adc_calibration_enable();
}



/*!
    \brief      pd_get_adc
    \param[in]  none
    \param[out] none
    \retval     vol_value
*/
uint16_t adc_get_adc(uint8_t chn)
{
    uint16_t adc_value;
    adc_flag_clear(ADC_FLAG_EOC);               //清除EOC 标志位
    adc_software_trigger_enable(ADC_INSERTED_CHANNEL);
    while(SET != adc_flag_get(ADC_FLAG_EOC));   //等待ADC 转换完成
    adc_value = adc_inserted_data_read(chn);
    return adc_value;
}


/*!
    \brief      adc_rcu_config
    \param[in]  none
    \param[out] none
    \retval     none
*/
void adc_rcu_config(void)
{
    rcu_periph_clock_enable(ADC_IN1_GPIO_CLK);
    rcu_periph_clock_enable(RCU_ADC);
    rcu_adc_clock_config(RCU_ADCCK_APB2_DIV6);
}
/*!
    \brief      adc_gpio_config
    \param[in]  none
    \param[out] none
    \retval     none
*/
void adc_gpio_config(void)
{
    /* config the GPIO as analog mode */
    gpio_mode_set(ADC_IN1_GPIO_PORT, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, ADC_IN1_GPIO_PIN);
}



void  main(void)
{
    uint16_t  val;
    //外部24MHz晶振,已正确倍频到72MHz
    systick_config();   
    adc_rcu_config();
    adc_gpio_config();
    adc_base_config();
    //.....
    while(1)
    {
           //PA1是ADC管脚输入, 为了测试方便我固定接了一个2V的文博极低的电压测试
           val=adc_get_adc(ADC_INSERTED_CHANNEL_0);            //......
           delay_ms(100);
    }
}

问题描述,我就一个通道软件注入方式采集ADC,
还有一个是规则组的内部温度通道16,也是软件触发读
那这样配置没毛病吧?,但是如下配置每次复位CPU或者断电再上电ADC值  一部分情况2V,10次通断电或者软复位就有2次至少变 2.2V
adc_special_function_config(ADC_SCAN_MODE,DISABLE);
adc_special_function_config(ADC_CONTINUOUS_MODE, DISABLE);

但现在, 连续模式要设置enable才能正确读ADC值 每次都是  2.0V; 试过几百次都是正确的2.0Vadc_special_function_config(ADC_SCAN_MODE,DISABLE);
adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE);

否则
这是为何呢?不要连续读,为何只能ADC_CONTINUOUS_MODE设置ENABLE才能正确读?百思不得解,还请帮忙看下哪里不对呢?



另外说明:CPU测温可以读出正确的,但应为CPU温度会变动些,这里我先没去关注它 是否对错。
CPU读温代码也贴下,如下:
/*!
    \brief      gd32_cpu_temperature
    \param[in]  none
    \param[out] none
    \retval     (CPU实际温度值+273°C)x10倍  25.5°C=10*(25.5+273)=0BA9
*/
uint16_t gd32_cpu_temperature(void)
{
          uint16_t  adc_value;
          uint16_t  t_value;
          float     vol_value;
          float     cpu_temp;        
          adc_flag_clear(ADC_FLAG_EOC);                     //清除EOC 标志位
          adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
          while(SET != adc_flag_get(ADC_FLAG_EOC));  //等待ADC 转换完成
          adc_value = adc_regular_data_read();
          vol_value = (float)adc_value*(3.3/4096);        //转换为电压值
          cpu_temp = ((1.43-(float)vol_value)/0.0043)+25; //计算温度
          t_value=((int)(cpu_temp*10))%10;               //取一位小数
          t_value=(cpu_temp)*10;                              //扩大10倍        
         return t_value;
}





使用特权

评论回复
沙发
siliconnect|  楼主 | 2021-6-7 17:51 | 只看该作者
请帮忙看下什么问题呢?

使用特权

评论回复
板凳
sonicll| | 2021-6-8 09:59 | 只看该作者
开了连续模式就正常,说明只有前几次采样有问题,连续模式由于不停的采样,后面的新数据把前面的数据覆盖了。可以试试在ADC使能之后,触发采样之前,再增加一些延时看看,还有采样周期可以配置的大一些

使用特权

评论回复
评论
sonicll 2021-6-9 09:36 回复TA
@siliconnect :是我看错了,开连续模式,ADC数据寄存器被不停的覆盖,这种只有规则组才会出现,而你现在用的是注入组,连续模式对注入组是无效的,应该不会有影响,你这个现象确实很奇怪,但还是建议在使能ADC之后和触发采样之前加点延时看看,采样周期也配置到最大 
siliconnect 2021-6-9 09:23 回复TA
连续模式由于不停的采样,后面的新数据把前面的数据覆盖了 请问 这里覆盖的意思是什么,我这边是一个大数组,采用后放不同位置,应该没有覆盖存在。 是不是指的寄存器ADC里面数据 被覆盖了? 当我取的时候实际已经是几次ADC完成以后的最后一次覆盖值,不是第一次ADC转换完成的值,所以正常吗 
地板
siliconnect|  楼主 | 2021-6-9 09:16 | 只看该作者
sonicll 发表于 2021-6-8 09:59
开了连续模式就正常,说明只有前几次采样有问题,连续模式由于不停的采样,后面的新数据把前面的数据覆盖了 ...

好的,我试试看。谢谢

使用特权

评论回复
5
siliconnect|  楼主 | 2021-6-12 18:38 | 只看该作者
不行哦

使用特权

评论回复
6
小景报到| | 2021-6-22 01:42 | 只看该作者
是的,遇到同样的问题,采用如下的配置ADC才能正常读取数据,同样的疑问
/* ADC mode config */
    adc_mode_config(ADC_MODE_FREE);
    /* ADC contineous function enable */
    adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE,ENABLE );
    /* ADC scan mode disable */
    adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE);

使用特权

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

本版积分规则

27

主题

89

帖子

0

粉丝