我現在用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++;
}
}
|