DS18B20是一种数字温度传感器,常用于温度监测、控制等领域。
它有三个脚,如图所示
DQ是信号线,经过4.7K上拉电阻(当连接的单片机io口不能确定电平的时候,DQ将走4.7K这条路,达到+5V)接到+5v ;
单总线时序:一根线来传输信号,因此要求比较严格,所有的信号(由0和1组成的一串按照规定高低变化的电平,相当于打一套拳,一下高一下低我们称为时序)都在这上面传达:例如复位,写0,写1,读0,读1
因此,在通信前,需要进行初始化操作。(想详细了解一个元件的使用,需要下载它的数据手册有详细介绍)
上图是它的内部结构,看不懂没关系不影响使用。64位的ROM相当于可以存放它们的身份证号,以便于在一条线上连接多个DS18B20
暂存器是RAM寄存器(图里面看),就是相当于一个可以存放数据的小房子。
接下来我们来看如何通过特定操作来实现这套时序的打法:
粗黑线表示单片机的动作:
浅灰线表示从机(DS18B20)的动作:
戏黑线表示上拉电阻的动作:
初始化:
1.发出一个至少480us的低电平脉冲(常取600us)
2.释放总线变为高电平,持续时间为15u~60us(常取60us)
3.若有低电平出现则说明总线上有器件做出应答,将总线电平拉低60~240us, 告知主机器件已经做好准备
4.若没有检测到则一直在检测,停止等待。
uchar DS18B20_Init()
{
bit ackset;
DS18B20_IO = 0;
delay_us(600);
DS18B20_IO = 1;
delay_us(60);
ackset = DS18B20_IO;
while(!DS18B20_IO);
return ackset;
}
写0和写1:
1.单片机直接将引脚拉低
2.写1的时候,单片机先将这个引脚拉低,拉低时间大于 1us,然后马上释放总线,DS18B20 会在15us 到 60us 之间来读取这个被上拉电阻拉高的 1。
3.写0的时候,单片机先将这个引脚拉低,然后马上释放总线,DS18B20 会在15us 到 60us 之间来读取这个仍然被主机置 的0。
void DS18B20_WriteByte(uchar dat)//定义一个函数,有个形参dat:代表单片机往DS1302要写入的数据
这里是写字节,1字节Byte是8bit (8个01比特)
{
uchar detect;//辅助变量
for(detect = 0x01;detect !=0; detect <<1)//循环左移,判断detect不是0就继续,为0停止,来八次
{
DS18B20_IO = 0;//先拉低
_nop_();_nop_();//_nop_: 51单片机中封装好的函数,相当于机器执行一条指令的时间,用于延时,在晶振为12MHz时候大约1us 需包含 #include “intrins.h” 间隔2us
if((detect&dat)==0)
DS18B20_IO = 0;
else
DS18B20_IO = 1;
delay_us(60);//等待它采集存入
DS18B20_IO = 1;
}
}
1.例如想写入dat:10101101
最低位相与(&)然后判断是否为0,发现写的不是0,执行else IO置1;
倒数第2位相与(&)然后判断是否为0,发现是0,执行IO置0;
2.延时60us,让从机采集数据存入自己的房间
3.最后io口置1,回到初始的默认拉高状态,预备下一次操作
读0和读1:
1.单片机首先要拉低引脚
2.至少保持1us 的时间,然后释放引脚
3.从拉低这个引脚到读取引脚状态,不能超过 15us。先读低位,再读高位!
留给大家思考
uchar DS18B20_ReadByte()
{
uchar udat,detect;
for(detect = 0x01;detect!=0;detect<<=1)
{
DS18B20_IO = 0;
_nop_();_nop_();
DS18B20_IO = 1;
_nop_();_nop_();
if(DS18B20_IO)
{
udat = udat|detect;
}
else
{
udat = udat&(~detect);
}
delay_us(60);
}
return udat;
}
初始化,读,写三个强大的武器被我们制作好啦!!!
接下来就是利用上面的武器进行作战了!
第一步:初始化;
第二步:发出跳过ROM匹配指令【CCH】;(当总线上只有一个器件的时候,可以跳过ROM,不进行ROM检测,不用查身份证,因为只有一个人)
第三步:发出温度转换命令【44H】;
第四步:初始化;
第五步:发出跳过ROM匹配指令【CCH】;
第六步:发出读暂存器命令【BEH】;
第七步:读取RAM暂存器中的前两个字节,分别为低字节和高字节。
指令类型 | 指令 | 功能 | 详细描述 |
ROM指令 | [CCH] | 忽略ROM指令 | 允许总线控制器不用提供ROM编码就能使用该功能 |
功能指令 | [44H] | 温度转换指令 | 用来控制DS18B20启动一次温度转换,生成的数据以2字节形式存储在高速暂存器中 |
[BEH] | 读暂存器指令 | 读取DS18B20暂存器数据,读取将从0字节开始到第8字节结束。 |
此处的低位高位就是用来存放DS18B20将温度转换成二进制数值。
byte4:用来设置温度精度,测量温度也需要有最小单位,像一把尺子,最小刻度可以是1mm,1cm。实际只需要操作bit6和bit5,排列组合有四种精度和最大转换时间可供选择。
注意看高位的前5bit 是s(五个1为负),代表符号位(可以表示正负温度)
低位的bit4是个位,bit5是十位,bit3是小数。以此类推:最低四位表小数
上电默认精度就是0.0625℃
也就是
0000 0000 0000 0000 表示0℃
0000 0000 0000 0001 表示0.0625℃ 2的-4次方, 注意:本来按照计算机中的存放规则,最低位是2的0次方,这里面的寄存器为了表示小数,将2的0次方向左👈挪动了四位(扩大了16倍,每向左挪一位就相当于乘2)
写程序啦:
//DS18B20指令 见上面的图,先给大家取个名字
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE
void DS18B20_ConvertT(void)
{
OneWire_Init();//初始化
OneWire_SendByte(DS18B20_SKIP_ROM);//忽略查验大家的身份证,只有一个从机
OneWire_SendByte(DS18B20_CONVERT_T);//开始温度转换
}
float DS18B20_ReadT(void)//定义一个返回值类型是浮点数(带小数点的)的函数
{
unsigned char TLSB,TMSB;//定义无符号是2个变量,每个变量一个字节(8bit)
int Temp;//定义有符号数整形变量,两个字节16位
float T;
DS18B20_Init();//初始化
DS18B20_ReadByte(DS18B20_SKIP_ROM);
DS18B20_WirteByte(DS18B20_READ_SCRATCHPAD);
TLSB=DS18B20_ReadByte();//读取,放入TLSB
TMSB=DS18B20_ReadByte();//读取,放入TLSB
Temp=(TMSB<<8)|TLSB;//强制类型转换后,高位左移8位,低位放进低8位两个数拼在一起
T=Temp/16.0;//跟实际相比大了十六倍,给他还原,同时带小数点,不让他丢失精度
return T;//返回这个浮点温度值
}
这个返回的T就可以送去显示啦,大功告成!
显示可以用LCD1602;数码管;OLED,以后逐一介绍哦
还可以通过串口发送给电脑哦
还可以通过无线模块传输哦
十分有趣!