硬件:使用STM8S005的AIN0采样TL431的电压,AIN2到AIN5采样外部的电压。 每次计算电压时先采样AIN0的电压,再采样AIN X通道的电压,通过431和AINX外部的分压电阻换算出电压。AIN2到AIN5都是正常的,但是AIN1会有小概率的偏低问题,正常计算得到电压为3.3V,但是偏低的时候会出来2.4V,使用示波器查看AIN1脚电压正常。使用STLINK看AIN1的数字采样值的确是偏低,所以计算得到2.4V左右。电路图:
javascript:;
javascript:;
代码部分:
IO设置:
//PF4:模拟输入AIN12。ADC_4V,分压电阻13/3;
PF_DDR_DDR4=0;
PF_CR1_C14=0; //
PF_CR2_C24=0;
//PB5:模拟输入AIN5。ADC_5VISO,分压电阻13/3;
PB_ODR_ODR5=1;
PB_DDR_DDR5=0;
PB_CR1_C15=0; //
PB_CR2_C25=0;
//PB4:模拟输入AIN4。ADC_VDDISO,分压电阻13/3;
PB_ODR_ODR4=1;
PB_DDR_DDR4=0;
PB_CR1_C14=0; //
PB_CR2_C24=0; //
//PB3:模拟输入AIN3。ADC_VDCIN,分压电阻13/3;
PB_ODR_ODR3=1;
PB_DDR_DDR3=0;
PB_CR1_C13=0; //
PB_CR2_C23=0; //
//PB2:模拟输入AIN2。ADC_I, 1V对应0.1A;
PB_ODR_ODR2=1;
PB_DDR_DDR2=0;
PB_CR1_C12=0; //
PB_CR2_C22=0; //
//PB1:模拟输入AIN1。ADC_VDD33,分压电阻13/3;
PB_ODR_ODR1=1;
PB_DDR_DDR1=0;
PB_CR1_C11=0; //
PB_CR2_C21=0; //
//PB0:模拟输入AIN0。TL431电压 2.495V
PB_ODR_ODR0=1;
PB_DDR_DDR0=0;
PB_CR1_C10=0; //
PB_CR2_C20=0; //
//ADC采用函数
void AdcPLoad(u8 *vdat,u8 chx)
{
u32 value;
u16 dat,dat2,dat3;
ADC_CR1_ADON = 1; //打开adc
ADC_CR2_ALIGN = 1; //右对齐数据,先读低位,再读高位
ADC_CR1_SPSEL = 2; //4分频时钟 原来=0的时钟太快了,可能导致AIN1有时电压偏低,经过验证。也不是这个问题!!
ADC_CSR_CH =0; //开AIN0脚,先读431电压
delay100us();
ADC_CR1_ADON = 1; //使能adc。单次ADC模式必须每次使能ADC
while(ADC_CSR_EOC==0); //至少读第二次才能获得正确的ADC值
ADC_CSR_EOC = 0;
ADC_CR1_ADON = 1; //使能adc。单次ADC模式必须每次使能ADC
while(ADC_CSR_EOC==0);
((u8*)&dat)[1] = ADC_DRL; //右对齐数据,先读低位
((u8*)&dat)[0] = ADC_DRH; //再读高位
ADC_CSR_EOC = 0;
ADC_CSR_CH = chx; //再chx脚,读目标
delay100us();
ADC_CR1_ADON = 1; //使能adc
while(ADC_CSR_EOC==0);
ADC_CSR_EOC = 0;
ADC_CR1_ADON = 1; //使能adc。单次ADC模式必须每次使能ADC
delay100us();
while(ADC_CSR_EOC==0);
((u8*)&dat2)[1] = ADC_DRL; //右对齐数据,先读低位
((u8*)&dat2)[0] = ADC_DRH; //再读高位
ADC_CSR_EOC = 0;
ADC_CR1_ADON = 1; //打开adc
ADC_CR2_ALIGN = 1; //右对齐数据,先读低位,再读高位
ADC_CR1_SPSEL = 2; //使能adc。单次ADC模式必须每次使能ADC
ADC_CSR_CH = chx;
while(ADC_CSR_EOC==0);
((u8*)&dat2)[1] = ADC_DRL; //右对齐数据,先读低位
((u8*)&dat2)[0] = ADC_DRH; //再读高位
ADC_CSR_EOC = 0;
ADC_CR1_ADON = 0; //关adc 关ADC要最后关!!
value=dat2; //换算为电压
value=value*2530/dat;
value=value*13/3;
dat3=value;
vdat[0]=((u8*)&dat3)[0]; //保存
vdat[1]=((u8*)&dat3)[1];
}
另外分享一个使用运放+三极管做高端电流采样的电路,同时使用单片机的IO输出方波来给运放电压做自举升压,因为运放的VCC电压要高于输入电压运放才能正常工作,使用LM358。缺点是单片机在使用仿真器打断点停的时候,因为IO没方波输出,所以运放电压偏低,这个时候看运放输出的电压来判断电流是不对的。要在采样完成后打断电停止。或者直接uart输出更好。
javascript:;
一周热门 更多>