51 单片机 AT89C52 与温度传感器芯片 DS18B20 例程
一、 概述
本例程由 AT89C52 和 DS18B20 构成测温系统,并提供源程序供读者参考.
其测量的温度精度达到 0.1 度,测量的温度的范围在-20 度到+50 度之间,本
例程直接利用 P2 口和 P1 口输出对应的温度数字,读者很容易修改再用 4 位数
码管等显示部分显示出来,并且使用共阳极数码管显示温度值。
二、 电路图
C1
33pF
C2
33pF
C3
22uF
X1
12M
R1
10k
19
18
9
29
30
31
1
2
3
4
5
6
7
8
U1
XTAL1
XTAL2
RST
PSEN
ALE
EA
P1.0/T2
P1.1/T2EX
P1.2
P1.3
P1.4
P1.5
P1.6
P1.7
AT89C52
1
2
3
4
5
6
7
8
RN1
100
16
15
14
13
12
11
10
9
R2
4.7k
P0.0/AD0
P0.1/AD1
P0.2/AD2
P0.3/AD3
P0.4/AD4
P0.5/AD5
P0.6/AD6
P0.7/AD7
P2.0/A8
P2.1/A9
P2.2/A10
P2.3/A11
P2.4/A12
P2.5/A13
P2.6/A14
P2.7/A15
P3.0/RXD
P3.1/TXD
P3.2/INT0
P3.3/INT1
P3.4/T0
P3.5/T1
P3.6/WR
P3.7/RD
39
38
37
36
35
34
33
32
21
22
23
24
25
26
27
28
10
11
12
13
14
15
16
17
U2
VCC
DQ
GND
3
2
1
DS18B20
22.0
AT89S52 与 DS18B20 组成的测温系统原理图
三、 温度值对应关系举例
环境温度 Y 输出值(二进制,高
输出值(十进制)
-40
-32
-16
-10
-8
-7
-2
-1
0
1
2
3
4
按此公式
1111111111111111-Y+1
位 低位)
11111101 10000000 当为负温度时,输出计算
11111110 00000000
11111111 00000000
11111111 01100000
11111111 10000000
11111111 10010000
11111111 11100000
11111111 11110000
00000000 00000000
00000000 00010000
00000000 00100000
00000000 00110000
00000000 01000000
0
16
32
48
64
输出显示值
(十进制)/16
40
32
16
10
8
7
2
1
0
1
2
3
4
14
22
32
53
106(对应
电路图)
00000000 11100000
00000001 01100000
00000010 00000000
00000011 01010000
00000110 10100000
224
352
512
848
1496
14
22
32
53
106
注:在应用时,只需要将二进制输出转化成十进制再除以 16 显示出来即可。
四、 C 语言源程序
#include "REG52.H"
#include "INTRINS.H"
typedef unsigned char BYTE;//复杂的声明定义简单的别名 BYTE,类似#define uchar unsigned
char
#define uint unsigned int
long tmp;
sbit DQ = P3^3;
sbit P37= P3^7;
BYTE TPH;
BYTE TPL;
//存放温度值的高字节
//存放温度值的低字节
sbit P36= P3^6; sbit P35= P3^5; sbit P34= P3^4;
//DS18B20 的数据口位 P3.3
void DelayXus(BYTE n);
void DS18B20_Reset();
void DS18B20_WriteByte(BYTE dat);
void delay_ms( unsigned int x);
void led(unsigned int x);
BYTE DS18B20_ReadByte();
code unsigned char seg7code[11]={0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,0x70,}; //显示段码 0-9,℃ 符号
void main()
{
while (1)
{
DS18B20_Reset();
DS18B20_WriteByte(0xCC);
DS18B20_WriteByte(0x44);
while (!DQ);
DS18B20_Reset();
DS18B20_WriteByte(0xCC);
DS18B20_WriteByte(0xBE);
TPL = DS18B20_ReadByte();
//设备复位
//跳过 ROM 命令
//开始转换命令
//等待转换完成
//设备复位
//跳过 ROM 命令
//读暂存存储器命令
//读温度低字节
TPH = DS18B20_ReadByte();
P1=TPL;
P2=TPH;
tmp=TPH<<8;tmp=(tmp+TPL)/16;
//读温度高字节
//从 P1 口输出低位
//从 P2 口输出高位
//数据组合成温度,如 00000000 11100000 处理后变
成 14
//
led(TPL);
led(tmp);
delay_ms( 0);
}
}
//显示温度
//显示温度
//每隔 100ms 进行一次温度测量
/**************************************
延时 X*10 微秒(STC90C52RC@12M)
不同的工作环境,需要调整此函数
当改用 1T 的 MCU 时,请调整此延时函数
**************************************/
void DelayX0us(BYTE n)
{
while (n--)
{
_nop_();
_nop_();
}
}
/**************************************
复位 DS18B20,并检测设备是否存在
**************************************/
void DS18B20_Reset()
{
CY = 1;
while (CY)
{
DQ = 0;
DelayX0us(48);
DQ = 1;
DelayX0us(6);
CY = DQ;
DelayX0us(42);
}
}
//送出低电平复位信号
//延时至少 480us
//释放数据线
//等待 60us
//检测存在脉冲
//等待设备释放数据线
/**************************************
从 DS18B20 读 1 字节数据
**************************************/
BYTE DS18B20_ReadByte()
{
BYTE i;
BYTE dat = 0;
for (i=0; i<8; i++)
{
dat >>= 1;
DQ = 0;
_nop_();
_nop_();
DQ = 1;
_nop_();
_nop_();
if (DQ) dat |= 0x80;
DelayX0us(6);
}
return dat;
}
//8 位计数器
//开始时间片
//延时等待
//准备接收
//接收延时
//读取数据
//等待时间片结束
/**************************************
向 DS18B20 写 1 字节数据
**************************************/
void DS18B20_WriteByte(BYTE dat)
{
char i;
for (i=0; i<8; i++)
{
DQ = 0;
_nop_();
_nop_();
dat >>= 1;
DQ = CY;
DelayX0us(6);
DQ = 1;
}
}
//8 位计数器
//开始时间片
//延时等待
//送出数据
//等待时间片结束
//恢复数据线
/**************************************
P34=0;
//显示第 1 位 10ms,消
P35=0;
// 显 示 第 2 位
P36=0;
//显示第 3 位即℃
通用 LED 显示函数
**************************************/
void led(unsigned int x)
{
int i,y,z;
y=x/10;z=x%10;
for(i=0;i<2;i++)
{
P34=1;P35=0;P36=0;P37=0; P0=seg7code[y] ; delay_ms(10);
隐
P34=0;P35=1;P36=0;P37=0; P0=seg7code[z] ; delay_ms(10);
10ms,消隐
P34=0;P35=0;P36=1;P37=0; P0=seg7code[10] ; delay_ms(10);
10ms,消隐
}
}
/**************************************
通用延时函数
**************************************/
void delay_ms( unsigned int x)
{
unsigned int
for(i=x;i>1;i--)
for(j=114;j>1;j--);
i,j;
}