longor 发表于 2022-1-19 09:58:03

FM33L025 ADC REF1.2V测试不准

如题,采用FM33L025芯片,采用PC9--ADC0测量外部电压,但是测量内部1.2V电压时发现ad值不稳定,当PC9电压超过1.85V时,1.2V的电压测量值就偏差很大,偏差能达到上下一两百左右,当PC9电压低于1.85V时,1.2V的电压测量值稳定在1485,偏差就几个数。采用的FL固件库的程序移植的,希望大神解惑。系统时钟为RCHF 16MHz,测量外部电压又是比较稳定的。
//adc初始化

void adcInit(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    //AD检测口
    GPIO_InitStruct.Pin = ADC_DET_PIN;
    GPIO_InitStruct.PxFCR = GPIO_FCR_ANA;
    GPIO_InitStruct.PxPUEN = GPIO_PU_Dis;
    GPIO_InitStruct.PxINEN = GPIO_IN_Dis;
    GPIO_InitStruct.PxODEN = GPIO_OD_En;
    GPIO_Init( ADC_DET_PORT, &GPIO_InitStruct );

    // 模块时钟
    RCC_OPC_CR2_ADCCKE_Setable(ENABLE);               // ADC时钟使能
    RCC_OPC_CR2_ADCPRSC_Set(RCC_OPC_CR2_ADCPRSC_DIV16); // ADC工作时钟
    RCC_OPC_CR2_ADCCKS_Set(RCC_OPC_CR2_ADCCKS_RCHF);   // ADC时钟 RCHF

    // 电源控制
    if(DISABLE == PMU_VREF_CR_EN_Getable())   //判断ref122是否使能,如果禁止需清IF,保证下次使能查到的IF正确
      PMU_VREF_SR_IF_Clr();
    PMU_VREF_CR_EN_Setable(ENABLE);   // EN VREF1.22
    while(!PMU_VREF_SR_IF_Chk());
    // 复位ADC模块
    RCC_PRST_EN_Write(RSTKEY0);
    RCC_APBRST_CR2_ADCRST_Setable(ENABLE);// 数字部分复位
    RCC_APBRST_CR2_ADCRST_Setable(DISABLE);
    RCC_APBRST_CR2_ADCCRST_Setable(ENABLE); // 模拟部分复位
    RCC_APBRST_CR2_ADCCRST_Setable(DISABLE);
    RCC_PRST_EN_Write(RSTKEY1);

    //上电校准
    ADC_CR_ADEN_Setable(ENABLE);    // 使能ADC
    ADC_CAL_CALEN_Setable(ENABLE);// Calibration使能,软件写1启动校准周期,硬件开始校准后自动清零。软件通过EOCAL寄存器查询校准周期结束。
    while(0 == ADC_ISR_EOCAL_Chk());
    ADC_ISR_EOCAL_Clr();            // 清校准结束
    ADC_CR_ADEN_Setable(DISABLE);   // 关闭ADC

    // ADC配置
    ADC_CAL_CONV_CAL_Set(ADC_CAL_CONV_CAL_USE_CAL); //ADC转换使用校准寄存器里的数据

    ADC_SMTR_SMTS1_Set(ADC_SMTR_SMTS1_10_5_TMCLK);//设置快速采样时间

    ADC_SMTR_SMTS2_Set(ADC_SMTR_SMTS2_10_5_TMCLK);//设置快速采样时间

    // ADC配置寄存器
    ADC_CFGR_CKS_Set(ADC_CFGR_CKS_ADCCLK);// ADCCLK
    ADC_CFGR_CONT_Setable(DISABLE);          // ENABLE:连续转换, DISABLE: 单次转换
    ADC_CFGR_SEMI_Set(ADC_CFGR_SEMI_AUTO);   //半自动,仅单次转换有效
    ADC_CFGR_OVRM_Set(ADC_CFGR_OVRM_COVER); // 当overrun发生时,覆盖上次数据

    ADC_CFGR_OVSS_Set(ADC_CFGR_OVSS_R_SHIFT_4);
    ADC_CFGR_OVSR_Set(ADC_CFGR_OVSR_16x);
    ADC_CFGR_OVSEN_Setable(ENABLE);
    ADC_CFGR_WAIT_Setable(ENABLE);
    //AD检测口设置为ADC输入通道
    GPIOx_ANEN_Setable(ADC_DET_PORT, ADC_DET_PIN, ENABLE);
}

//测试发现引脚电压超过1.85V,测到的1.22V的电压值就变化比较大,正常在1485
uint16_t GetVref1p22Sample(void)
{
    uint8_t i = 0;
    uint32_t adc_val = 0;
    uint32_t result = 0;
    //此处分频不能太小,否则最终测量电压会偏高
    //实测,16MHz RCHF,分频8,会偏高,改到16分频,则数据正常
    RCC_OPC_CR2_ADCPRSC_Set(RCC_OPC_CR2_ADCPRSC_DIV16);// ADC时钟16分频,VREF的驱动能力较弱,采样时间不能小于10.5*(1/2M)

    PMU_BUF_CR_VREFBUFFER_EN_Setable(ENABLE);   // 电压通道使能
    RCC_OPC_CR2_ADCCKE_Setable(ENABLE);         // ADC时钟使能
    ADC_CHER_REFCH_Setable(ENABLE);                    // VREF测量通道使能
    PMU_VREF_CR_EN_Setable(ENABLE);   // EN VREF1.22
   
    ADC_ISR_EOC_Clr();
    ADC_CR_ADEN_Setable(ENABLE);   // 启动ADC
    delay_ms(5);                        // 软件延时至少5个ADC工作时钟   
    for (i = 0; i < 4; i++)
    {
      ADC_CR_START_Setable(ENABLE);// 开始转换
      while (ADC_ISR_EOC_Chk() == RESET);
      ADC_ISR_EOC_Clr();
      adc_val = ADC_DR_Read();
      result += adc_val;
    }
    result = result/4;

    ADC_CR_ADEN_Setable(DISABLE);               // 关闭ADC
    while(ADC_ISR_BUSY_Chk());
    RCC_OPC_CR2_ADCCKE_Setable(DISABLE);      // ADC时钟关闭

//    PMU_BUF_CR_VREFBUFFER_EN_Setable(DISABLE);// VREF BUFFER输出关闭
    ADC_CHER_REFCH_Setable(DISABLE);                // VREF测量通道关闭

    // 返回转换结果
    return (uint16_t)result;
}


我是一只鱼21 发表于 2022-1-20 10:38:29

没太看懂,意思是说REF1.2在测量PC9高于1.85V的时候,采样值偏差很大,但是算出的外部电压又是稳定的??那这时候的VDD电压稳定吗

longor 发表于 2022-1-21 15:23:01

我是一只鱼21 发表于 2022-1-20 10:38
没太看懂,意思是说REF1.2在测量PC9高于1.85V的时候,采样值偏差很大,但是算出的外部电压又是稳定的??那 ...

vdd电压稳定的,找到问题了。芯片用的设配器供电,pc9的电压是另一个可调电源,可调电源地接到板子上,电源正接到pc9引脚。是2个不同电源导致的
页: [1]
查看完整版本: FM33L025 ADC REF1.2V测试不准