DS18B20+LCD1602數(shù)字溫度傳感器
顯示4位小數(shù)
僅支持正溫度
DJNZ指令為兩周期指令*/
RS BIT P2.4
RW BIT P2.5
E BIT P2.6
DQ BIT P1.7
COM DATA 30H
DAT DATA 31H
BAI DATA 32H
SHI DATA 33H
GEX DATA 34H
TH DATA 35H
TL DATA 36H
XI DATA 37H
ORG 0000H
SJMP MAIN
ORG 0030H
MAIN:MOV SP,#40H
LCALL INIT_LCD
N1:LCALL TEMP_18B20//測(cè)溫
LCALL LCD18B20//合并整數(shù) ,拆分小數(shù)
LCALL BCD//數(shù)據(jù)拆解,將16進(jìn)制轉(zhuǎn)為BCD碼
LCALL DISP_LCD//溫度顯示
LJMP N1
TEMP_18B20:LCALL INIT_18B20
MOV COM,#0CCH
LCALL WRITE_18B20
MOV COM,#44H
LCALL WRITE_18B20
LCALL DELAY200MS
LCALL INIT_18B20
MOV COM,#0CCH
LCALL WRITE_18B20
MOV COM,#0BEH
LCALL WRITE_18B20
LCALL READ_18B20
MOV TL,DAT
LCALL READ_18B20
MOV TH,DAT
RET
INIT_18B20:SETB DQ
NOP
CLR DQ
LCALL DELAY600US//延時(shí)600US
SETB DQ
MOV R0,#20
N2:NOP
DJNZ R0,N2//延時(shí)60US
JB DQ,$
LCALL DELAY600US//等待18B20響應(yīng)完畢
SETB DQ
RET
WRITE_18B20:MOV A,COM
MOV R2,#8
WR1:SETB DQ
NOP
CLR DQ
NOP
RRC A
MOV DQ,C
MOV R3,#30
DJNZ R3,$
DJNZ R2,WR1
SETB DQ//寫(xiě)完一個(gè)數(shù)據(jù)必須將DQ拉到,因?yàn)?br />RET //若最后一位C為低電平超過(guò)600US則DS18B20被復(fù)位
READ_18B20:MOV R2,#8
RE01:SETB DQ
NOP
CLR DQ
NOP
SETB DQ
MOV R3,#5
DJNZ R3,$
MOV C,DQ
MOV R3,#23
DJNZ R3,$
RRC A
DJNZ R2,RE01
MOV DAT,A
RET
LCD18B20:MOV R0,#04
MOV A,TH
N8:RL A
DJNZ R0,N8
MOV TH,A
MOV A,TL
SWAP A
ANL A,#0FH
ORL A,TH
MOV TH,A//整數(shù)部分
MOV A,#0FH
ANL A,TL
MOV TL,A//小婁部分
RET
BCD: MOV A,TH
MOV B,#100
DIV AB
MOV BAI,A
MOV A,B
MOV B,#10
DIV AB
MOV SHI,A
MOV GEX,B
MOV A,TL
MOV R0,#4
MOV R1,#XI//四位小數(shù)由高到低分別在XI開(kāi)始的單元中存儲(chǔ)
M1:MOV B,#10
MUL AB
MOV B,#16
DIV AB
MOV @R1,A
INC R1
MOV A,B
DJNZ R0,M1
RET
INIT_LCD:MOV COM,#00111000B
LCALL WRITE_COM
MOV COM,#00001110B
LCALL WRITE_COM
MOV COM,#00000110B
LCALL WRITE_COM
MOV COM,#00000001B
LCALL WRITE_COM
RET
DISP_LCD:MOV COM,#80H
LCALL WRITE_COM
MOV DPTR,#TABLE1
MOV R1,#16
MOV R0,#00
M2:MOV A,R0
MOVC A,@A+DPTR
MOV DAT,A
LCALL WRITE_DAT
INC R0
LCALL DELAY1MS
DJNZ R1,M2
MOV COM,#0C0H
LCALL WRITE_COM
MOV DPTR,#TABLE3
MOV R1,#05H
MOV R0,#00H
M3:MOV A,R0
MOVC A,@A+DPTR
MOV DAT,A
LCALL WRITE_DAT
INC R0
LCALL DELAY1MS
DJNZ R1,M3
MOV DPTR,#TABLE2
MOV A,BAI
MOVC A,@A+DPTR
MOV DAT,A
LCALL WRITE_DAT
MOV A,SHI
MOVC A,@A+DPTR
MOV DAT,A
LCALL WRITE_DAT
MOV A,GEX
MOVC A,@A+DPTR
MOV DAT,A
LCALL WRITE_DAT
MOV A,#10
MOV DPTR,#TABLE2
MOVC A,@A+DPTR
MOV DAT,A
LCALL WRITE_DAT
MOV R1,#04
MOV R0,#XI
M4:MOV A,@R0
MOVC A,@A+DPTR
MOV DAT,A
LCALL WRITE_DAT
LCALL DELAY1MS
INC R0
DJNZ R1,M4
MOV A,#11
MOVC A,@A+DPTR
MOV DAT,A
LCALL WRITE_DAT
LCALL DELAY1MS
RET
WRITE_COM:CLR RS
CLR RW
MOV P0,COM
LCALL DELAY3MS
CLR E
SETB E
CLR E
RET
WRITE_DAT:SETB RS
CLR RW
MOV P0,DAT
LCALL DELAY3MS
CLR E
SETB E
CLR E
RET
DELAY200MS: ;誤差 0us
MOV R7,#04H
DL6:
MOV R6,#74H
DL5:
MOV R5,#0D6H
DJNZ R5,$
DJNZ R6,DL5
DJNZ R7,DL6
NOP
RET
DELAY3MS: ;誤差 0us
MOV R6,#6FH
DL0:
MOV R5,#0CH
DJNZ R5,$
DJNZ R6,DL0
RET
DELAY1MS: ;誤差 0us
MOV R7,#01H
DL4:
MOV R6,#8EH
DL3:
MOV R5,#02H
DJNZ R5,$
DJNZ R6,DL3
DJNZ R7,DL4
RET
DELAY600US: ;誤差 0us
MOV R6,#03H
DL2:
MOV R5,#62H
DJNZ R5,$
DJNZ R6,DL2
RET
TABLE1: DB "Digital thermomet"
TABLE2: DB "0123456789.C"
TABLE3: DB "temp:"
END
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include
#include
#define uint unsigned int
#define uchar unsigned char
sbit rs=P2^4;
sbit rw=P2^5;
sbit e=P2^6;
sbit dq=P1^7;
uchar bai,shi,ge,xi1,xi2,i;
uint temp;
uchar code table1[]={"0123456789.C"};
uchar code table2[]="Digital thermomet";
uchar code table3[]="temp:";
void delay(uchar t) //誤差 0us 1mS延時(shí)
{
unsigned char a,b;
for(t=1;t>0;t--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}
/**************DS18B20操作******************/
void init_ds18b20()
{
dq=1;
_nop_();
dq=0;
for(i=0;i<200;i++);//延時(shí)min=480uS ,max=960uS;
dq=1;
for(i=0;i<20;i++);//延時(shí)min=15uS,max=60uS.DS18B20等待15~60uS;
while(dq);//dq為1表明無(wú)DS18B20
for(i=0;i<200;i++)//延時(shí)300us使DS18B20輸出應(yīng)答完畢
dq=1;
}
void WriteOneByte(uchar dat)
{
uchar j;
for(j=8;j>0;j--)
{
dq=1;
_nop_(); //至少1mS延時(shí)
dq=0;
_nop_();
dq=(bit)(dat&0x01);
for(i=0;i<20;i++);//寫(xiě)周期最少為60uS,不能超過(guò)120uS
dq=1;
//for(i=0;i<1;i++); //可以沒(méi)有
dat>>=1;
}
}
uchar ReadOneByte()
{
uchar j,dat;
for(j=0;j<8;j++)
{
dq=1;
_nop_(); //至少1uS的恢復(fù)期
dq=0;
_nop_();
dq=1;
for(i=0;i<3;i++);//主機(jī)在15uS內(nèi)讀取DQ
dat>>=1;
if(dq==1)
dat|=0x80;
else
dat|=0x00;
for(i=0;i<15;i++);//一個(gè)讀周期至少要60us
}
return(dat);
}
void temp_ds18b20()
{
uchar th,tl;
uint x;
float p;
init_ds18b20();
WriteOneByte(0xcc);
WriteOneByte(0x44);
delay(255);//等待轉(zhuǎn)換最大為750ms,典型值為200mS
init_ds18b20();
WriteOneByte(0xcc);
WriteOneByte(0xbe);
tl=ReadOneByte();
th=ReadOneByte();
x=th;
x<<=8;
x|=tl;//合并高低位
p=x*0.0625;//實(shí)際轉(zhuǎn)換溫度值為p
temp=p*100+0.5;//將小數(shù)轉(zhuǎn)換為整數(shù)并保留兩位小數(shù),第三位小數(shù)四舍五入
}
/******************************************************/
/***********************數(shù)據(jù)轉(zhuǎn)換***********************/
void datchx()
{
uchar d,t;
float g;
g=temp/100.00;
d=g;
t=(g-d)*100;//整數(shù)與小數(shù)部分分離,t為小數(shù),d為整數(shù);
bai=d/100;
shi=(d%100)/10;
ge=d%10;//整數(shù)分離
xi1=t/10;
xi2=t%10;
}
/****************************************************/
/******************LCD1602操作***********************/
void write_com(uchar dat)
{
rs=0;
rw=0;
P0=dat;
delay(3);
e=0;
e=1;
e=0;
}
void write_dat(uchar dat)
{
rs=1;
rw=0;
P0=dat;
delay(3);
e=0;
e=1;
e=0;
}
void init_lcd()
{
write_com(0x38);
write_com(0x0D);
write_com(0x06);
write_com(0x01);
}
void disp_lcd()
{
write_com(0x80);
for(i=0;i<16;i++)
{
write_dat(table2[i]);
delay(5);
}
write_com(0xc0);
for(i=0;i<5;i++)
{
write_dat(table3[i]);
delay(5);
}
write_dat(table1[bai]);
write_dat(table1[shi]);
write_dat(table1[ge]);
write_dat(table1[10]);
write_dat(table1[xi1]);
write_dat(table1[xi2]);
write_dat(table1[11]);
}
/****************************************************/
void main()
{
SP=0x30;
init_lcd();
while(1)
{
temp_ds18b20();
datchx();
disp_lcd();
}
}
評(píng)論