目录
一、学习目标
1、学习单总线温度传感器DB18B20的原理和通信时序;
2、使用51单片机的一个 IO 口模拟单总线时序与温度传感器DS18B20通信,将检测的环境温度读取出来。
二、单总线温度传感器DS18B20
2.1 单总线
单总线只有一条数据输入/输出线DQ,总线上所有器件都挂在DQ上,电源也通过这条信号线供给。
单总线系统中配置的各种器件,由DALLAS公司提供的专用芯片实现。每个芯片都有64位ROM,厂家对每一芯片都用激光烧写编码,其中存有16位十进制编码序列号,它是器件的地址编号,确保它挂在总线上后,可以唯一被确定。除了器件的地址编码外,芯片内还包含收发控制和电源存储电路,见图11-1。这些芯片耗电量都很小(空闲时几µW,工作时几mW),工作时从总线上馈送电能到大电容中就可以工作,故一般不需另加电源。
单总线芯片内部结构示意图
2.2 单总线温度传感器DS18B20
2.2.1 简介
1)数字温度传感器 DS18B20
DS18B20是一款常用的高精度的单总线数字温度测量芯片。具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
2)传感器引脚原理图
DS18B20传感器的引脚及封装图如下:
DS18B20一共有三个引脚,分别是:
- GND:电源地线
- DQ:数字信号输入/输出端。
- VDD:外接供电电源输入端。
3)单总线串行扩展
DS18B20是美国DALLAS公司生产的数字温度传感器,体积小、低功耗、抗干扰能力强。可直接将温度转化成数字信号传送给单片机处理,因而可省去传统的信号放大、A/D转换等外围电路。
单总线构成的分布式温度检测系统
如图所示为单片机与多个带有单总线接口的DS18B20组成的分布式温度测量系统,图中多个DS18B20都挂接在单片机的1根I/O口线(即DQ线)上。单片机对每个DS18B20都通过总线DQ寻址。DQ为漏极开路,须加上拉电阻。DS18B20的一种封装形式如上图右边所示。除DS18B20外,在该数字温度传感器系列中还有DS1820、DS18S20、DS1822等其他型号,工作原理与特性基本相同。
片内有9个字节的高速暂存器RAM单元,9个字节具体分布如下:
第1字节和第2字节是在单片机发给DS18B20温度转换命令发布后,经转换所得的温度值,以两字节补码形式存放其中。一般情况下,用户多使用第1字节和第2字节。单片机通过单总线可读得该数据,读取时低位在前,高位在后。
第3、4字节分别是由软件写入用户报警的上下限值TH和TL。
第5个字节为配置寄存器,可对其更改DS18B20的测温分辨率,高速暂存器的第6、7、8字节未用,为全1。第9字节是前面所有8个字节的CRC码,用来保证正确通信。片内还有1个E2PROM为TH、TL以及配置寄存器的映像。
配置寄存器各位的定义如下:
其中,TM位出厂时已被写入0,用户不能改变;低5位都为1;R1和R0用来设置分辨率。表10-1列出了R1、R0与分辨率和转换时间的关系。用户可通过修改R1、R0位的编码,获得合适的分辨率。
由表10-1,DS18B20转换时间与分辨率有关。当设定为9位时,转换时间为93.75ms;设定10位时,转换时间为187.5 ms;当设定11位时,转换时间为375ms;当设定为12位时,转换时间为750ms。
表10-2列出了DS18B20温度转换后所得到的16位转换结果的典型值。
4)温度转换
下面介绍温度转换的计算方法:
当DS18B20采集的温度为+125℃时,输出为0x07d0,则:
实际温度=(0x07d0)/16=(0×163+7×162+13×161+0×160)/16=125℃
当DS18B20采集的温度为-55℃时,输出为0xfc90,由于是补码,则先将11位数据取反加1得0x0370,注意符号位不变,也不参加运算,则
实际温度=(0x0370)/16=(0×163+3×162+7×161+0×160)/16=55℃
注意,负号则需对采集的温度进行判断后,再予以显示。
2.2.2 DS18B20的工作时序
工作时序要求严格,延时时间需准确,否则容易出错。
DS18B20的工作时序包括初始化时序、写时序和读时序。
(1)初始化时序
单片机将数据线电平拉低480~960µs后释放,等待15~60µs,单总线器件即可输出一持续60~240µs的低电平,单片机收到此应答后即可进行操作。
初始化具体时序步骤如下:
1.单片机拉低总线至少480us,产生复位脉冲,然后释放总线(拉高电平)。
2.这时DS8B20检测到请求之后,会拉低信号,大约60~240us表示应答。
3.DS8B20拉低电平的60~240us之间,单片机读取总线的电平,如果是低电平,那么表示初始化成功。
4.DS18B20拉低电平60~240us之后,会释放总线。
代码如下:
unsigned int Init_DS18B20(void)
{
unsigned int x=0;
DQ = 1; //DQ复位
delay(4); //稍做延时
DQ = 0; //单片机将DQ拉低
delay(60); //精确延时,大于480us
DQ = 1; //拉高总线
delay(8);
x = DQ; //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
delay(4);
return x;
}
(2)写时序
总线控制器通过控制单总线高低电平持续时间从而把逻辑1或0写DS18B20中。每次只传输1位数据
单片机想要给DS18B20写入一个0时,需要将单片机引脚拉低,保持低电平时间要在60~120us之间,然后释放总线
单片机想要给DS18B20写入一个1时,需要将单片机引脚拉低,拉低时间需要大于1us,然后在15us内拉高总线.
在写时序起始后15μs到60μs期间,DS18B20处于采样单总线电平状态。如果在此期间总线为高电平,则向DS18B20写入1;如果总线为低电平,则向DSl8B20写入0。
注意:2次写周期之间至少间隔1us
代码如下:
void WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01; //与1按位与运算,dat最低位为1时DQ总线为1,dat最低位为0时DQ总线为0
delay(4);
DQ = 1;
dat>>=1;
}
delay(4);
}
(3)读时序
读时隙由主机拉低总线电平至少1μs然后再释放总线,读取DS18B20发送过来的1或者0
DS18B20在检测到总线被拉低1微秒后,便开始送出数据,若是要送出0就把总线拉为低电平直到读周期结束。若要送出1则释放总线为高电平。
注意:所有读时隙必须至少需要60us,且在两次独立的时隙之间至少需要1ps的恢复时间
同时注意:主机只有在发送读暂存器命令(0xBE)或读电源类型命令(0xB4)后,立即生成读时隙指令,DS18B20才能向主机传送数据。 也就是先发读取指令,再发送读时隙
最后一点: 写时序注意是先写命令的低字节,比如写入跳过ROM指令0xCC(11001100),写的顺序是“零、零、壹、壹、零、零、壹、壹”,
读时序时是先读低字节,在读高字节,也就是先读取高速暂存器的第0个字节(温度的低8位),在读取高速暂存器的第1个字节(温度的高8位) 我们正常使用DS18B20读取温度读取两个温度字节即可。
代码如下:
uchar readbyte(void) //函数功能:读取1字节数据
{
uchar i=0;
uchar date=0;
for (i=8;i>0;i--)
{
DQ =0;
delay5(1);
DQ =1; //15µs内拉释放总线
date>>=1;
if(DQ)
date|=0x80;
delay5(11);
}
return(date);
}
2.3 DS18B20的环境温度采集
利用DS18B20和LED数码管实现单总线温度测量系统。DS18B20测量范围是−55~128℃。本例只显示00~99。通过本例我们应掌握DS18B20特性及单片机I/O实现单总线协议的方法。
Proteus仿真时,用手动,即用鼠标单击DS18B20图标上的“↑”或“↓”来改变温度,注意手动调节温度同时,LED数码管会显示出与DS18B20窗口相同的2位温度数值。
电路中74LS47是BCD-7段译码器/驱动器,用于将单片机P0口输出欲显示的BCD码转化成相应的数字显示的段码,并直接驱动LED数码管显示。
原理图
代码
#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define out P0
sbit smg1=out^4;
sbit smg2=out^5;
sbit DQ=P3^7;
void delay5(uchar);
void init_ds18b20(void);
uchar readbyte(void);
void writebyte(uchar);
uchar retemp(void);
void main(void) //主函数
{
uchar i,temp;
delay5(1000);
while(1)
{
temp=retemp();
for(i=0;i<10;i++) //连续扫描数码管10次
{
out=(temp/10)&0x0f;
smg1=0;
smg2=1;
delay5(1000); //延时5ms
out=(temp%10)&0x0f;
smg1=1;
smg2=0;
delay5(1000); //延时5ms
}
}
}
void delay5(uchar n) //函数功能:延时5µs
{
do
{
_nop_();
_nop_();
_nop_();
n--;
}
while(n);
}
void init_ds18b20(void) //函数功能:18B20初始化
{
uchar x=0;
DQ =0;
delay5(120);
DQ =1;
delay5(16);
delay5(80);
}
uchar readbyte(void) //函数功能:读取1字节数据
{
uchar i=0;
uchar date=0;
for (i=8;i>0;i--)
{
DQ =0;
delay5(1);
DQ =1; //15µs内拉释放总线
date>>=1;
if(DQ)
date|=0x80;
delay5(11);
}
return(date);
}
void writebyte(uchar dat) //函数功能:写1字节
{
uchar i=0;
for(i=8;i>0;i--)
{
DQ =0;
DQ =dat&0x01; //写"1" 在15µs内拉低
delay5(12); //写"0" 拉低60µs
DQ = 1;
dat>>=1;
delay5(5);
}
}
uchar retemp(void) //函数功能:读取温度
{
uchar a,b,tt;
uint t;
init_ds18b20();
writebyte(0xCC);
writebyte(0x44);
init_ds18b20();
writebyte(0xCC);
writebyte(0xBE);
a=readbyte();
b=readbyte();
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
return(tt);
}
仿真验证
2.4 keil虚拟逻辑分析仪分析显示波形
通过对波形的观察,此程序符合技术要求。
当我们故意在代码中把时序弄错(改延时delay的延时值),再重新运行之前的实验,观察到DS18B20不能正确返回相应的温度。
三、总结
通过学习DS18B20单总线温度采集,我对51单片机的应用有了进一步的了解。在学习过程中,首先了解到了DS18B20的基本原理,DS18B20只需要一根数据线即可实现与单片机的通信,也学习了如何将DS18B20与51单片机连接,同时学到了一些读取温度的编程。通过温度采集的编写,让我认识到编程实践的重要性,理论只有通过实践才能进一步掌握。文章多有不足,请大家多多指正!
参考博客:https://blog.csdn.net/as480133937/article/details/112604303