DS18B20温度传感器
芯片:AT89S52 :如下
/************************************************************************* 该程序的功能如下:DS18B20使用程序。将DS18B读取20的温度值并显示 示在液晶LCD1602上。 作者:Crazy Wind 日期:2020.11.9 version:1.0.0 **************************************************************************/ #include"reg52.h" #include"intrins.h" #define uchar unsigned char #define uint unsigned int uchar code digit[11]={
"0123456789-"}; ///定义字符数组显示数字 uchar code Str[]={
"DS18B20"}; //说明显示的是温度 uchar code Error[]={
" DS18B20 ERROR"}; //说明没有检测到DS18B20 uchar code Error1[]={
" PLEASE CHECK"}; //说明没有检测到DS18B20 uchar code Temp[]={
"Temp:"}; ///说明显示温度 uchar code Cent[]={
"C"}; ///温度单位 uchar flag,tltemp; ///负温度标志和临时暂存变量 /***************************************************** 函数功能:ms延时 ******************************************************/ void delayms(uint ms) {
uchar i,j; for(i=0;i<ms;i ) {
for(j=115;j>0;j--)
;
}
}
/*****************************************************************/
/***********************液晶LCD1602操作程序***********************/
/*****************************************************************/ sbit RS
=P2
^
0
;
//寄存器选择位RS为P2.0 sbit RW
=P2
^
1
;
//读写选择位RW为P2.1 sbit E
=P2
^
2
;
//使能信号位E为P2.2 sbit BF
=P0
^
7
;
//忙碌标志位BF为P0.7
/***************************************************** 函数功能:判断液晶模块的忙碌状态 返回值:busy。busy=1,忙碌;busy=0,不忙 ******************************************************/ bit
BusyTest
(
void
)
{
bit busy
; RS
=
0
;
//RS为低电平,RW为高电平时,可以读状态 RW
=
1
; E
=
1
;
//E=1,才允许读写
_nop_
(
)
;
//空操作四个机器周期,给硬件反应时间
_nop_
(
)
;
_nop_
(
)
;
_nop_
(
)
; busy
=BF
;
//将忙碌标志电平赋给m E
=
0
;
return busy
;
//将忙碌标志电平赋给m
}
/***************************************************** 函数功能:将模式设置指令或显示地址写入液晶模块 入口参数:z ******************************************************/
void
Write_zl
(uchar z
)
{
while
(
BusyTest
(
)
==
1
)
;
//如果忙就等待 RS
=
0
;
//RS和RW同时为低电平时,可以写入指令 RW
=
0
; E
=
0
;
//使能信号E置低电平(写指令前先赋低电平0)
_nop_
(
)
;
_nop_
(
)
;
//空操作两个机器周期,给硬件反应时间 P0
=z
;
//将数据送入P0口(数据总线line),即写入指令或地址
_nop_
(
)
;
_nop_
(
)
;
_nop_
(
)
;
_nop_
(
)
;
//空操作四个机器周期,给硬件反应时间 E
=
1
;
//使能信号E上升沿(0到1)时读取信息
_nop_
(
)
;
_nop_
(
)
;
_nop_
(
)
;
_nop_
(
)
;
//空操作四个机器周期,给硬件反应时间 E
=
0
;
//使能信号E下降沿(1到0)时执行指令
}
/***************************************************** 函数功能:指定字符显示的实际地址 入口参数:x ******************************************************/
void
WriteAddress
(uchar x
)
{
Write_zl
(x
|
0x80
)
;
//显示位置的确定方法规定为"地址码x+80H"
}
/***************************************************** 函数功能:将数据(字符的标准ASCII码)写入液晶模块 入口参数:y(为字符常量) ******************************************************/
void
WriteData
(uchar y
)
{
while
(
BusyTest
(
)
==
1
)
;
//如果忙就等待 RS
=
1
;
//RS为高电平,RW为低电平时,可以写入数据 RW
=
0
; E
=
0
;
//使能信号E置低电平(写数据前先赋低电平0)
_nop_
(
)
;
_nop_
(
)
;
//空操作两个机器周期,给硬件反应时间 P0
=y
;
//将数据送入P0口(数据总线line),即将数据写入液晶模块
_nop_
(
)
;
_nop_
(
)
;
_nop_
(
)
;
_nop_
(
)
;
//空操作四个机器周期,给硬件反应时间 E
=
1
;
//使能信号E上升沿(0到1)时读取信息
_nop_
(
)
;
_nop_
(
)
;
_nop_
(
)
;
_nop_
(
)
;
//空操作四个机器周期,给硬件反应时间 E
=
0
;
//使能信号E下降沿(1到0)时执行指令
}
/***************************************************** 函数功能:对LCD的显示模式进行初始化设置 ******************************************************/
void
LcdInit
(
void
)
{
delayms
(
15
)
;
//延时15ms,首次写指令时应给LCD一段较长的反应时间
Write_zl
(
0x38
)
;
//显示模式设置:16×2显示,5×7点阵,8位数据接口
delayms
(
5
)
;
//延时5ms
Write_zl
(
0x38
)
;
delayms
(
5
)
;
Write_zl
(
0x38
)
;
//3次写 设置模式
delayms
(
5
)
;
Write_zl
(
0x0c
)
;
//显示模式设置:显示开,无光标,光标不闪烁
delayms
(
5
)
;
Write_zl
(
0x06
)
;
//显示模式设置:光标右移,字符不移
delayms
(
5
)
;
Write_zl
(
0x01
)
;
//清屏幕指令,将以前的显示内容清除
delayms
(
5
)
;
}
/*****************************************************************/
/*************************DS18B20操作程序*************************/
/*****************************************************************/ sbit DQ
=P3
^
3
;
//DS18B20管脚 uchar time
;
//设置全局变量,专门用于严格延时
/***************************************************** 函数功能:将DS18B20传感器初始化,读取应答信号 出口参数:flag ******************************************************/ bit
Init_DS18B20
(
void
)
{
bit flag
;
//储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在 DQ
=
1
;
//先将数据线拉高
for
(time
=
0
;time
<
2
;time
++
)
;
//略微延时约6μs DQ
=
0
;
//再将数据线从高拉低,要求保持480~960μs
for
(time
=
0
;time
<
200
;time
++
)
;
//略微延时约600μs,以向DS18B20发出一持续480~960μs的低电平复位脉冲 DQ
=
1
;
//释放数据线(将数据线拉高)
for
(time
=
0
;time
<
10
;time
++
)
;
//延时约30μs(释放总线后需等待15~60μs让DS18B20输出存在脉冲) flag
=DQ
;
//让单片机检测是否输出了存在脉冲(DQ=0表示存在)
for
(time
=
0
;time
<
200
;time
++
)
;
//延时足够长时间,等待存在脉冲输出完毕
return
(flag
)
;
//返回检测成功标志
}
/***************************************************** 函数功能:向DS18B20写一个字节数据 出口参数:dat ******************************************************/
void
WriteOneChar
(uchar dat
)
{
uchar i
=
0
;
for
(i
=
0
;i
<
8
;i
++
)
{
DQ
=
1
;
//先将数据线拉高
_nop_
(
)
;
//等待一个机器周期 DQ
=
0
;
//将数据线从高拉低,即启动写时序 DQ
=dat
&
0x01
;
//给数据线送dat中二进制数据的低位,等待DS18B20采样
for
(time
=
0
;time
<
10
;time
++
)
;
//延时约30μs,DS18B20在拉低后的约15~60μs期间从数据线上采样 DQ
=
1
;
//释放数据线
for
(time
=
0
;time
<
1
;time
++
)
;
//延时3μs,两个写时序间至少需要1μs的恢复期 dat
>>=
1
;
//将dat中的各二进制位数据右移1位
}
for
(time
=
0
;time
<
4
;time
++
)
;
//稍作延时,给硬件一点反应时间
}
/***************************************************** 函数功能:从DS18B20读一个字节数据 出口参数:dat ******************************************************/ uchar
ReadOneChar
(
void
)
{
uchar i
=
0
; uchar dat
;
//储存读出的一个字节数据
for
(i
=
0
;i
<
8
;i
++
)
{
DQ
=
1
;
// 先将数据线拉高
_nop_
(
)
;
//等待一个机器周期 DQ
=
0
;
//将数据线从高拉低,即启动读时序
_nop_
(
)
;
//等待一个机器周期 DQ
=
1
;
//将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备
for
(time
=
0
;time
<
2
;time
++
)
;
//延时约6μs,使主机在15μs内采样 dat
>>=
1
;
//将dat中的各二进制位数据右移1位
if
(DQ
==
1
) dat
|
=
0x80
;
//如果读到的数据是1,则将1存入dat
else dat
|
=
0x00
;
//如果读到的数据是0,则将0存入dat
for
(time
=
0
;time
<
8
;time
++
)
;
//延时3μs,两个读时序之间必须有大于1μs的恢复期
}
return
(dat
)
;
//返回读出的十六进制数据
}
/***************************************************** 函数功能:从DS18B20读一个字节数据 出口参数:dat ******************************************************/
void
ReadyReadTemp
(
void
)
{
Init_DS18B20
(
)
;
//将DS18B20初始化
WriteOneChar
(
0xCC
)
;
//跳过读序号列号的操作
WriteOneChar
(
0x44
)
;
//启动温度转换
delayms
(
200
)
;
//转换一次需要延时一段时间
Init_DS18B20
(
)
;
//将DS18B20初始化
WriteOneChar
(
0xCC
)
;
//跳过读序号列号的操作
WriteOneChar
(
0xBE
)
;
//读取温度寄存器,前两个分别是温度的低位和高位
}
/*****************************************************************/
/****************************显示模块*****************************/
/*****************************************************************/ uchar code zidingyi
[
]
=
{
0x07
,
0x05
,
0x07
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
}
;
//自定义字符
/***************************************************** 函数功能:显示没有检测到DS18B20 ******************************************************/
void
display_error
(
void
)
{
uchar i
;
WriteAddress
(
0x00
)
;
//写显示地址,将在第1行第1列开始显示 i
=
0
;
while
(Error
[i
]
!=
'\0'
)
//"\0"数组结束标志
{
WriteData
(Error
[i
]
)
;
//将字符常量写入LCD i
++
;
delayms
(
100
)
;
//延时100ms
}
WriteAddress
(
0x40
)
;
//写显示地址,将在第2行第1列开始显示 i
=
0
;
while
(Error1
[i
]
!=
'\0'
)
//"\0"数组结束标志
{
WriteData
(Error1
[i
]
)
;
//将字符常量写入LCD i
++
;
delayms
(
100
)
;
//延时100ms
}
while
(
1
)
;
//进入死循环,等待查明原因
}
/***************************************************** 函数功能:显示说明信息 ******************************************************/
void
display_explain
(
void
)
{
uchar i
;
WriteAddress
(
0x04
)
;
//写显示地址,将在第1行第5列开始显示 i
=
0
;
while
(Str
[i
]
!=
'\0'
)
//"\0"数组结束标志
{
WriteData
(Str
[i
]
)
;
//将字符常量写入LCD i
++
;
delayms
(
100
)
;
//延时100ms
}
}
/***************************************************** 函数功能:显示说明信息 ******************************************************/
void
display_symbol
(
void
)
{
uchar i
;
WriteAddress
(
0x40
)
;
//写显示地址,将在第2行第1列开始显示 i
=
0
;
while
(Temp
[i
]
!=
'\0'
)
//"\0"数组结束标志
{
WriteData
(Temp
[i
]
)
;
//将字符常量写入LCD i
++
;
delayms
(
50
)
;
//延时50ms
}
}
/***************************************************** 函数功能:显示温度的小数点 ******************************************************/
void
display_dot
(
void
)
{
WriteAddress
(
0x49
)
;
//写显示地址,将在第2行第10列开始显示
WriteData
(
'.'
)
;
//将小数点的字符常量写入LCD
delayms
(
50
)
;
//延时50ms
}
/***************************************************** 函数功能:显示温度的单位(Cent) ******************************************************/
void
display_cent
(
void
)
{
uchar i
,a
;
WriteAddress
(
0x4d
)
;
//写显示地址,将在第2行第14列开始显示 i
=
0
;
while
(Cent
[i
]
!=
'\0'
)
//"\0"数组结束标志
{
WriteData
(Cent
[i
]
)
;
//将字符常量写入LCD i
++
;
delayms
(
50
)
;
//延时50ms
}
Write_zl
(
0x40
)
;
//设定CGRAM地址
delayms
(
5
)
;
for
(a
=
0
;a
<
8
;a
++
)
{
WriteData
(zidingyi
[a
]
)
;
//写入自定义图形
}
WriteAddress
(
0x4c
)
;
//设定屏幕上的显示位置
delayms
(
5
)
;
WriteData
(
0x00
)
;
//从CGRAM里取出自定义图形显示
}
/***************************************************** 函数功能:显示温度的整数部分 入口参数:x ******************************************************/
void
display_temp1
(uchar x
)
{
uchar b
,s
,g
;
//分别储存温度的百位、十位和个位 b
=x
/
100
;
//取百位 s
=
(x
%
100
)
/
10
;
//取十位 g
=x
%
10
;
//取个位
WriteAddress
(
0x46
)
;
//写显示地址,将在第2行第7列开始显示
if
(flag
==
1
)
//负温度时显示“—”
{
WriteData
(digit
[
10
]
)
;
//将"-"的字符常量写入LCD
}
else
{
WriteData
(digit
[b
]
)
;
//将百位数字的字符常量写入LCD
}
WriteData
(digit
[s
]
)
;
//将十位数字的字符常量写入LCD
WriteData
(digit
[g
]
)
;
//将个位数字的字符常量写入LCD
delayms
(
50
)
;
//延时50ms
}
/***************************************************** 函数功能:显示温度的小数数部分 入口参数:x ******************************************************/
void
display_temp2
(uchar x
)
{
WriteAddress
(
0x4a
)
;
//写显示地址,将在第2行第11列开始显示
WriteData
(digit
[x
]
)
;
//将小数部分的第一位数字字符常量写入LCD
标签: ds18b20温度传感器参数