ADC结果是12位的,并且ADC结果也是对的,就是电压不对,很奇怪的。
“地板”楼的代码里,本该用12位的4096反推的算式被注释掉了,用的10位的1024反推的,所以结果正好变成了四分之一
3.288变成了0.822
vcc = (int)(1024L * *BGV / res); //(10位ADC算法)计算VREF管脚电压,即电池电压
//vcc = (int)(4096L * *BGV / res); //(12位ADC算法)计算VREF管脚电压,即电池电压
我手边有8h4k64tl 刚跑了你的程序依然是
接收←ADC15=1482,AVREF=0.822V
接收←ADC15=1481,AVREF=0.823V
但跑例程他们的结果不一样。
8h4k64tlhex模式输出0337
8h8k64u hex模式输出0000
例程是这个
#include "reg51.h"
#include "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()
{
P_SW2 |= 0x80;
ADCTIM = 0x3f; //设置ADC内部时序
P_SW2 &= 0x7f;
ADCCFG = 0x2f; //设置ADC时钟为系统时钟/2/16
ADC_CONTR = 0x8f; //使能ADC模块,并选择第15通道
}
int ADCRead()
{
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 main()
{
int res;
int vcc;
int i;
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
BGV = (int idata *)0xef;
ADCInit(); //ADC初始化
UartInit(); //串口初始化
ES = 1;
EA = 1;
//ADCRead();
//ADCRead(); //前两个数据建议丢弃
while (1){
res = 0;
for (i=0; i<8; i++)
{
res += ADCRead(); //读取8次数据
}
res >>= 3; //取平均值
vcc = (int)(1024L * *BGV / res); //(10位ADC算法)计算VREF管脚电压,即电池电压
//vcc = (int)(4096L * *BGV / res); //(12位ADC算法)计算VREF管脚电压,即电池电压
//注意,此电压的单位为毫伏(mV)
UartSend(vcc >> 8); //输出电压值到串口
UartSend(vcc);
};
}
这个我刚刚弄好的. 读出外部电压.
// u16ADC_Read( u8 no )
// {
// static u16 new_value;
// adc_val = new_value;
//// u16 adcval; //adc数值保存变量
// ADC_CONTR &= 0xf0; //清空通道
// ADC_CONTR = (ADC_CONTR & 0xF0) | 0x40 | no;
//// ADC_CONTR |= no; //选择通道
// ADC_CONTR |=0x40; //ADC_START = 1; //开启ADC转化
// _nop_(); //空操作指令
// _nop_();
// while((ADC_CONTR & 0x20) == 0); //等待ADC结束
// ADC_CONTR &= ~ 0x20; //ADC_FLAG = 0;
// adc_val = (ADC_RES << 8)+ ADC_RESL; //计算adc的数值
//
// if((new_value - adc_val > 500)||(adc_val - new_value > 500)) return adc_val;//跳变大于0.3V放弃本次采样值
// else return new_value;
// }
adc_dianya = (int)(4096L * 1194 / res);
页:
1
[2]