求助大神,32G12K128 ADC读电压有误差 | 很准了
#define VREFH_ADDR CHIPID7#define VREFL_ADDR CHIPID8
int xdata VCCres;
int xdata vcc;
unsigned char xdata volt_tens = 0; // 电压千位数
unsigned char xdata volt_units = 0; // 电压百位数
unsigned char xdata volt_units2 = 0; // 电压十位数
unsigned char xdata volt_units3 = 0; // 电压个位数
void ADCInit()
{
ADCTIM = 0x3f; //设置ADC内部时序
ADCCFG = 0x2f; //设置ADC时钟为系统时钟/2/16
}
int ADCRead()
{
int VCCres;
ADC_START = 1; //启动AD转换
_nop_();
_nop_();
while (!ADC_FLAG); //查询ADC完成标志
ADC_FLAG = 0; //清完成标志
VCCres = (ADC_RES << 8) | ADC_RESL; //读取ADC结果
return VCCres;
}
// ————————————————读电源VCC res和电压————————————————
BGV=(VREFH_ADDR<<8)+VREFL_ADDR;
ADC_CONTR = 0x00;
ADC_CONTR = 0x8f; //选择通道15(内部基准)
_nop_();
_nop_();
ADCRead();
ADCRead();
VCCres = 0;
for (i=0; i<8; i++)
{
VCCres += ADCRead(); //读取8次数据
}
VCCres >>= 3; //取平均值
vcc = (int)(4096L * BGV / VCCres);
volt_tens = vcc / 1000; // 获取千位数 (2756/1000=2)
volt_units = (vcc % 1000) / 100; // 获取百位数 (2756%1000=700, 700/100=7)
volt_units2 = (vcc % 100) / 10; // 获取十位数 (2756%100=50, 50/10=5)
volt_units3 = (vcc % 10) / 1; // 获取个位数 (2756%10=6, 6/1=6)
得出来的数据用来FOR循环闪灯用,最后靠闪灯读数,发现有误差
4.2v 读出来4395
4.3v 读出来4500
3.4v 读3555
3.2 读3348
3.9 读4072
5.1 读5341
之前用的STC8G1K08 TSSOP20,读出来很准,换成STC32G12K128就不准了,硬件没改动
而且发现用其他引脚读GND电压,应该是0V,读出来0.168V,大佬们有空帮看看代码有没有问题,太感谢了!!
32G12K128有独立VREF,注意VREF的连接
DebugLab 发表于 2025-7-22 14:00
32G12K128有独立VREF,注意VREF的连接
VREF直接接到VCC上面了,这样会影响精度么
linlinmiao 发表于 2025-7-22 14:26
VREF直接接到VCC上面了,这样会影响精度么
高精度应用还是建议外接基准的(但这样无法直接得到VCC电压,还需要另外占用一个ADC通道,外加至少两个电阻)
VREF接VCC,计算VCC和外部输入的电压程序,供参考:
AVREF连接了吗? 没有这么大的误差把,
1%倒是可能有 感觉可能是通过BGV计算电压实际值的时候出了点问题,看起来像是因为没有强制转换成更高精度数据类型,造成计算的时候出现了一些误差。
可以先尝试一下直接输出adcread读出来的数值,看看接地的时候是否为0,这个一般是不会出问题的
用户请先别修改程序, 直接下载"01-读取15通道ADC计算AVREF电压-串口1(P3.1)返回结果->Objects"里的"ADC.hex"测试.
下载时选择主频11.0592MHZ. 测试时, 电脑的串口助手设置115200,8,n,1.
本程序演示查询方式读取15通道ADC并计算AVREF的电压值,通过串口1(P3.1)发送给上位机,波特率115200,8,n,1.
很准确的:
梁工 发表于 2025-7-23 09:51
用户请先别修改程序, 直接下载"01-读取15通道ADC计算AVREF电压-串口1(P3.1)返回结果->Objects"里的"ADC.h ...
哇,用这个程序读出来的电压又变得很准了,奇怪了,得仔细检查代码才行
页:
[1]
2