显示4位小数
仅支持正温度
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//测温
LCALL LCD18B20//合并整数 ,拆分小数
LCALL BCD//数据拆解,将16进制转为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//延时600US
SETB DQ
MOV R0,#20
N2:NOP
DJNZ R0,N2 //延时60US
JB DQ,$
LCALL DELAY600US //等待18B20响应完毕
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//写完一个数据必须将DQ拉到,因为
RET //若最后一位C为低电平超过600US则DS18B20被复位
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//整数部分
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 //四位小数由高到低分别在XI开始的单元中存储
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延时
{
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++);//延时min=480uS ,max=960uS;
dq=1;
for(i=0;i<20;i++);//延时min=15uS,max=60uS.DS18B20等待15~60uS;
while(dq); //dq为1表明无DS18B20
for(i=0;i<200;i++)//延时300us使DS18B20输出应答完毕
dq=1;
}
void WriteOneByte(uchar dat)
{
uchar j;
for(j=8;j>0;j--)
{
dq=1;
_nop_(); //至少1mS延时
dq=0;
_nop_();
dq=(bit)(dat&0x01);
for(i=0;i<20;i++);//写周期最少为60uS,不能超过120uS
dq=1;
//for(i=0;i<1;i++); //可以没有
dat>>=1;
}
}
uchar ReadOneByte()
{
uchar j,dat;
for(j=0;j<8;j++)
{
dq=1;
_nop_(); //至少1uS的恢复期
dq=0;
_nop_();
dq=1;
for(i=0;i<3;i++);//主机在15uS内读取DQ
dat>>=1;
if(dq==1)
dat|=0x80;
else
dat|=0x00;
for(i=0;i<15;i++);//一个读周期至少要60us
}
return(dat);
}
void temp_ds18b20()
{
uchar th,tl;
uint x;
float p;
init_ds18b20();
WriteOneByte(0xcc);
WriteOneByte(0x44);
delay(255);//等待转换最大为750ms,典型值为200mS
init_ds18b20();
WriteOneByte(0xcc);
WriteOneByte(0xbe);
tl=ReadOneByte();
th=ReadOneByte();
x=th;
x<<=8;
x|=tl; //合并高低位
p=x*0.0625; //实际转换温度值为p
temp=p*100+0.5;//将小数转换为整数并保留两位小数,第三位小数四舍五入
}
/******************************************************/
/***********************数据转换***********************/
void datchx()
{
uchar d,t;
float g;
g=temp/100.00;
d=g;
t=(g-d)*100;//整数与小数部分分离,t为小数,d为整数;
bai=d/100;
shi=(d%100)/10;
ge=d%10;//整数分离
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();
}
}
上一篇:AT89C2051+LCD1602+DS1302实时时钟设计(c51)
下一篇:LCD1602+ADC0832数字电压表(asm/c51)
推荐阅读最新更新时间:2024-03-16 15:12
- 热门资源推荐
- 热门放大器推荐