关于STC8G测量通道X电压计算公式的求助
各位高手:我这里有两个地方不明白。见图片(改版后,图片无法上传了?)。
//16.6.4利用 ADC 第 15 通道测量外部电压或电池电压
//STC8G 系列 ADC 的第 15 通道用于测量内部参考信号源,由于内部参考信号源很稳定,约为 1.19V,
//且不会随芯片的工作电压的改变而变化,所以可以通过测量内部 1.19V 参考信号源,然后通过 ADC 的
//值便可反推出外部电压或外部电池电压。
//2023-2-15在主涵数中增加先利用通道15读取参考电压对应的数据值,再读取通道3的测量数据值,
//最后在主涵数中算出的测量通道的电压值。此程序在STC8G1K08A上面进行试验。
//STC8G 系列技术手册
//官方网站: www.STCAI.com
//技术支持: 13922829991
//选型顾问: 13922805190
//深圳国芯人工智能有限公司
//国内分销商电话: 0513-5501 2928/2929/2966
//去纯技术交流论坛:www.STCAIMCU.com - 584 -
//C 语言代码
//测试工作频率为 11.0592MHz
#include "C:\Keil_v5\C51\INC\reg51.h"
#include "C:\Keil_v5\C51\INC\intrins.h"
#define FOSC 11059200UL
#define BRT (65536 - FOSC / 115200 / 4)
sfr AUXR = 0x8e;
sfr ADC_CONTR = 0xbc;
sfr ADC_RES= 0xbd;
sfr ADC_RESL = 0xbe;
sfr ADCCFG= 0xde;
sfr P_SW2 = 0xba;
#define ADCTIM (*(unsigned char volatile xdata *)0xfea8)
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xc9;
sfr P5M0 = 0xca;
int *BGV;
//内部 1.19V 参考信号源值存放在 idata 中
//idata 的 EFH 地址存放高字节
//idata 的 F0H 地址存放低字节
//电压单位为毫伏(mV)
bit busy;
void UartIsr() interrupt 4
{
if (TI)
{
TI = 0;
busy = 0;
}
if (RI)
{
RI = 0;
}
}
void UartInit()
{
SCON = 0x50;
TMOD = 0x00;
TL1 = BRT;
TH1 = BRT >> 8;
TR1 = 1;
AUXR = 0x40;
busy = 0;
}
void UartSend(char dat)
{
while (busy);
busy = 1;
SBUF = dat;
}
void ADCInit() //ADC初始化
{
P_SW2 |= 0x80;
ADCTIM = 0x3f;//设置 ADC 内部时序
P_SW2 &= 0x7f;
ADCCFG = 0x2f;//设置 ADC 时钟为系统时钟/2/16
ADC_CONTR = 0x8f; //使能 ADC 模块,并选择第 15 通道
}
int ADCRead() //ADC读取通道0的电压
{
int res;
ADC_CONTR |= 0x40; //启动 AD 转换
_nop_();
_nop_();
while (!(ADC_CONTR & 0x20));//查询 ADC 完成标志
ADC_CONTR &= ~0x20; //清完成标志
res = (ADC_RES << 8) | ADC_RESL; //读取 ADC 结果
return res;
}
void Delay1000us()//@11.0592MHz
{
unsigned char k, j;
k = 15;
j = 90;
do
{
while (--j);
} while (--k);
}
void main()
{
int res3;
int resbg;
int TD3_TV;
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x08;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
BGV = (int idata *)0xef;
ADCInit(); //ADC 初始化
UartInit(); //串口初始化
Delay1000us(); //延时1毫秒让ADC稳定
ES = 1;
EA = 1;
resbg = ADCRead(); //先读出内部参考信号源的数据值
ADC_CONTR = 0x83; //使能 ADC 模块,并选择第 3 通道
res3 = ADCRead(); //再读出通道3的数据值
ADC_CONTR = 0x0f; //关闭 ADC 模块电源,并选择第 15 通道
TD3_TV = (int)( ((((*BGV * 100L) / resbg) * res3) / 100L) );
//上面公式中,*BGV直接除resbg会出现小数,造成最终结果TD3_TV不正确。
//*BGV先乘100,最后再除100,能够输出正确结果。
//但是,*BGV=1188*100=118800,已经超出65535了,但最终结果是正确的,不解?
// 问题在这里,有没有更好的办法解决小数和输出不正确的问题?
//1188是烧录芯片时提示信息中的参考电压值
//(10 位 ADC 算法)计算测量通道电压,即由读取值换算成电压值
// vcc = (int)(4096L * *BGV / res); //(12 位 ADC 算法)计算 VREF 管脚电压,即电池电压
//注意,此电压的单位为毫伏(mV)
UartSend(*BGV >> 8); //输出内部参考信号源电压值到串口
UartSend(*BGV);
UartSend(resbg >> 8); //输出内部参考信号源数据值到串口
UartSend(resbg);
UartSend(res3 >> 8); //输出通道3数据值到串口
UartSend(res3);
UartSend(TD3_TV >> 8); //输出通道3电压值到串口
UartSend(TD3_TV);
while (1);
}
//上面的方法是使用 ADC 的第 15 通道反推外部电池电压的。在 ADC 测量范围内,ADC 的外部测量
//电压与 ADC 的测量值是成正比例的,所以也可以使用 ADC 的第 15 通道反推外部通道输入电压,假设
//当前已获取了内部参考信号源电压为 BGV,内部参考信号源的 ADC 测量值为 resbg,外部通道输入电压
//的 ADC 测量值为 resx,则外部通道输入电压 Vx=BGV / resbg * resx;
我似乎找到了办法。
在 STC8H8K64U实验箱-V9.3 里面有一个例程 《33-P1.3做ADC-使用内部基准计算外部电压》,
里面有这么一段:
......
u8i;
u16 j;
......
for(i=0; i<8; i++)LED8 = 0x10; //上电消隐
while(1)
{
if(B_1ms) //1ms到
{
B_1ms = 0;
if(++msecond >= 300) //300ms到
{
msecond = 0;
#if (Cal_MODE == 0)
//=================== 只读1次ADC, 12bit ADC. 分辨率0.01V ===============================
Get_ADC12bitResult(15);//先读一次并丢弃结果, 让内部的采样电容的电压等于输入值.
Bandgap = Get_ADC12bitResult(15); //读内部基准ADC, 读15通道
Get_ADC12bitResult(3);//先读一次并丢弃结果, 让内部的采样电容的电压等于输入值.
j = Get_ADC12bitResult(3);//读外部电压ADC
j = (u16)((u32)j * 119 / Bandgap);//计算外部电压, Bandgap为1.19V, 测电压分辨率0.01V
......
是不是要把我的程序中变量定义那部分和公式部分,由int 型换成 u16 和 u32。再先乘后除,问题就解决了。
等待高手给个确认。
我也在等待 直接用float型的数据来存,这样就不存在65535问题了。算好后乘以100,再把float类型的毫伏数值付给一个int变量haofu。这样输出的时候用sendbuf=((haofu/10000)%10+0x30);sendbuf=((haofu/1000)%10+0x30);sendbuf=((haofu/100)%10+0x30);sendbuf=((haofu/10)%10+0x30);sendbuf=haofu%10+0x30;这样输出到串口。调试用文本方式看,就得到了毫伏值。 <p>我喜欢用内部有参考源的<img alt="ciya" class="emoji" src="https://www.stcaimcu.com/static/image/smiley/default/ciya.gif" title="ciya" />,不用折腾</p>
页:
[1]