ds18b20详解及程序
DS18B20原理及程序编写

DS18B20原理及程序编写(一)概述DS18B20为单总线12位(二进制)温度读数。
内部有64位唯一的ID编码。
工作电压从3.0~5.5V。
测量温度范围从-55℃~125℃。
最高±0.0625℃分辩率。
其内部结构如下图所示。
DS18B20的核心功能是直接数字温度传感器。
温度传感器可以配置成9、10、11和12位方式。
相应的精度分别为:0.5℃、0.25℃、0.125℃和0.0625℃。
默认的分辨率为12位。
DS18B20在空闲低功耗状态下加电(寄生电源工作方式)。
主机必须发出Convert T [44h]命令使其对测量温度进行A-D转换。
接下来进行采集转换,结果存于两字节高速温度寄存器并返回到空闲低功耗状态。
如果DS18B20在外部VDD供电方式下,单片机可以在发出Convert T 命令并总线为1时(总线为0表示正在转换)发出“read time slots”命令。
DS18B20芯片内部共有8字节的寄存器,其中地址编号0,1为温度寄存器,里面存储着DS18B20温度转换后的AD值,其格式如表1所示。
地址编号2,3为温度报警寄存器,里面为报警设定值,地址编号4为配置寄存器(这三个寄存器在读取之前请使用“重新调入EEPROM”命令将存储在EEPROM里的内容调出,同样,在向温度报警寄存器里写入内容后,也要使用“复制到存储器”命令48H将温度报警寄存器内的内容存入EEPROM当中,以免掉电丢失数据)。
DS18B20内部寄存器映射如下图所示。
配置寄存器的格式如表2和表3所示。
DS18B20内部寄存器映射表1 温度寄存器的格式表2 配置寄存器的格式表3 温度分辨率配置DS18B20使用单总线工作方式,其通信协议以电平的高平时间作为依据,其基本时序有复位时序,写时序、读时序。
//********************************************************************** //** 文件名:DS18B20.c//** 说明:DS18B20驱动程序文件//----------------------------------------------------------------------//** 单位://** 创建人:张雅//** 创建时间:2010-01-20//** 联系方式:QQ:276564402//** 版本:V1.0//----------------------------------------------------------------------//**********************************************************************//----------------------------------------------------------------------//** 芯片:AT89S52//** 时钟:11.0592MHz//** 其它:这个文档为18B20的驱动程序,引用了数码管的驱动。
(完整版)读取DS18B20温度传感器的64位ID号方法及程序

#include <reg52.h>#define uchar unsigned char#define uint unsigned int/********************************************************************/ sbit DQ = P2^2; //温度传感器信号线sbit rs = P3^5; //LCD数据/命令选择端(H/L)位声明sbit lcden = P3^4; //LCD使能信号端位声明/********************************************************************/ //uint temp; //定义整型的温度数据//float f_temp; //定义浮点型的温度数据//uint warn_11 = 270; //定义温度设定值,是温度值乘以10后的结果//uint warn_12 = 250; //定义温度下限值//uint warn_h1 = 300; //定义温度上限值/********************************************************************/ void delay(uint z); //延时函数void DS18B20_Reset(void); //DQ18B20复位,初始化函数bit DS18B20_Readbit(void); //读1位数据函数uchar DS18B20_ReadByte(void); //读1个字节数据函数void DS18B20_WriteByte(uchar dat); //向DQ18B20写一个字节数据函数void LCD_WriteCom(uchar com); //1602液晶命令写入函数void LCD_WriteData(uchar dat); //1602液晶数据写入函数void LCD_Init(); //LCD初始化函数void Display18B20Rom(char Rom); //显示18B20序列号函数/**********************************************//* 主函数 *//**********************************************/void main(){ uchar a,b,c,d,e,f,g,h;LCD_Init();DS18B20_Reset();delay(1);DS18B20_WriteByte(0x33);delay(1);a = DS18B20_ReadByte();b = DS18B20_ReadByte();c = DS18B20_ReadByte();d = DS18B20_ReadByte();e = DS18B20_ReadByte();f = DS18B20_ReadByte();g = DS18B20_ReadByte();h = DS18B20_ReadByte();LCD_WriteCom(0x80+0x40);Display18B20Rom(h);Display18B20Rom(g);Display18B20Rom(f);Display18B20Rom(e);Display18B20Rom(d);Display18B20Rom(c);Display18B20Rom(b);Display18B20Rom(a);while(1);}/***************************************************//* 延时函数:void delay() *//* 功能:延时函数 *//***************************************************/void delay(uint z)//延时函数{uint x,y;for( x = z; x > 0; x-- )for( y = 110; y > 0; y-- );}/***************************************************//* DS18B20函数:void DS18B20_Reset() *//* 功能:复位18B20 */ /***************************************************/void DS18B20_Reset(void)//DQ18B20复位,初始化函数{uint i;DQ = 0;i = 103;while( i > 0 ) i--;DQ = 1;i = 4;while( i > 0 ) i--;}/***************************************************//* DS18B20函数:void DS18B20_Readbit() *//* 功能:读1个字节数据函数 *//***************************************************/bit DS18B20_Readbit(void) //读1位数据函数{uint i;bit dat;DQ = 0;i++; //i++起延时作用DQ = 1;i++;i++;dat = DQ;i = 8;while( i > 0 )i--;return( dat );}/***************************************************//* DS18B20函数:void DS18B20_ReadByte() *//* 功能:读1个字节数据函数 */ /***************************************************/uchar DS18B20_ReadByte(void) //读1个字节数据函数{uchar i,j,dat;dat = 0;for( i = 1; i <= 8; i++ ){j = DS18B20_Readbit();dat = ( j << 7 ) | ( dat >> 1 );}return(dat);}/***************************************************//* DS18B20函数:void DS18B20_WriteByte() *//* 功能:向DQ18B20写一个字节数据函数 *//***************************************************/void DS18B20_WriteByte(uchar dat) //向DQ18B20写一个字节数据函数{uint i;uchar j;bit testb;for( j=1; j<=8; j++){testb = dat&0x01;dat= dat>>1;if(testb) //写1{DQ = 0;i++;i++;DQ = 1;i = 8;while(i>0)i--;}else{DQ = 0; //写0i = 8;while(i>0)i--;DQ = 1;i++;i++;}}}/***********************************************//* LCD函数:void LCD_WriteCom() *//* 功能:向LCD写入命令 *//***********************************************/void LCD_WriteCom(uchar com){rs = 0;P0 = com;delay(5);lcden = 0;delay(5);lcden = 1;delay(5);lcden = 0;}/***********************************************//* LCD函数:void LCD_WriteData(uchar dat) *//* 功能:向LCD写入数据 *//***********************************************/void LCD_WriteData(uchar dat){rs = 1; //选择LCD为写入数据状态lcden = 0;P0 = dat; //将待写入数据放到总线上delay(5);lcden = 1; //给LCD使能端一个脉冲delay(5); //信号将之前放到总线上lcden = 0; //的数据写入LCDdelay(5);}/***********************************************//* LCD函数:void LCD_Init() */ /* 功能:初始化LCD,设定LCD的初始状态 *//***********************************************/void LCD_Init(){LCD_WriteCom(0x38); //LCD显示模式设定delay(15);LCD_WriteCom(0x08); //关闭LCD显示delay(3);LCD_WriteCom(0x01); //LCD显示清屏delay(3);LCD_WriteCom(0x06); //设定光标地址指针为自动加1delay(3);LCD_WriteCom(0x0c); //打开LCD显示,但不显示光标}/**********************************************//* */ /* 显示18B20序列号 *//* *//**********************************************/void Display18B20Rom(char Rom){uchar h,l;l = Rom & 0x0f; //取低4位h = Rom & 0xf0; //取高4位h >>= 4;if( ( h >= 0x00 )&&( h <= 0x09 ) )LCD_WriteData(h+0x30); //取ASCII码elseLCD_WriteData(h+0x37); //取ASCII码if( ( l >= 0x00 )&&( l <= 0x09 ) )LCD_WriteData(l+0x30); //取ASCII码elseLCD_WriteData(l+0x37); //取ASCII码}。
DS18B20智能温度控制器(附软件程序)

DS18B20智能温度控制器DALLAS最新单线数字温度传感器DS18B20简介新的“一线器件”体积更小、适用电压更宽、更经济 Dallas 半导体公司的数字化温度传感器DS1820是世界上第一片支持“一线总线”接口的温度传感器。
一线总线独特而且经济的特点,使用户可轻松地组建传感器网络,为测量系统的构建引入全新概念。
DS18B20、 DS1822 “一线总线”数字化温度传感器同DS1820一样,DS18B20也支持“一线总线”接口,测量温度范围为 -55°C~+125°C,在-10~+85°C范围内,精度为±0.5°C。
DS1822的精度较差为± 2°C 。
现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。
适合于恶劣环境的现场温度测量,如:环境控制、设备或过程控制、测温类消费电子产品等。
与前一代产品不同,新的产品支持3V~5.5V 的电压范围,使系统设计更灵活、方便。
而且新一代产品更便宜,体积更小。
DS18B20、 DS1822 的特性 DS18B20可以程序设定9~12位的分辨率,精度为±0.5°C。
可选更小的封装方式,更宽的电压适用范围。
分辨率设定,及用户设定的报警温度存储在EEPROM中,掉电后依然保存。
DS18B20的性能是新一代产品中最好的!性能价格比也非常出色! DS1822与 DS18B20软件兼容,是DS18B20的简化版本。
省略了存储用户定义报警温度、分辨率参数的EEPROM,精度降低为±2°C,适用于对性能要求不高,成本控制严格的应用,是经济型产品。
继“一线总线”的早期产品后,DS1820开辟了温度传感器技术的新概念。
DS18B20和DS1822使电压、特性及封装有更多的选择,让我们可以构建适合自己的经济的测温系统。
DS18B20的内部结构DS18B20内部结构主要由四部分组成:64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
DS18B20温度传感器详细注解及驱动程序解析

DS18B20独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条线即可实现微处理器与DS18B20的双向通讯。
测温范围-55℃~+125℃,固有测温误差(注意,不是分辨率,这里之前是错误的)1℃。
支持多点组网功能,多个DS18B20可以并联在唯一的三线上,最多只能并联8个,实现多点测温,如果数量过多,会使供电电源电压过低,从而造成信号传输的不稳定。
工作电源:3.0~5.5V/DC(可以数据线寄生电源)在使用中不需要任何外围元件。
测量结果以9~12位数字量方式串行传送。
如果使用51单片机的话,那么中间那个引脚必须接上4.7K~10K的上拉电阻,否则,由于高电平不能正常输入/输出,要么通电后立即显示85℃,要么用几个月后温度在85℃与正常值上乱跳。
根据DS18B20的通讯协议,主机(单片机)控制DS18B20完成温度转换必须经过三个步骤:每一次读写之前都要对DS18B20进行复位操作,复位成功后发送一条ROM指令,最后发送RAM指令,这样才能对DS18B20进行预定的操作。
读ROM 33H 读DS1820温度传感器ROM中的编码(即64位地址)发出此命令之后,接着发出64 位ROM 编码,访问单总线上与该编码相符合ROM 55H对应的DS1820 使之作出响应,为下一步对该DS1820 的读写作准备。
用于确定挂接在同一总线上DS1820 的个数和识别64 位ROM 地址。
为搜索ROM FOH操作各器件作好准备。
跳过ROM CCH 忽略64 位ROM 地址,直接向DS1820 发温度变换命令。
告警搜索ECH 执行后只有温度超过设定值上限或下限的片子才做出响应。
RAM命令启动DS1820进行温度转换,12位转换时最长为750ms(9位为93.75m温度变换44Hs)。
结果存入内部第0、1字节RAM中。
1、复位操作复位要求主CPU将数据线下拉500微秒,然后释放,当DS18B20收到信号后等待16~60微秒左右,后发出60~240微秒的存在低脉冲,主CPU收到此信号表示复位成功。
温度传感器DS18B20检测程序说明

DS18B20美国达拉斯公司生产的单总线协议的数字温度检测芯片,数据的写入与读取都在一根总线上进行操作,在总线上可以连接多个DS18B20,因为每个DS18B20都有唯一的光刻ROM序列号,所以可以进行ROM匹配,搜索指令进行选择相应的从机序列号。
编写DS18B20的检测程序主要包括:初始化函数(复位脉冲+存在脉冲),写数据函数,读取数据的函数。
对DS18B20的操作包括:初始化函数,ROM指令,RAM指令这三个部分。
接下来我先说一下这三个部分所对应的时序图的理解吧。
初始化:由于上拉电阻的存在,总线默认状态是高电平,接着主机将总线拉低,维持480us 到960us的时间,再接着就是释放总线,维持时间为15us到60us,接着就由从机发出一个低电平信号,将总线拉低,表示该DS18B20是正常地,或者说是存在的,其维持时间为60us 到240us。
上面一图是写入数据的时序图。
写时序:默认状态为高电平,先将总线拉低,至少维持1us 的延时时间,接着就往总线上进行写数据操作,接着DS18B20就开始采样数据了,整个过程时间为60us到120us。
下面一图是读取数据的时序图。
读时序:默认状态为高电平,先将总线拉低,接着在15us 之前,主机进行数据采样,其维持时间也为60us到120us。
下面是我在理解了DS18B20的原理之后所写的程序,调试成功了,且能实时读取外界温度的功能,这里是不读取小数部分的温度,只读取温度的正数值。
#include<reg52.h>#define uint unsigned int#define uchar unsigned charuchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};sbit DQ=P2^2;sbit duan=P2^6;sbit wei=P2^7;//是在11.0592M赫兹的频率下void delay_ms(uint t){uint i;for(;t>0;t--)for(i=110;i>0;i--);} //约为tms的延时程序void delay(uint x){while(x--);}void init_ds18b20(){uchar n;DQ=1;delay(2); //约为38usDQ=0;delay(80); //约为800usDQ=1;delay(4); //约为58usn=DQ;delay(10); //约为110us}void write_byte(uchar dat){uchar i;for(i=0;i<8;i++){DQ=0; //无论是写0或写1都要有至少1us的低电平DQ=dat&0x01;//总线直接等于写入的数据(低位在前,高位在后)delay(4); //约为58usDQ=1; //释放总线,为下一步的数据变换做准备dat>>=1;//数据进行移位操作}delay(4);}uchar read_byte(){uchar i,value;for(i=0;i<8;i++){DQ=0;value>>=1; //移位7次DQ=1; //先要释放总线,那样才能采样到有效数据if(DQ) //判断8次{value|=0x80;}delay(6); //约为78us}return value;}uchar read_temperature(){uchar a,b;init_ds18b20(); //每次操作指令前,都必须进行初始化设置write_byte(0xcc);//跳过ROM指令write_byte(0x44);//进行温度转换处理delay(300);//进行一定地延时约为3ms左右init_ds18b20();write_byte(0xcc);//跳过ROM操作write_byte(0xbe);//读取温度a=read_byte();//温度低字节b=read_byte();//温度高字节b<<=4;//b左移四位,低四位为0000b=b+(a&0xf0)>>4;//将a的低四位屏蔽,不取小数点,进行右移四位,合并成一个字节的数据return b;}void display(uchar aa,uchar bb) {duan=1;P0=table[aa];duan=0;P0=0xff;wei=1;P0=0xfe;wei=0;delay_ms(5);duan=1;P0=table[bb];duan=0;P0=0xff;wei=1;P0=0xfd;wei=0;delay_ms(5);}void main(){uchar num,shi,ge;while(1){num=read_temperature();shi=num/10; //分离出十位ge=num%10; //分离出个位display(shi,ge);}}。
DS18B20工作过程及时序

DS18B20工作过程及时序DS18B20内部的低温度系数振荡器是一个振荡频率随温度变化很小的振荡器,为计数器1提供一频率稳定的计数脉冲。
高温度系数振荡器是一个振荡频率对温度很敏感的振荡器,为计数器2提供一个频率随温度变化的计数脉冲。
初始时,温度寄存器被预置成-55℃,每当计数器1从预置数开始减计数到0时,温度寄存器中寄存的温度值就增加1℃,这个过程重复进行,直到计数器2计数到0时便停止。
初始时,计数器1预置的是与-55℃DS18B20工作过程及时序DS18B20内部的低温度系数振荡器是一个振荡频率随温度变化很小的振荡器,为计数器1提供一频率稳定的计数脉冲。
高温度系数振荡器是一个振荡频率对温度很敏感的振荡器,为计数器2提供一个频率随温度变化的计数脉冲。
初始时,温度寄存器被预置成-55℃,每当计数器1从预置数开始减计数到0时,温度寄存器中寄存的温度值就增加1℃,这个过程重复进行,直到计数器2计数到0时便停止。
初始时,计数器1预置的是与-55℃相对应的一个预置值。
以后计数器1每一个循环的预置数都由斜率累加器提供。
为了补偿振荡器温度特性的非线性性,斜率累加器提供的预置数也随温度相应变化。
计数器1的预置数也就是在给定温度处使温度寄存器寄存值增加1℃计数器所需要的计数个数。
DS18B20内部的比较器以四舍五入的量化方式确定温度寄存器的最低有效位。
在计数器2停止计数后,比较器将计数器1中的计数剩余值转换为温度值后与0.25℃进行比较,若低于0.25℃,温度寄存器的最低位就置0;若高于0.25℃,最低位就置1;若高于0.75℃时,温度寄存器的最低位就进位然后置0。
这样,经过比较后所得的温度寄存器的值就是最终读取的温度值了,其最后位代表0.5℃,四舍五入最大量化误差为±,即0.25℃。
温度寄存器中的温度值以9位数据格式表示,最高位为符号位,其余8位以二进制补码形式表示温度值。
测温结束时,这9位数据转存到暂存存储器的前两个字节中,符号位占用第一字节,8位温度数据占据第二字节。
DS18B20中文资料+C程序

DS18B20中文资料+C程序18b20温度传感器应用解析温度传感器的种类众多,在应用与高精度、高可靠性的场合时dallas(达拉斯)公司生产的ds18b20温度传感器当仁不让。
超小的体积,超低的硬件开消,抗干扰能力强,精度高,附加功能强,使得ds18b20更受欢迎。
对于我们普通的电子爱好者来说,ds18b20的优势更是我们学习单片机技术和开发温度相关的小产品的不二选择。
了解其工作原理和应用可以拓宽您对单片机开发的思路。
ds18b20的主要特征:全系列数字温度切换及输入。
??一流的单总线数据通信。
最高12位分辨率,精度可达土0.5摄氏度。
12十一位分辨率时的最小工作周期为750毫秒。
??可选择真菌工作方式。
检测温度范围为c55°c~+125°c(c67°f~+257°f)??内置eeprom,限温报警功能。
64十一位光刻rom,内置产品序列号,便利多机了变。
??多样PCB形式,适应环境相同硬件系统。
ds18b20芯片PCB结构:ds18b20引脚功能:gnd电压地dq单数据总线vdd电源电压nc空插槽ds18b20工作原理及应用领域:ds18b20的温度检测与数字数据输出全集成于一个芯片之上,从而抗干扰力更强。
其一个工作周期可分为两个部分,即温度检测和数据处理。
在讲解其工作流程之前我们有必要了解18b20的内部存储器资源。
18b20共有三种形态的存储器资源,它们分别是:rom只读存储器,用作放置ds18b20id编码,其前8位就是单线系列编码(ds18b20的编码就是19h),后面48位就是芯片唯一的序列号,最后8位就是以上56的位的crc码(缓存校验)。
数据在出产时设置无可奈何用户修改。
ds18b20共64十一位rom。
ram数据暂存器,用于内部计算和数据存取,数据在掉电后丢失,ds18b20共9个字节ram,每个字节为8位。
第1、2个字节是温度转换后的数据值信息,第3、4个字节是用户eeprom(常用于温度报警值储存)的镜像。
DS18B20温度传感器详解带c程序

case 0: if(zf==0) P1=numfh[zf];
else if(bai!=0) P1=numd[bai]; else if(shi!=0) P1=numd[shi]; else P1=numdg[ge]; break;
case 1: if(zf==0&&shi!=0) P1=numd[shi];
break; case 2: if(zf==0&&shi!=0)
//因为存在脉冲检测结束后自动拉高*/ //return stat; } /******************写一个字节函数****************/ void write_byte(uchar dat) { uchar i; DQ=1; //先拉高电平,为写作准备 for(i=0;i<8;i++) {
以 12 位转化为例说明温度高低字节存放形式(温度的存储形式如表 3.1)及计算:12 位转化后得到的 12
位数据,存储在 18B20 的两个高低 8 位的 RAM 中,二进制中的前面 5 位是符号位。如果测得的温度大于 0,
这 5 位为 0,只要将测到的数值乘于 0.0625 即可得到实际温度;如果温度小于 0,这 5 位为 1,测到的数值
配置寄存器
8位CRC生成器
内部结构图
2. 2 DS18B20 内部存储器及温度数据格式
对于 DS18B20 内部存储器结构(见下图),它包括一个暂存 RAM 和一个非易失性电可擦除 EERAM,后者存
放报警上下限 TH、TL。当改变 TH、T L 中的值时,数据首先被写进暂存器的第二、三字节中,主机可再读
表 3.2 DS18B20 温度/数字对应关系表
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
最近都在学习和写单片机的程序, 今天有空又模仿DS18B20温度测量显示实验写了一个与DS18B20基于单总线通信的程序.DS18B20 数字温度传感器(参考:智能温度传感器DS18B20的原理与应用)是DALLAS 公司生产的1-Wire,即单总线器件,具有线路简单,体积小的特点。
因此用它来组成一个测温系统,具有线路简单,在一根通信线,可以挂很多这样的数字温度计。
DS18B20 产品的特点:(1)、只要求一个I/O 口即可实现通信。
(2)、在DS18B20 中的每个器件上都有独一无二的序列号。
(3)、实际应用中不需要外部任何元器件即可实现测温。
(4)、测量温度范围在-55 到+125℃之间; 在-10 ~ +85℃范围内误差为±5℃; (5)、数字温度计的分辨率用户可以从9 位到12 位选择。
将12位的温度值转换为数字量所需时间不超过750ms;(6)、内部有温度上、下限告警设置。
DS18B20引脚分布图DS18B20 详细引脚功能描述:1、GND 地信号;2、DQ数据输入出引脚。
开漏单总线接口引脚。
当被用在寄生电源下,此引脚可以向器件提供电源;漏极开路, 常太下高电平. 通常要求外接一个约5kΩ的上拉电阻.3、VDD可选择的VDD 引脚。
电压范围:3~5.5V; 当工作于寄生电源时,此引脚必须接地。
DS18B20存储器结构图暂存储器的头两个字节为测得温度信息的低位和高位字节;第3, 4字节是TH和TL的易失性拷贝, 在每次电复位时都会被刷新;第5字节是配置寄存器的易失性拷贝, 同样在电复位时被刷新;第9字节是前面8个字节的CRC检验值.配置寄存器的命令内容如下:MSB LSBR0和R1是温度值分辨率位, 按下表进行配置.默认出厂设置是R1R0 = 11, 即12位.温度值分辨率配置表4种分辨率对应的温度分辨率为0.5℃, 0.25℃, 0.125℃, 0.0625℃(即最低一位代表的温度值)12位分辨率时的两个温度字节的具体格式如下:其中高字节前5位都是符号位S, 若分辨率低于12位时, 相应地使最低为0, 如: 当分辨, 高字节不变....一些温度与转换后输出的数字参照如下:由上表可看出, 当输出是负温度时, 使用补码表示, 方便计算机运算(若是用C语言, 直接将结果赋值给一个int变量即可).DS18B20 的使用方法:由于DS18B20 采用的是1-Wire 总线协议方式,即在一根数据线实现数据的双向传输,而对单片机来说,我们必须采用软件的方法来模拟单总线的协议时序来完成对DS18B20芯片的访问。
由于DS18B20是在一根I/O线上读写数据,因此,对读写的数据位有着严格的时序要求。
DS18B20有严格的通信协议来保证各位数据传输的正确性和完整性。
该协议定义了几种信号的时序:初始化时序(dsInit()实现)、读时序(readByte())、写时序(writeByte())。
所有时序都是将主机作为主设备,单总线器件作为从设备。
而每一次命令和数据的传输都是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需启动读时序完成数据接收。
数据和命令的传输都是低位在先。
DS18B20与单片机连接电路图:利用软件模拟DS18B20的单线协议和命令:主机操作DS18B20必须遵循下面的顺序1. 初始化单线总线上的所有操作都是从初始化开始的. 过程如下:1)请求: 主机通过拉低单线480us以上, 产生复位脉冲, 然后释放该线, 进入Rx接收模式. 主机释放总线时, 会产生一个上升沿脉冲.DQ : 1 -> 0(480us+) -> 12)响应: DS18B20检测到该上升沿后, 延时15~60us, 通过拉低总线60~240us来产生应答脉冲.DQ: 1(15~60us) -> 0(60~240us)3)接收响应: 主机接收到从机的应答脉冲后, 说明有单线器件在线. 至此, 初始化完成. DQ: 02. ROM操作命令当主机检测到应答脉冲, 便可发起ROM操作命令. 共有5类ROM操作命令, 如下表3. 内存操作命令在成功执行ROM操作命令后, 才可使用内存操作命令. 共有6种内存操作命令:4. 数据处理DS18B20要求有严格的时序来保证数据的完整性. 在单线DQ上, 有复位脉冲, 应答脉冲,写0, 写1, 读0, 读1这6种信号类型. 除了应答脉冲外, 其它都由主机产生. 数据位的读和写是通过读、写时隙实现的.1) 写时隙: 当主机将数据线从高电平拉至低电平时, 产生写时隙.所有写时隙都必须在60us以上, 各写时隙间必须保证1us的恢复时间.写"1" : 主机将数据线DQ先拉低, 然后释放15us后, 将数据线DQ拉高;写"0" : 主机将DQ拉低并至少保持60us以上.2)读时隙: 当主机将数据线DQ从高电平拉至低电平时, 产生读时隙. 所有读时隙最短必须持续60us, 各读时隙间必须保证1us的恢复时间.读: 主机将DQ拉低至少1us,. 此时主机马上将DQ拉高, 然后就可以延时15us后, 读取DQ即可.源代码: (测量范围: 0 ~ 99度)DS18B201#include <reg51.H>2//通过DS18B20测试当前环境温度, 并通过数码管显示当前温度值3sbit wela = P2^7; //数码管位选4sbit dula = P2^6; //数码管段选5sbit ds = P2^2;6//0-F数码管的编码(共阴极)7unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,8 0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};9//0-9数码管的编码(共阴极), 带小数点10unsigned char code tableWidthDot[]={0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 11 0x87, 0xff, 0xef};1213//延时函数, 例i=10,则大概延时10ms.14void delay(unsigned char i)15{16 unsigned char j, k;17for(j = i; j > 0; j--)18 {19for(k = 125; k > 0; k--);20 }21}2223//初始化DS18B2024//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动25void dsInit()26{27//一定要使用unsigned int型, 一个i++指令的时间, 作为与DS18B20通信的小时间间隔28 //以下都是一样使用unsigned int型30 ds = 0;31 i = 103;32while(i>0) i--;33 ds = 1;34 i = 4;35while(i>0) i--;36}3738//向DS18B20读取一位数据39//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平, 40//之后DS18B20则会输出持续一段时间的一位数据41bit readBit()42{43 unsigned int i;44 bit b;45 ds = 0;46 i++;47 ds = 1;48 i++; i++;49 b = ds;50 i = 8;51while(i>0) i--;52return b;53}5455//读取一字节数据, 通过调用readBit()来实现56unsigned char readByte()57{58 unsigned int i;59 unsigned char j, dat;60 dat = 0;61for(i=0; i<8; i++)62 {63 j = readBit();64//最先读出的是最低位数据65 dat = (j << 7) | (dat >> 1);66 }67return dat;68}6970//向DS18B20写入一字节数据71void writeByte(unsigned char dat)72{74 unsigned char j;75 bit b;76for(j = 0; j < 8; j++)77 {78 b = dat & 0x01;79 dat >>= 1;80//写"1", 让低电平持续2个小延时, 高电平持续8个小延时81if(b)82 {83 ds = 0;84 i++; i++;85 ds = 1;86 i = 8; while(i>0) i--;87 }88else//写"0", 让低电平持续8个小延时, 高电平持续2个小延时89 {90 ds = 0;91 i = 8; while(i>0) i--;92 ds = 1;93 i++; i++;94 }95 }96}9798//向DS18B20发送温度转换命令99void sendChangeCmd()100{101 dsInit(); //初始化DS18B20102 delay(1); //延时1ms103 writeByte(0xcc); //写入跳过序列号命令字104 writeByte(0x44); //写入温度转换命令字105}106107//向DS18B20发送读取数据命令108void sendReadCmd()109{110 dsInit();111 delay(1);112 writeByte(0xcc); //写入跳过序列号命令字113 writeByte(0xbe); //写入读取数据令字114}115116//获取当前温度值117unsigned int getTmpValue()118{119 unsigned int value; //存放温度数值120float t;121 unsigned char low, high;122 sendReadCmd();123//连续读取两个字节数据124 low = readByte();125 high = readByte();126//将高低两个字节合成一个整形变量127 value = high;128 value <<= 8;129 value |= low;130//DS18B20的精确度为0.0625度, 即读回数据的最低位代表0.0625度131 t = value * 0.0625;132//将它放大10倍, 使显示时可显示小数点后一位, 并对小数点后第二2进行4舍5入133 //如t=11.0625, 进行计数后, 得到value = 111, 即11.1 度134 value = t * 10 + 0.5;135return value;136}137138//显示当前温度值, 精确到小数点后一位139void display(unsigned int v)140{141 unsigned char count;142 unsigned char datas[] = {0, 0, 0};143 datas[0] = v / 100;144 datas[1] = v % 100 / 10;145 datas[2] = v % 10;146for(count = 0; count < 3; count++)147 {148//片选149 wela = 0;150 P0 = ((0xfe << count) | (0xfe >> (8 - count))); //选择第(count + 1) 个数码管151 wela = 1; //打开锁存, 给它一个下降沿量152 wela = 0;153//段选154 dula = 0;155if(count != 1)156 {157 P0 = table[datas[count]]; //显示数字158 }159else160 {161 P0 = tableWidthDot[datas[count]]; //显示带小数点数字162 }163 dula = 1; //打开锁存, 给它一个下降沿量164 dula = 0;165 delay(5); //延时5ms, 即亮5ms166167 //清除段先, 让数码管灭, 去除对下一位的影响, 去掉高位对低位重影168 //若想知道影响效果如何, 可自行去掉此段代码169 //因为数码管是共阴极的, 所有灭的代码为: 00H170 dula = 0;171 P0 = 0x00; //显示数字172 dula = 1; //打开锁存, 给它一个下降沿量173 dula = 0;174 }175}176177void main()178{179 unsigned char i;180 unsigned int value;181while(1)182 {183//启动温度转换184 sendChangeCmd();185 value = getTmpValue();186//显示3次187for(i = 0; i < 3; i++)188 {189 display(value);190 }191 }192}显示效果:流程图:改进代码: 扩大测量范围, 使可测量范围为: -55度~ +125度, 严格按照上面的流程进行软件设计3.15 1:34 修正display()函数中的下一位显示对上一位的影响改进代码1#include <reg51.H>2#include<intrins.h>3#include <math.H> //要用到取绝对值函数abs()4//通过DS18B20测试当前环境温度, 并通过数码管显示当前温度值, 目前显示范围: -55~ +125度5sbit wela = P2^7; //数码管位选6sbit dula = P2^6; //数码管段选7sbit ds = P2^2;8int tempValue;910//0-F数码管的编码(共阴极)11unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,12 0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};13//0-9数码管的编码(共阴极), 带小数点14unsigned char code tableWidthDot[]={0xbf, 0x86, 0xdb, 0xcf, 0xe6, 0xed, 0xfd, 15 0x87, 0xff, 0xef};1617//延时函数, 对于11.0592MHz时钟, 例i=10,则大概延时10ms.18void delay(unsigned int i)19{20 unsigned int j;21while(i--)22 {23for(j = 0; j < 125; j++);24 }25}2627//初始化DS18B2028//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动29void dsInit()30{31//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于为8us32 unsigned int i;33 ds = 0;34 i = 100; //拉低约800us, 符合协议要求的480us以上35while(i>0) i--;36 ds = 1; //产生一个上升沿, 进入等待应答状态37 i = 4;38while(i>0) i--;39}4041void dsWait()42{43 unsigned int i;44while(ds);45while(~ds); //检测到应答脉冲46 i = 4;47while(i > 0) i--;48}4950//向DS18B20读取一位数据51//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,52//之后DS18B20则会输出持续一段时间的一位数据53bit readBit()54{55 unsigned int i;56 bit b;57 ds = 0;58 i++; //延时约8us, 符合协议要求至少保持1us59 ds = 1;60 i++; i++; //延时约16us, 符合协议要求的至少延时15us以上61 b = ds;62 i = 8;63while(i>0) i--; //延时约64us, 符合读时隙不低于60us要求 64return b;65}6667//读取一字节数据, 通过调用readBit()来实现68unsigned char readByte()69{70 unsigned int i;71 unsigned char j, dat;72 dat = 0;73for(i=0; i<8; i++)74 {75 j = readBit();76//最先读出的是最低位数据77 dat = (j << 7) | (dat >> 1);78 }79return dat;80}8182//向DS18B20写入一字节数据83void writeByte(unsigned char dat)84{85 unsigned int i;86 unsigned char j;87 bit b;88for(j = 0; j < 8; j++)89 {90 b = dat & 0x01;91 dat >>= 1;92//写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写193if(b)94 {95 ds = 0;96 i++; i++; //拉低约16us, 符号要求15~60us内97 ds = 1;98 i = 8; while(i>0) i--; //延时约64us, 符合写时隙不低于60us要求99 }100else//写"0", 将DQ拉低60us~120us101 {102 ds = 0;103 i = 8; while(i>0) i--; //拉低约64us, 符号要求104 ds = 1;105 i++; i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了106 }107 }108}109110//向DS18B20发送温度转换命令111void sendChangeCmd()112{113 dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化114 dsWait(); //等待DS18B20应答115 delay(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号116 writeByte(0xcc); //写入跳过序列号命令字 Skip Rom117 writeByte(0x44); //写入温度转换命令字 Convert T118}119120//向DS18B20发送读取数据命令121void sendReadCmd()122{123 dsInit();124 dsWait();125 delay(1);126 writeByte(0xcc); //写入跳过序列号命令字 Skip Rom127 writeByte(0xbe); //写入读取数据令字 Read Scratchpad128}129130//获取当前温度值131int getTmpValue()132{133 unsigned int tmpvalue;134int value; //存放温度数值135float t;136 unsigned char low, high;137 sendReadCmd();138//连续读取两个字节数据139 low = readByte();140 high = readByte();141//将高低两个字节合成一个整形变量142 //计算机中对于负数是利用补码来表示的143 //若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的value144 tmpvalue = high;145 tmpvalue <<= 8;146 tmpvalue |= low;147 value = tmpvalue;148149//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度150 t = value * 0.0625;151//将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入152 //如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度153 //如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度154 value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5 155return value;156}157158unsigned char const timeCount = 3; //动态扫描的时间间隔159//显示当前温度值, 精确到小数点后一位160//若先位选再段选, 由于IO口默认输出高电平, 所以当先位选会使数码管出现乱码161void display(int v)162{163 unsigned char count;164 unsigned char datas[] = {0, 0, 0, 0, 0};165 unsigned int tmp = abs(v);166 datas[0] = tmp / 10000;167 datas[1] = tmp % 10000 / 1000;168 datas[2] = tmp % 1000 / 100;169 datas[3] = tmp % 100 / 10;170 datas[4] = tmp % 10;171if(v < 0)172 {173//关位选, 去除对上一位的影响174 P0 = 0xff;175 wela = 1; //打开锁存, 给它一个下降沿量176 wela = 0;177//段选178 P0 = 0x40; //显示"-"号179 dula = 1; //打开锁存, 给它一个下降沿量180 dula = 0;181182//位选183 P0 = 0xfe;184 wela = 1; //打开锁存, 给它一个下降沿量185 wela = 0;186 delay(timeCount);187 }188for(count = 0; count != 5; count++)189 {190//关位选, 去除对上一位的影响191 P0 = 0xff;192 wela = 1; //打开锁存, 给它一个下降沿量193 wela = 0;194//段选195if(count != 2)196 {197/* if((count == 0 && datas[count] == 0)198 || ((count == 1 && datas[count] == 0) && (count == 0 && data s[count - 1] == 0)))199 {200 P0 = 0x00; //当最高位为0时, 不作显示201 }202 else*/203 P0 = table[datas[count]]; //显示数字204 }205else206 {207 P0 = tableWidthDot[datas[count]]; //显示带小数点数字208 }209 dula = 1; //打开锁存, 给它一个下降沿量210 dula = 0;211212//位选213 P0 = _crol_(0xfd, count); //选择第(count + 1) 个数码管214 wela = 1; //打开锁存, 给它一个下降沿量215 wela = 0;216 delay(timeCount);217 }218}219220void main()221{222 unsigned char i;223224while(1)225 {226//启动温度转换227 sendChangeCmd();228//显示5次229for(i = 0; i < 40; i++)230 {231 display(tempValue);232 }233 tempValue = getTmpValue(); 234 }235}改进后的效果图:只有一位小数两位小数, 并消除下一位对上一位的影响。