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 intsbit 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~960usi = 70; while(i--);//延时642usDS18B20 = 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; //每写入一位数据之前先把总线拉低1usi++;DS18B20 = data & 0x01; //然后写入一个数据,从最低位开始i=6;while(i--); //延时68us,持续时间最少60usDS18B20 = 1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值data >>= 1;}
}uchar Ds18b20ReadByte()
{uchar byte, bi;uint i, j; for(j=8; j>0; j--){DS18B20 = 0;//先将总线拉低1usi++;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 P0sbit 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); //写一个指针加1LcdWriteCom(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)); }
}