我现在用ADC0832采集数据,0832的基准电压测出来实际是4.95V,刚开始是采集后的数据显示到数码管上,但是有误差,于是就改为将电压值发送到串口进行显示,现在串口显示数据为4.51V的时候,输入电压测出来实际值为4.77V,有0.2v的误差,有没有大神知道这误差怎么来的,以及如何解决呢。感谢。
这是我的程序,写的有点乱,因为修改了好多次,见谅。
#include<reg52.h>
#include<intrins.h>
/***********ad0832与单片机的接口定义**********************/
sbit CS =P3^2;
sbit CLK=P3^3;
sbit OUT=P3^4;
sbit DI=P3^5;
float key;
unsigned char code tab[]={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};
unsigned char temdat[]={0,0,0};
unsigned char adc0832(void);
void display(unsigned char *pl);
void delayms(unsigned char t);
void uart_init(void);
void send_string(unsigned char *str);
void main(void)
{
float tep;
unsigned char string[10]; // "X.XXV\r\n"共6个字符
unsigned int integer_part; // 整数部分(0~5)
unsigned int decimal_part; // 小数部分(0~99,代表0.00~0.99)
uart_init();
while(1)
{
tep = (5.0 / 255.0) * adc0832(); // 正确计算电压值
integer_part = (unsigned int)tep; // 提取整数部分(如3.85→3)
decimal_part = (unsigned int)((tep - integer_part) * 100 + 0.5); // 提取两位小数(+0.5是四舍五入)
// 构造字符串(例如 "3.85V\r\n")
string[0] = integer_part + '0'; // 整数位(3→'3')
string[1] = '.'; // 小数点
string[2] = (decimal_part / 10) + '0'; // 小数第一位(85/10=8→'8')
string[3] = (decimal_part % 10) + '0'; // 小数第二位(85%10=5→'5')
string[4] = 'V';
string[5] = '\r';
string[6] = '\n';
string[7] = '\0';
send_string(string);
delayms(1000);// 间隔1秒
}
}
/*********************************************
**函数描述:AD采样函数
**写入参数:无
**返回参数:电压0-5V对应的8位二进制数即0—255
************************************************/
unsigned char adc0832(void)
{
unsigned char i;
unsigned int l_key;
OUT=1;
CLK=0;
_nop_();_nop_();
CS=0;
DI=1;
_nop_();_nop_();//大于等于500ns
_nop_();_nop_();
_nop_();_nop_();
CLK=1;
_nop_();_nop_();
CLK=0;
DI=1;
_nop_();_nop_();
CLK=1;
_nop_();_nop_();
CLK=0;
DI=0;
_nop_();_nop_();
CLK=1;
_nop_();_nop_();
CLK=0;
_nop_();_nop_();
CLK=1;
_nop_();_nop_();
CLK=0;
for(i=0;i<8;i++)
{
l_key<<=1;
if(OUT)
l_key++;
CLK=1;
_nop_();_nop_();
CLK=0;
_nop_();_nop_(); //两个时钟下降延后就输出第一个数据,是一个同步串行通信协议
}
CS=1; //结束读取
return l_key;
}
/********************************************************
**名称:显示子函数
**功能:动态扫描P2口做为位选,P0口送段码
**输入:pl指向要显示数据的地址,最后3位
**返回:无
*******************************************************/
void display(unsigned char *pl)
{
P2=0x04;
P1=tab[*pl]; //低
delayms(3);
P1=0xff;
P2=0x02;
P1=tab[*(pl+1)]; //中
delayms(3);
P1=0xff;
P2=0x01;
P1=tab[*(pl+2)]&0x7f; //高 //高位数码管总是带小数,因为电压的范围:0—5V
delayms(3);
P1=0xff;
}
void delayms(unsigned char t)
{
unsigned char x,y;
for(x=t;x>0;x--)
for(y=110;y>0;y--);
}
//串口配置
void uart_init(void)
{
PCON |= 0x80; //使能波特率倍速位SMOD
SCON = 0x50; //允许接收中断,其中包括REN=1
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器1为方式2自动重载
TH1 = 0xf3; //波特率4800 (11.0592MHz晶振)
TL1 = 0xf3;
ET1 = 0; //禁止定时器1自身中断
TR1 = 1; //启动定时器1
EA = 1; //打开总中断
ES = 1; //打开串口中断
}
// 发送一个字节
void sendbyte(unsigned char byte)
{
SBUF = byte;
while(TI == 0); //等待发送完成
TI = 0; //清除发送标志
}
// 发送字符串
void send_string(unsigned char *str) //*str表示这是一个字符型指针,用于接收要发送的字符串的首地址
{
while(*str != '\0')
{
sendbyte(*str);
str++;
}
}
|