求助:STM8S005的AIN1电压采样值出现小概率偏低

2019-12-27 19:02发布

硬件:使用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:;
0条回答

一周热门 更多>