用32F103CB AD测量6路电池电压,范围1-28V电压只通过电阻分压直接输入AD管脚,采用6路循环DMA自动采集方式,通过数字滤波基本可以到2mV内的跳动,现在碰到一个奇怪的现象:进行多次上电,偶尔数据会有一个恒定的测量偏移,大概8mV左右,这个恒定偏移只要不重新上电会一直在,显示的测量数据也稳定。比如:大多数的时候测量为3.123V, 偶尔一次上电为3.130V,可以肯定的是测试环境相同:我用万用表量过两种状态下VCC和电阻分压处电压是一致的。为了找原因我直接查看AD值,也同样有这个问题,可以排除中间数据处理问题。经过多次判断,问题锁定在AD开启前的AD自效准上(见红色代码),理由1是在程序中加入人为触发的AD自效准,不重新上电也会产生上面问题。理由2注释掉红色代码运行,反复上电不会有上面问题。
什么原因会导致AD自效准会有如此偏差,或自效准时外围电路要注意什么?我在网上搜不到有类似问题的内容,特来求大家给我指点迷津!救救我呀
void AD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
/* Enable DMA clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable ADC1 and GPIOA clocks */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
/* Configure (ADC Channel) as analog input -------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_A_D | GPIO_Pin_A_V | GPIO_Pin_A_BAT1 | GPIO_Pin_A_BAT2 | \
GPIO_Pin_A_BAT3 | GPIO_Pin_A_BAT4 | GPIO_Pin_A_BAT5 | GPIO_Pin_A_BAT6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* DMA1 channel1 configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = RE_SAMPLE_COUNT*CH_MAX;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
//DMA_ITConfig(DMA1_Channel1,DMA1_IT_TC1,ENABLE); //开传输完中断
/* Enable DMA1 channel1 */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* ADC1 configuration ------------------------------------------------------*/
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC_Mode_RegSimult;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = CH_MAX;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel2 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, CH_CURRENT+1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, CH_VOLT+1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, CH_BAT1+1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, CH_BAT2+1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, CH_BAT3+1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, CH_BAT4+1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_7, CH_BAT5+1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_8, CH_BAT6+1, ADC_SampleTime_55Cycles5);
// ADC1 regular channel16 Temp Sensor configuration
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, CH_TEMP+1, ADC_SampleTime_55Cycles5);
#ifdef INT_REFV
// ADC1 regular channel17
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, CH_IREFV+1, ADC_SampleTime_55Cycles5);
#endif
// Enable the temperature sensor and vref internal channel
ADC_TempSensorVrefintCmd(ENABLE);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* 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);
} |
|