基于AT89C51单片机和DS18B20温度传感器、LCD1602液晶显示的多路数字温度计程序

如题所述

//DS从机程序
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define SLAVE 0x01
#define BN 6
sbit LCD_RS = P2^5; /*定义LCD控制端口*/
sbit LCD_RW = P2^6;
sbit LCD_EN = P2^7;

sbit DS1=P1^0;
sbit DS2=P1^1;
sbit key3=P3^5;
sbit tem=P3^3;
sbit win=P3^4;
sbit key1=P3^6;
sbit key2=P3^7;
uint temp1,temp2,tempH,tempL; // variable of temperature
uchar flag1,aa,we;
uchar A1,A2,A3,A4,B1,B2,B3,B4; // sign of the result positive or negative
uchar dis1[16]={76,45,84,'0','0','.','0',32,32,72,45,84,'0','0','.','0'};
uchar dis2[16]={48,49,32,'0','0','.','0',32,32,48,50,32,'0','0','.','0'};
uchar code tab[] = {'0','1','2','3','4','5','6','7','8','9'};
uchar trbuf[6];
bit tready;
bit rready;
void str(void);
void sre(void);

void delay(int ms)
{
int i;
while(ms--)
{
for(i = 0; i< 250; i++)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
}

/*******************************************************************/
/* */
/*检查LCD忙状态 */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。 */
/* */
/*******************************************************************/

bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (bit)(P0&0x80);
LCD_EN = 0;
return result;
}

/*******************************************************************/
/* */
/*写指令数据到LCD */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 */
/* */
/*******************************************************************/

void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 0;
}

/*******************************************************************/
/* */
/*写显示数据到LCD */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。 */
/* */
/*******************************************************************/

void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 0;
}

/*******************************************************************/
/* */
/* 设定显示位置 */
/* */
/*******************************************************************/

void lcd_pos(uchar pos)
{
lcd_wcmd(pos|0x80); //数据指针=80+地址变量
}

/*******************************************************************/
/* */
/* LCD初始化设定 */
/* */
/*******************************************************************/

void lcd_init()
{
lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x38);
delay(5);

lcd_wcmd(0x0c); //显示开,关光标
delay(5);
lcd_wcmd(0x06); //移动光标
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(5);
lcd_wcmd(0x06); //向右移动光标
delay(5);
}

/*******************************************************************/
/* */
/* 闪动子程序 */
/* */
/*******************************************************************/

void flash()
{
delay(600); //控制停留时间
lcd_wcmd(0x08); //关闭显示
delay(200); //延时
lcd_wcmd(0x0c); //开显示
delay(200); //延时
lcd_wcmd(0x08); //关闭显示
delay(200); //延时
lcd_wcmd(0x0c); //开显示
delay(200);
}

/*void delay(uint count) //delay
{
uint i;
while(count)
{
i=100;
while(i>0)
i--;
count--;
}
} */
///////功能:串口初始化,波特率9600,方式1///////
void Init(void)
{
TMOD=0x20;
TL1=0xfd;
TH1=0xfd;
PCON=0x00;
TR1=1;
SCON=0xf0;
ES=1;
EA=1;
}

void dsreset(uchar DS) //send reset and initialization command 18B20复位,初始化函数
{
uint i;
if(DS==1)
{
DS1=0;
i=103;
while(i>0)i--;
DS1=1;
i=4;
while(i>0)i--;
}
if(DS==2)
{
DS2=0;
i=103;
while(i>0)i--;
DS2=1;
i=4;
while(i>0)i--;
}
}

bit tmpreadbit(uchar DS) //read a bit 读DS2 1位数据函数
{
uint i;
bit dat;
if(DS==1)
{
DS1=0;i++; //i++ for delay
DS1=1;i++;i++;
dat=DS1;
i=8;while(i>0)i--;
}
if(DS==2)
{
DS2=0;i++; //i++ for delay
DS2=1;i++;i++;
dat=DS2;
i=8;while(i>0)i--;
}
return (dat);
}

uchar tmpread(uchar DS) //read a byte date 读1字节函数
{
uchar i,j,dat;
dat=0;
if(DS==1)
{
for(i=1;i<=8;i++)
{
j=tmpreadbit(1);
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
}
if(DS==2)
{
for(i=1;i<=8;i++)
{
j=tmpreadbit(2);
dat=(j<<7)|(dat>>1); //读出的数据最低位在最前面,这样刚好一个字节在DAT里
}
}
return(dat);
}

void tmpwritebyte(uchar dat,uchar DS) //write a byte to ds18b20 向1820写一个字节数据函数
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(DS==1)
{
if(testb) //write 1
{
DS1=0;
i++;i++;
DS1=1;
i=8;while(i>0)i--;
}
else
{
DS1=0; //write 0
i=8;while(i>0)i--;
DS1=1;
i++;i++;
}
}
if(DS==2)
{
if(testb) //write 1
{
DS2=0;
i++;i++;
DS2=1;
i=8;while(i>0)i--;
}
else
{
DS2=0; //write 0
i=8;while(i>0)i--;
DS2=1;
i++;i++;
}
}
}
}

void tmpchange(uchar DS) //DS18B20 begin change 开始获取数据并转换
{
if(DS==1)
{
dsreset(1);
delay(1);
tmpwritebyte(0xcc,1); // address all drivers on bus 写跳过读ROM指令
tmpwritebyte(0x44,1);
} // initiates a single temperature conversion 写温度转换指令
if(DS==2)
{
dsreset(2);
delay(1);
tmpwritebyte(0xcc,2); // address all drivers on bus 写跳过读ROM指令
tmpwritebyte(0x44,2);
} // initiates a single temperature conversion 写温度转换指令
}

uint tmp1(void) //get the temperature 读取寄存器中存储的温度数据
{
float tt;
uchar a,b;
dsreset(1);
delay(1);
tmpwritebyte(0xcc,1);
tmpwritebyte(0xbe,1);
a=tmpread(1); //读低8位
b=tmpread(1); //读高8位
temp1=b;
temp1<<=8; //two byte compose a int variable 两个字节组合为1个字
temp1=temp1|a;
tt=temp1*0.0625; //温度在寄存器中是12位,分辨率是0.0625
temp1=tt*10+0.5; //乘10表示小数点后只取1位,加0.5是四折五入
//temp1=temp1+5; //误差补偿
return temp1;
}
uint tmp2( void) //get the temperature 读取寄存器中存储的温度数据
{
float tt;
uchar a,b;
dsreset(2);
delay(1);
tmpwritebyte(0xcc,2);
tmpwritebyte(0xbe,2);
a=tmpread(2); //读低8位
b=tmpread(2); //读高8位
temp2=b;
temp2<<=8; //two byte compose a int variable 两个字节组合为1个字
temp2=temp2|a;
tt=temp2*0.0625; //温度在寄存器中是12位,分辨率是0.0625
temp2=tt*10+0.5; //乘10表示小数点后只取1位,加0.5是四折五入
//temp2=temp2+5; //误差补偿
return temp2;
}
void delay10ms() //delay
{
uchar a,b;
for(a=10;a>0;a--)
for(b=60;b>0;b--);
}

uchar display(uint temp1,uint temp2) //显示程序
{
uchar i;
A1=temp1/100;
A2=temp1%100/10;
A3=temp1%100%10;

B1=temp2/100;
B2=temp2%100/10;
B3=temp2%100%10;

trbuf[0]=A1;
trbuf[1]=A2;
trbuf[2]=A3;
trbuf[3]=B1;
trbuf[4]=B2;
trbuf[5]=B3;

dis1[3]=tab[tempL*10/100];
dis1[4]=tab[tempL*10%100/10];
dis1[6]=tab[tempL*10%100%10];

dis1[12]=tab[tempH*10/100];
dis1[13]=tab[tempH*10%100/10];
dis1[15]=tab[tempH*10%100%10];
dis2[3]=tab[A1];
dis2[4]=tab[A2];
dis2[6]=tab[A3];

dis2[12]=tab[B1];
dis2[13]=tab[B2];
dis2[15]=tab[B3];

delay(1);
lcd_pos(0); //设置显示位置为第一行的第1个字符
delay(2);
for(i=0;i<16;i++)
{
lcd_wdat(dis1[i]);
}
delay(2);
lcd_pos(0x40);
delay(2);
for(i=0;i<16;i++)
{
lcd_wdat(dis2[i]);
}

return (A1,A2,A3,B1,B2,B3);
}
void TemC()
{
if(temp1<=(tempL*10)||temp2<=(tempL*10)) tem=0;
else tem=1;
if (temp1>=(tempH*10)||temp2>=(tempH*10)) win=0;
else win=1;
}

uchar chan()
{
if(key1==0)
{
tempL++;
while(key1==0);
if(tempL>35)
tempL=0;
}

if(key2==0)
{
tempH++;
while(key2==0);
if(tempH>35)
tempH=0;
}
return (tempH,tempL);
}

/******************************************************************************/

void main()
{ //uchar a;

//uchar i;
delay(10);
lcd_init();
Init();
tempH=35;
tempL=15;
while(1)
{
tmpchange(1);
tmpchange(2);
tmp1();
tmp2();
chan();
TemC();
display(temp1,temp2);

tready=1;
rready=1;
}
}
void ssio(void)interrupt 4
{
uchar a;
RI=0;
ES=0;
if(SBUF!=SLAVE)
{
ES=1;
goto reti;
}
SM2=0;
SBUF=SLAVE;
while(TI!=1);
TI=0;
while(RI!=1);
RI=0;

if(RB8==1)
{
SM2=1;
ES=1;
goto reti;
}
a=SBUF;
if(a==0x02)
{
if(tready==1)
SBUF=0x02;
else
SBUF=0x00;
while(TI!=1);
TI=0;

str();
goto reti;
}
else
{
SBUF=0x08;
while(TI!=1);
TI=0;
SM2=1;
ES=1;
}
reti:RI=0;
SM2=1;
ES=1;

}
void str(void)
{
uchar i;
tready=0;
while(1)
{

tmpchange(1);
tmpchange(2);
tmp1();
tmp2();
chan();
TemC();
display(temp1,temp2);
for(i=0;i<BN;i++)
{
SBUF=trbuf[i];
while(TI!=1);
TI=0;
}
while(RI!=1);
RI=0;
if(RB8==1)goto loop;
}
loop:SM2=1;
ES=1;
}追问

很感谢很感谢你哦,可是我的不是很懂得程序,如果还能解释一下该多好呀,就有的程序语句不是看的很明白你,谢谢了!

追答

DS18B20序列号测试程序http://wenku.baidu.com/view/f9d519d1c1c708a1284a44bc.html

温馨提示:答案为网友推荐,仅供参考
第1个回答  2012-05-29
正打算做这个程序呢,不过要做的是要事先读出每个的序列号
第2个回答  2012-05-29
楼上回答正确 这个我之前做过的 有问题可以交流下追问

请问有程序的代码嘛?极度需要把代码给我行不!

相似回答