说明一下,项目需要检测电池电压,在低电量时给用户提示。
下面是第一列是供电电压,即电池电压,第二列是分压后电压,第三列是ide读到的adc转化后的数值。mcu工作电压2.5V 电池电压 分压后电压 IDE中读取到的数值DEC 4.4 1.719 2316 4 1.572 2189 3.8 1.456 2108 3.7 1.385 2081 3.6 1.361 2066 3.4 1.267 2092
当电压从4.4降低到3.6过程中,最后一列数据是正常的,保持一个降低的趋势,但从3.6继续降低3.4时,ide读到的数据上升。这样就无法区分到底是3.7V还是3.4V。 开始认为是参考电压变化太快所致。使用的是48Pin的封装,没有Ref+ - IO。其参考电压是MCU的供电电压。但此电压是经过LDO之后的电压,从测量的结果看从4.4-3.4的过程,MCU供电电压保持在2.5V。
从去年的一个项目就发现这个问题,没有解决掉,因为是干电池,可以回避掉。但现在又是这个问题,使用锂电池,因为可充电,电压上升也是正常状态 ,无法回避。
请教,到底什么原因。大概的程序流程如下:
void Init_ADC_Voltage(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure;
/* Configure PC.04 (ADC Channel14) as analog input -------------------------*/ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* ADC1 configuration ------------------------------------------------------*/ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE;//single channle ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//single ,not continuous ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//control by soft ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel0 configuration */ ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_13Cycles5); ADC_ClearFlag(ADC1,ADC_FLAG_EOC); ADC_Cmd(ADC1, ENABLE); START_ADC_MCU(); }
void START_ADC_MCU(void) { /* Enable ADC1 reset calibaration register */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibaration */ ADC_StartCalibration(ADC1); /* Check the end of ADC1 calibration */ while(ADC_GetCalibrationStatus(ADC1));
/* Start ADC1 Software Conversion */ ADC_SoftwareStartConvCmd(ADC1, ENABLE); // ADC_Cmd(ADC1, ENABLE); }
u16 Get_Once_Voltage(void) { u16 voltage=0; while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == RESET); voltage = ADC_GetConversionValue(ADC1); //start the next adc conversion ADC_SoftwareStartConvCmd(ADC1, ENABLE);
return voltage;
}
u16 Get_32times_Voltage(void) { u32 voltage=0; u16 voltage_aver=0; u8 i=0;
for(i=0;i<32;i++) voltage += (u32)Get_Once_Voltage(); voltage_aver = (u16)(voltage>>5);
return voltage_aver; }
int main(void) { Init_ADC_Voltage(); Battery_Voltage = Get_32times_Voltage(); while(1); } |