赞
踩
当我们利用stm32制作电压表时,需要利用stm32单片机内置12位的ADC进行AD采集然后转换成电压值来显示,但是此时我们遇到了一个问题——stm32单片机进行AD采集到的数据总是在个位十位数跳变,转换成电压值时也会显示一直变化,那我们该如何解决这个问题呢?
首先来看我对ADC进行的配置。
- void ADC1_Init(void)
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
-
- RCC_ADCCLKConfig(RCC_PCLK2_Div6);//六分频
-
- GPIO_InitTypeDef GPIO_InitStruct;
- GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
- GPIO_InitStruct.GPIO_Pin=GPIO_Pin_7|GPIO_Pin_6;
- GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_Init(GPIOA,&GPIO_InitStruct);
-
-
- ADC_InitTypeDef ADC_InitStructure;
- ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;//单次转换
- ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
- ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
- ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;
- ADC_InitStructure.ADC_NbrOfChannel=1;
- ADC_InitStructure.ADC_ScanConvMode=DISABLE;//非扫描模式
- ADC_Init(ADC1,&ADC_InitStructure);
-
- ADC_Cmd(ADC1,ENABLE);
-
- ADC_ResetCalibration(ADC1);
- while(ADC_GetResetCalibrationStatus(ADC1)==SET);
- ADC_StartCalibration(ADC1);
- while(ADC_GetCalibrationStatus(ADC1)==SET);
- }
-
- u16 Get_ADValue(u8 ADC_Channel)//用哪个通道采集就填哪个ADC通道
- {
- ADC_RegularChannelConfig(ADC1,ADC_Channel,1,ADC_SampleTime_239Cycles5);//规则组通道配置
- ADC_SoftwareStartConvCmd(ADC1,ENABLE);//开启软件转换
- while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);//等待AD转换
- return ADC_GetConversionValue(ADC1);
- }

这里我们想到的是利用取平均值消出AD采集值的抖动,每采集一百次时用一百次采集到的AD值的总和减去100次采集中的最大值和最小值再除以98来实现,代码如下。
- u32 AD_Counter=0;
- u16 AD_MAX=0;
- u16 AD_MIN=4095;//为什么AD_MIN最大,AD_MAX最小呢?后文会为你解释明白
- u32 AD_SUM=0;
- u8 AD_Value;
- float Voltage;
- char ADC_Strings[];
-
- void Get_Voltage(u8 ADC_Channel)
- {
- AD_Value=Get_ADValue(ADC_Channel);
- if(AD_Value>AD_MAX) AD_MAX=AD_Value;
- if(AD_Value<AD_MIN) AD_MIN=AD_Value;
- AD_Counter++;
- AD_SUM=AD_SUM+AD_Value;//储存AD采集的数值
- if(AD_Counter==100) //AD采集次数=100时
- {
- AD_Value=(AD_SUM-AD_MAX-AD_MIN)/(AD_Counter-2);//求平均值
- AD_Counter=0;
- AD_MAX=0;
- AD_MIN=4095;
- AD_SUM=0;
- Voltage=(float)AD_Value/4096*3.3;//将采集到的AD转换成电压
- sprintf(ADC_Strings,"%1.2f",Voltage);
- lcd_w_const_str(1,5,ADC_Strings);
- }
- }

我们将此函数放到主函数的循环中,在对应开通的ADC通道的引脚接入外部电路测量即可(记得要共地)。
电压测量
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。