|
|
我現(xiàn)在用ADC0832采集數(shù)據(jù),0832的基準(zhǔn)電壓測(cè)出來(lái)實(shí)際是4.95V,剛開始是采集后的數(shù)據(jù)顯示到數(shù)碼管上,但是有誤差,于是就改為將電壓值發(fā)送到串口進(jìn)行顯示,現(xiàn)在串口顯示數(shù)據(jù)為4.51V的時(shí)候,輸入電壓測(cè)出來(lái)實(shí)際值為4.77V,有0.2v的誤差,有沒(méi)有大神知道這誤差怎么來(lái)的,以及如何解決呢。感謝。
這是我的程序,寫的有點(diǎn)亂,因?yàn)樾薷牧撕枚啻危娬彙?br />
#include<reg52.h>
#include<intrins.h>
/***********ad0832與單片機(jī)的接口定義**********************/
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個(gè)字符
unsigned int integer_part; // 整數(shù)部分(0~5)
unsigned int decimal_part; // 小數(shù)部分(0~99,代表0.00~0.99)
uart_init();
while(1)
{
tep = (5.0 / 255.0) * adc0832(); // 正確計(jì)算電壓值
integer_part = (unsigned int)tep; // 提取整數(shù)部分(如3.85→3)
decimal_part = (unsigned int)((tep - integer_part) * 100 + 0.5); // 提取兩位小數(shù)(+0.5是四舍五入)
// 構(gòu)造字符串(例如 "3.85V\r\n")
string[0] = integer_part + '0'; // 整數(shù)位(3→'3')
string[1] = '.'; // 小數(shù)點(diǎn)
string[2] = (decimal_part / 10) + '0'; // 小數(shù)第一位(85/10=8→'8')
string[3] = (decimal_part % 10) + '0'; // 小數(shù)第二位(85%10=5→'5')
string[4] = 'V';
string[5] = '\r';
string[6] = '\n';
string[7] = '\0';
send_string(string);
delayms(1000);// 間隔1秒
}
}
/*********************************************
**函數(shù)描述:AD采樣函數(shù)
**寫入?yún)?shù):無(wú)
**返回參數(shù):電壓0-5V對(duì)應(yīng)的8位二進(jìn)制數(shù)即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_(); //兩個(gè)時(shí)鐘下降延后就輸出第一個(gè)數(shù)據(jù),是一個(gè)同步串行通信協(xié)議
}
CS=1; //結(jié)束讀取
return l_key;
}
/********************************************************
**名稱:顯示子函數(shù)
**功能:動(dòng)態(tài)掃描P2口做為位選,P0口送段碼
**輸入:pl指向要顯示數(shù)據(jù)的地址,最后3位
**返回:無(wú)
*******************************************************/
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; //高 //高位數(shù)碼管總是帶小數(shù),因?yàn)殡妷旱姆秶?—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; //設(shè)置定時(shí)器模式
TMOD |= 0x20; //設(shè)置定時(shí)器1為方式2自動(dòng)重載
TH1 = 0xf3; //波特率4800 (11.0592MHz晶振)
TL1 = 0xf3;
ET1 = 0; //禁止定時(shí)器1自身中斷
TR1 = 1; //啟動(dòng)定時(shí)器1
EA = 1; //打開總中斷
ES = 1; //打開串口中斷
}
// 發(fā)送一個(gè)字節(jié)
void sendbyte(unsigned char byte)
{
SBUF = byte;
while(TI == 0); //等待發(fā)送完成
TI = 0; //清除發(fā)送標(biāo)志
}
// 發(fā)送字符串
void send_string(unsigned char *str) //*str表示這是一個(gè)字符型指針,用于接收要發(fā)送的字符串的首地址
{
while(*str != '\0')
{
sendbyte(*str);
str++;
}
}
|
|