找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2990|回复: 10
收起左侧

STC15W单片机测量电压数值跟实际电压不符

[复制链接]
ID:956872 发表于 2021-10-12 20:31 | 显示全部楼层 |阅读模式
内部参考电压是1243mV,3位数码管显示1.24。这个程序也是范例程序加了数码管显示。P1.1脚我用充电宝通过可调电阻输入。显示的电压与实际输入电压不符
实际电压是0V到5.02V,数码管显示只有0.00调到0.29又从0.00开始循环



WORD idata Vbg_RAM _at_ 0xef;   

WORD code Vbg_ROM _at_ 0x1ff7;            //8K程序空间的MCU



sfr ADC_LOW2    =   0xBE;                   //ADC低2位结果

#define ADC_POWER   0x80                    //ADC电源控制位
#define ADC_FLAG    0x10                    //ADC完成标志
#define ADC_START   0x08                    //ADC起始控制位
#define ADC_SPEEDLL 0x00                    //540个时钟
#define ADC_SPEEDL  0x20                    //360个时钟
#define ADC_SPEEDH  0x40                    //180个时钟
#define ADC_SPEEDHH 0x60                    //90个时钟
void Timer0Init(void);
/*----------------------------
软件延时
----------------------------*/
void Delay(WORD n)
{
    WORD x;

    while (n--)
    {
        x = 5000;
        while (x--);
    }
}

BYTE GetADC(BYTE ch)
{
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL;
    Delay(2);                               //ADC上电并延时
    ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ch | ADC_START;
    _nop_();                                //等待4个NOP
    _nop_();
    _nop_();
    _nop_();
    while (!(ADC_CONTR & ADC_FLAG));        //等待ADC转换完成
    ADC_CONTR &= ~ADC_FLAG;                 //清除ADC标志

    return ADC_RES;
}

void main()
{
    BYTE ADCbg;
    BYTE ADCx;
    WORD Vx;
    Timer0Init();

while (1)
{//第一步:通过ADC的第2通道测试外部输入电压的ADC测量值
    ADC_RES = 0;                            //清除结果寄存器
    P1ASF = 0x02;                           //设置P1.1口为模拟通道
    GetADC(1);
    GetADC(1);
    ADCx = GetADC(1);

//第二步:通过ADC的第9通道测试Bandgap电压的ADC测量值
    ADC_RES = 0;                            //清除结果寄存器
    P1ASF = 0x00;                           //不设置P1ASF,即可从ADC的第9通道读取内部Bandgap电压的ADC测量值
    GetADC(1);
    GetADC(1);
    ADCbg = GetADC(1);

//第三步:通过公式计算外部输入的实际电压值
    Vx = Vbg_RAM * ADCx / ADCbg;            //使用RAM中的Bandgap电压参数进行计算
   // Vx = Vbg_ROM * ADCx / ADCbg;          //使用ROM中的Bandgap电压参数进行计算
    ledbuf[0]=(Vx/1000%10)+10;
    ledbuf[1]=Vx/100%10;
    ledbuf[2]=Vx/10%10;
               
}
}

void Timer0Init(void)                //1毫秒@11.0592MHz
{
        AUXR &= 0x7F;                //定时器时钟12T模式
        TMOD &= 0xF0;                //设置定时器模式
        TL0 = 0x66;                //设置定时初始值
        TH0 = 0xFC;                //设置定时初始值
        TF0 = 0;                //清除TF0标志
        ET0=1;
        EA=1;
        TR0 = 1;                //定时器0开始计时
}


void Timer0_Init() interrupt 1
{      TR0 =0;
        display();                   //数码管显示
        TL0 = 0x66;                //设置定时初始值
        TH0 = 0xFC;                //设置定时初始值
        TR0 = 1;
}

回复

使用道具 举报

ID:401564 发表于 2021-10-12 22:08 | 显示全部楼层
STC15W系列不能直接通过内部参考电压来测量VCC电压,直接测量不一定准确,数据手册898页面有重要说明

但这误差不会很大,像你这种有几V的误差,应该是你自己代码的问题

回复

使用道具 举报

ID:624769 发表于 2021-10-12 22:19 | 显示全部楼层
void main()
{
    BYTE ADCbg;
    BYTE ADCx;
    WORD Vx;                    <==== 这个用unsinged Long
    Timer0Init();

然后,第三步用 ROM去算而且分部算
Vx = Vbg_ROM;
Vx *= ADCx;
Vx /= ADCbg;

这样算,
然后看看结果。
回复

使用道具 举报

ID:959346 发表于 2021-10-12 22:27 | 显示全部楼层
检查一下数据长度是否满足?包括定义的数据类型长度、计算步骤内的数据长度等。
回复

使用道具 举报

ID:213173 发表于 2021-10-13 06:16 | 显示全部楼层
//第一步:通过ADC的第2通道测试外部输入电压的ADC测量值
    ADC_RES = 0; //清除结果寄存器
    P1ASF = 0x02;//设置P1.1口为模拟通道
    ADCx = GetADC(1);

//第二步:通过ADC的第9通道测试Bandgap电压的ADC测量值
    ADC_RES = 0; //清除结果寄存器
    P1ASF = 0x00; //不设置P1ASF,即可从ADC的第9通道读取内部Bandgap电压的ADC测量值
    ADCbg = GetADC(0);//第9通道!!!

//第三步:通过公式计算实际电源电压值Vx
//  Vx = Vbg_RAM * ADCx / ADCbg;            //使用RAM中的Bandgap电压参数进行计算
    Vx = 5.0 * Vbg_RAM / ADCbg;   

//第四步:通过公式计算外部输入的实际电压值
    Vin = Vx * ADCx / 256;
回复

使用道具 举报

ID:956872 发表于 2021-10-13 18:01 | 显示全部楼层
wulin 发表于 2021-10-13 06:16
//第一步:通过ADC的第2通道测试外部输入电压的ADC测量值
    ADC_RES = 0; //清除结果寄存器
    P1ASF = ...

5.0换成500,VX的值跟单片机电压相符。那个Vin通道1输入的实际电压还是不对
回复

使用道具 举报

ID:213173 发表于 2021-10-13 19:06 | 显示全部楼层
PEB188 发表于 2021-10-13 18:01
5.0换成500,VX的值跟单片机电压相符。那个Vin通道1输入的实际电压还是不对

不知你是否改正 ADCbg = GetADC(0);//第9通道!!!
回复

使用道具 举报

ID:956872 发表于 2021-10-14 15:59 | 显示全部楼层
wulin 发表于 2021-10-13 19:06
不知你是否改正 ADCbg = GetADC(0);//第9通道!!!

这个改正过来了。所以第三步测得电压没问题。第四步外部输入的电压值不正确。
//第一步:通过ADC的第2通道测试外部输入电压的ADC测量值
    ADC_RES = 0; //清除结果寄存器
    P1ASF = 0x02;//设置P1.1口为模拟通道
    ADCx+= GetADC(1);
//第二步:通过ADC的第9通道测试Bandgap电压的ADC测量值
    ADC_RES = 0; //清除结果寄存器
    P1ASF = 0x00; //不设置P1ASF,即可从ADC的第9通道读取内部Bandgap电压的ADC测量值
    ADCbg += GetADC(0);//第9通道!!!
    i++;
        if(i>=15)
        {
                i=0;               
                Vx = (500 * Vbg_RAM / ((long)ADCbg/15));     
                Vin= ((long)(ADCx/15)*Vx/256);
                ADCx=0;
                ADCbg=0;
                ledbuf[0]=Vin/100%10+10;
    ledbuf[1]=Vin/10%10;
    ledbuf[2]=Vin/1%10;
回复

使用道具 举报

ID:956872 发表于 2021-10-14 16:14 | 显示全部楼层
wulin 发表于 2021-10-13 19:06
不知你是否改正 ADCbg = GetADC(0);//第9通道!!!

1通道输入的电压有误差最大0.6V多,而且不能超过电源电压.电源电压3.9V的时候,那输入检测的电压就无法超过这个值.这属于正常的吗.误差应该怎么调校.
回复

使用道具 举报

ID:213173 发表于 2021-10-14 20:19 | 显示全部楼层
PEB188 发表于 2021-10-14 16:14
1通道输入的电压有误差最大0.6V多,而且不能超过电源电压.电源电压3.9V的时候,那输入检测的电压就无法超过 ...

输入电压=当前VCC电压*转换结果/256
使用第九通道的目的是为了利用芯片内部基准电压推算出当前VCC电压。
当输入电压大于VCC需要用分压电阻按比例降低到VCC以内,经转换后再按同比例放大显示。
回复

使用道具 举报

ID:213173 发表于 2021-10-16 16:45 | 显示全部楼层
PEB188 发表于 2021-10-14 16:14
1通道输入的电压有误差最大0.6V多,而且不能超过电源电压.电源电压3.9V的时候,那输入检测的电压就无法超过 ...

正常误差0.02V。
        i++;
        if(i>=15)
        {
                i=0;               
                Vx=500*Vbg_RAM/(ADCbg/15);     
                Vin=Vx*(long)ADCx/256/15;
                ADCx=0;
                ADCbg=0;
                ledbuf[0]=Vin/100%10;
                ledbuf[1]=Vin/10%10;
                ledbuf[2]=Vin%10;
        }
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表