DS18B20测温范围-55——125度,在-10——85度之间精度为0.5度,其测温精度还是较高的,DS18B20常见封装为3个引脚,VCC(电源正),DQ(信号线),GND(电源负),如图:
DS18B20相关指令,如下表:
指令 | 功能 |
---|---|
33H | 读ROM,即DS18B20传感器中ROM的编码 |
55H | 匹配ROM,为下一步读或写做准备 |
F0H | 搜索ROM,确定挂接在同一总线上DS18B20的个数 |
CCH | 跳过ROM,直接向DS18B20发温度转换命令,适用于只有一个DS18B20 |
ECH | 告警搜索,执行后只有温度超过上限或下限的传感器作出相应 |
44H | 温度转换,将结果存在内部9字节的RAM中 |
BEH | 读RAM,即读内部RAM中9字节的温度数据 |
4EH | 写RAM,向内部RAM的第2,3字节处写上、下限温度数据,紧跟该命令后传送两字节的数据,即上下限温度 |
48H | 复制RAM,将RAM中第2,3字节的内容复制到EEPROM中 |
B8H | 数据恢复,即将EEPROM中的内容恢复到RAM中的第3,4字节 |
B4H | 读供电方式,寄生供电时DS18B20发送0,外接电源供电时DS18B20发送1 |
DS18B20时序图如下:
(1)初始化
(2)DS18B20写数据
(3)DS18B20读数据
例程:
DS18B20.h
#ifndef __DS18B20_H_
#define __DS18B20_H_
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS18B20=P3^7;
extern uchar ShowData[6];
void Delay1ms(uint );
uchar Ds18b20Init();
void Ds18b20WriteByte(uchar com);
uchar Ds18b20ReadByte();
void Ds18b20ChangeTemp();
void Ds18b20ReadTempCom();
int Ds18b20ReadTemp();
void Datapros();
#endif
DS18B20.c
#include "DS18B20.h"
uchar ShowData[6]={0};
void Delay1ms(uint y)
{
uint x;
for( ; y>0; y--)
{
for(x=110; x>0; x--);
}
}
uchar Ds18b20Init()
{
uchar i;
DS18B20 = 0; //将总线拉低480us~960us
i = 70;
while(i--);//延时642us
DS18B20 = 1; //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
i = 0;
while(DS18B20) //等待DS18B20拉低总线
{
Delay1ms(1);
i++;
if(i>5)//等待>5MS
{
return 0;//初始化失败
}
}
return 1;//初始化成功
}
void Ds18b20WriteByte(uchar data)
{
uint i, j;
for(j=0; j<8; j++)
{
DS18B20 = 0; //每写入一位数据之前先把总线拉低1us
i++;
DS18B20 = data & 0x01; //然后写入一个数据,从最低位开始
i=6;
while(i--); //延时68us,持续时间最少60us
DS18B20 = 1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
data >>= 1;
}
}
uchar Ds18b20ReadByte()
{
uchar byte, bi;
uint i, j;
for(j=8; j>0; j--)
{
DS18B20 = 0;//先将总线拉低1us
i++;
DS18B20 = 1;//然后释放总线
i++;
i++;//延时6us等待数据稳定
bi = DS18B20; //读取数据,从最低位开始读取
/*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/
byte = (byte >> 1) | (bi << 7);
i = 4; //读取完之后等待48us再接着读取下一个数
while(i--);
}
return byte;
}
void Ds18b20ChangeTemp()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc); //跳过ROM操作命令
Ds18b20WriteByte(0x44); //温度转换命令
}
void Ds18b20ReadTempCom()
{
Ds18b20Init();
Delay1ms(1);
Ds18b20WriteByte(0xcc); //跳过ROM操作命令
Ds18b20WriteByte(0xbe); //发送读取温度命令
}
int Ds18b20ReadTemp()
{
int temp = 0;
uchar tmh, tml;
Ds18b20ChangeTemp(); //先写入转换命令
Ds18b20ReadTempCom(); //然后等待转换完后发送读取温度命令
tml = Ds18b20ReadByte(); //读取温度值共16位,先读低字节
tmh = Ds18b20ReadByte(); //再读高字节
temp = tmh;
temp <<= 8;
temp |= tml;
return temp;
}
void Datapros()
{
float tp;
int temp=Ds18b20ReadTemp();
if(temp< 0) //当温度值为负数
{
//因为读取的温度是实际温度的补码,所以减1,再取反求出原码
temp=temp-1;
temp=~temp;
tp=temp;
temp=tp*0.0625*100+0.5;
//留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
//后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
//算加上0.5,还是在小数点后面。
}
else
{
tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量
//如果温度是正的那么,那么正数的原码就是补码它本身
temp=tp*0.0625*100+0.5;
}
ShowData[0] = temp % 10000 / 1000;
ShowData[0] = '0'+ShowData[0];
ShowData[1] = temp % 1000 / 100;
ShowData[1] = '0'+ShowData[1];
ShowData[2] = '.';
ShowData[3] = temp % 100 / 10;
ShowData[3] = '0'+ShowData[3];
ShowData[4] = temp % 10;
ShowData[4] = '0'+ShowData[4];
ShowData[5] = 'C';
}
LCD1602.h
#ifndef _LCD1602_H
#define _LCD1602_H
#include <reg52.h>
#include <stdio.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_DATAPINS P0
sbit RW=P2^5; //读写选择端
sbit RS=P2^6; //数据命令选择端
sbit E=P2^7; //使能端
void Delay_1ms(uint i);
void LcdWriteCom(uchar com);
void LcdWriteData(uchar dat);
void LcdInit();
void LcdShow(uchar ShowData[],int ShowSize);
#endif
LCD1602.c
#include "LCD1602.h"
void Delay_1ms(uint i) //延时,误差 0us
{
uchar j;
for (; i>0; i--)
for (j=200;j>0;j--);
}
void LcdWriteCom(uchar com) //写入命令
{
E = 0; //使能
RS = 0; //选择发送命令
RW = 0; //选择写入
LCD1602_DATAPINS = com; //放入命令
Delay_1ms(1); //等待数据稳定
E = 1; //写入时序
Delay_1ms(5); //保持时间
E = 0;
}
void LcdWriteData(uchar dat) //写入数据
{
E = 0; //使能清零
RS = 1; //选择输入数据
RW = 0; //选择写
LCD1602_DATAPINS = dat; //写入数
Delay_1ms(1);
E = 1; //写入时序
Delay_1ms(5); //保持时间
E = 0;
}
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //开显示
LcdWriteCom(0x0f); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
void LcdShow(uchar ShowData[],int ShowSize)
{
uchar i=0;
for(;i<ShowSize;i++)
{
LcdWriteData(ShowData[i]);
}
}
main.c
#include "DS18B20.h"
#include "LCD1602.h"
void main()
{
LcdInit();
LcdWriteCom(0x0C); //不显示光标
while(1)
{
Datapros();
LcdWriteCom(0x80); //设置数据指针起点
LcdShow(ShowData,sizeof(ShowData));
}
}