|
如题,采用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;
- }
复制代码
|
|