ds18b20详解及程序
- 格式:doc
- 大小:658.50 KB
- 文档页数:17
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的驱动程序,引用了数码管的驱动。
#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智能温度控制器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的双向通讯。
测温范围-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都有唯一的光刻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内部的低温度系数振荡器是一个振荡频率随温度变化很小的振荡器,为计数器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程序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程序设计傻瓜式讲解
DS18B20 是一款数字温度传感器,可以直接读出被测温度,并采用 9 位数字量串行输出。
下面是一个简单的 DS18B20 程序设计讲解:
1. 初始化
在 DS18B20 通信过程中,首先需要初始化数据线,即将其置为高电平。
在初始化时,需要持续至少 480 微秒的高电平。
2. 跳过 ROM
在 DS18B20 中,每个传感器都有一个唯一的 ROM 序列号,可以通过跳过ROM 操作来避免对 ROM 进行操作。
具体操作是先发出一个低电平,然后持续至少 60 微秒的高电平。
3. 发送命令
在跳过 ROM 后,需要向传感器发送命令。
常用的命令有温度转换命令和读取温度命令。
温度转换命令是 0x44,读取温度命令是 0xBE。
4. 读取数据
在发送命令后,需要等待传感器响应。
传感器响应的标志是数据线上的低电平。
在低电平持续约 60-240 微秒后,数据线将变为高电平,此时可以开始读取数据。
每次读取一位数据后,需要将数据线置为低电平,等待传感器响应。
5. 数据解析
DS18B20 的数据由 9 位数字量组成,其中最高位是符号位。
如果最高位为0,则表示温度为正数;如果最高位为 1,则表示温度为负数。
其余 8 位为温度值,可以通过一定的计算公式将其转换为实际温度值。
以上就是 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检验值.配置寄存器的命令内容如下:0 R1 R0 1 1 1 1 1MSB LSBR0和R1是温度值分辨率位, 按下表进行配置.默认出厂设置是R1R0 = 11, 即12位.温度值分辨率配置表R1 R0 分辨率最大转换时间(ms)0 0 9bit 93.75(tconv/8)0 1 10bit 183.50(tconv/4)1 0 11bit 375(tconv/2)1 1 12bit 750 (tconv)4种分辨率对应的温度分辨率为0.5℃, 0.25℃, 0.125℃, 0.0625℃(即最低一位代表的温度值)12位分辨率时的两个温度字节的具体格式如下:低字节:2^3 2^2 2^1 2^0 2^-1 2^-2 2^-3 2^-4高字节:S S S S S 2^6 2^5 2^4其中高字节前5位都是符号位S, 若分辨率低于12位时, 相应地使最低为0, 如: 当分辨率为10位时, 低字节为:2^3 2^2 2^1 2^0 2^-1 2^-2 0 0, 高字节不变....一些温度与转换后输出的数字参照如下:温度数字输出换成16进制+125℃000001111101000007D0H+85℃00000101010100000550H+25.0625℃00000001100100010191H+10.125℃000000001010001000A2H+0.5℃00000000000010000008H0℃00000000000000000000H-0.5℃1111111111111000FFF8H-10.125℃1111111101011110FFE5H-25.0625℃1111111001101111FF6FH-55℃1111110010010000FC90H由上表可看出, 当输出是负温度时, 使用补码表示, 方便计算机运算(若是用C语言, 直接将结果赋值给一个int变量即可).DS18B20 的使用方法:由于DS18B20 采用的是1-Wire 总线协议方式,即在一根数据线实现数据的双向传输,而对单片机来说,我们必须采用软件的方法来模拟单总线的协议时序来完成对DS18B20芯片的访问。
硬件:51板(1)单线ds18b20接P2.2(2)使用外部电源给ds18b20供电,没有使用寄生电源奥软件:Kei uVision 2刚开始对时序把握不好,可是在论坛里没找到比较详细的解释,所以俺倒塌了这个东东,就把俺的经验贴上来,供大家参考,呵呵……如有错误请指正#include "reg52.h"#include "intrins.h"#define uchar unsigned char#define uint unsigned intsbit ds=P2^2;sbit dula=P2^6;sbit wela=P2^7;uchar flag ;uint temp; //参数temp一定要声明为int 型uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //不带小数点数字编码uchar code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //带小数点数字编码/*延时函数*/void TempDelay (uchar us){while(us--);}void delay(uint count) //延时子函数{uint i;while(count){i=200;while(i>0)i--;count--;}}/*串口初始化,波特率9600,方式1 */void init_com(){TMOD=0x20; //设置定时器1为模式2TH1=0xfd; //装初值设定波特率TL1=0xfd;TR1=1; //启动定时器SM0=0; //串口通信模式设置SM1=1;// REN=1; //串口允许接收数据PCON=0; //波特率不倍频// SMOD=0; //波特率不倍频// EA=1; //开总中断//ES=1; //开串行中断}/*数码管的显示*/void display(uint temp){uchar bai,shi,ge;bai=temp/100;shi=temp%100/10;ge=temp%100%10;dula=0;P0=table[bai]; //显示百位dula=1; //从0到1,有个上升沿,解除锁存,显示相应段dula=0; //从1到0再次锁存wela=0;P0=0xfe;wela=1;wela=0;delay(1); //延时约2msP0=table1[shi]; //显示十位dula=1;dula=0;P0=0xfd;wela=1;wela=0;delay(1);P0=table[ge]; //显示个位dula=1;dula=0;P0=0xfb;wela=1;wela=0;delay(1);}/*****************************************时序:初始化时序、读时序、写时序。
基于proteus的51单片机仿真实例六十七、单总线温度传感器DS18B20读写实例标签: proteus温度传感器单片机单总线实例2010-02-20 01:031、I2C总线器件与单片机之间的通信需要两根线,而单总线器件与单片机间的数据通信只要一根线。
单总线适用于单主机系统,能够控制一个或多个从机设备。
主机通常是单片机,从机可以是单总线器件,他们之间通过一条信号线进行数据交换,单总线上同样允许挂接多个单总线器件,因此,每隔单总线器件必须有各自固定的地址,但总线器件通常需要接一个4.7k左右的上拉电阻,这样,当总线空闲时,状态为高电平。
2、单总线器件的数据操作过程1)初始化单总线上的所有处理均从初始化开始,单片机先发送一个复位脉冲,当单总线其间接收到复位脉冲后,先单片机发出应答信号,以便通知单片机:该器件已经准备好等待下一步操作2)识别单总线器件总线上允许挂接多个但总线器件,为便于单片机识别,每个单总线器件在出厂前都分配好了64为序列号以作为地址序列码。
所以单片机能够根据该序列号来识别和判断对那一个单总线器件进行操作3)数据交换单片机与单总线器件之间的数据交换必须遵循严格的通信协议。
单总线协议定义了复位信号,应答信号,写/读0,写/读1的集中信号类型,所有的单总线命令都是由这些基本的信号类型组成的,除了应答信号外,其余信号都由单片机发出,并且发送的所有命令和数据都是低位在前,高位在后。
3、DS18B20的工作时序1)初始化单片机将数据线拉低480-960us后释放,等待15-60us,单总线器件即可输出一个持续时间为60-240us的低电平(应答信号),单片机受到此应答后即可进行后续操作2)写时序当主机将数据线的电平从高拉到低时,形成写时序,有写0和写1两种时序。
写时序开始后,DS18B20在15-60us期间从数据线上采样,如果采样到低电平,则向DS18B20写0,否则写1,两个独立的时序之间至少需要1us的回复时间按(拉高总线电平)3)读时序当主机从DS18B20读取数据时,产生读时序,此时,主机将数据线的电平从高拉到低使读时序被初始化。
fpga_ds18b20温度传感器手册介绍以及接口代码编写思路DS18B20是一款数字温度传感器,它可以通过一个数据线与FPGA(现场可编程门阵列)进行通信。
以下是一个简单的介绍和接口代码编写思路。
DS18B20温度传感器手册介绍:DS18B20由美国Dallas公司生产,是一种数字温度传感器,具有单总线接口、温度测量范围为-55℃~+125℃、测量精度为±0.5℃等特点。
DS18B20的引脚定义如下:GND:接地;VCC:供电电源,通常为+5V;*DQ:数据线,用于与FPGA进行通信。
DS18B20通过DQ线与FPGA进行通信,通信协议为单总线协议。
在数据传输过程中,DQ线上的信号是低电平有效,每次通信过程都需要严格按照协议进行。
DS18B20的测温原理是利用内部的振荡器产生一个频率与温度成正比的脉冲信号,通过计数器计数来测量温度值。
接口代码编写思路:初始化DS18B20和FPGA的DQ线。
在初始化过程中,需要设置DQ线的输入/输出模式,并确保DQ线处于空闲状态。
发送DS18B20的初始化命令序列。
DS18B20需要先执行一系列初始化命令,包括选择温度分辨率、启动温度转换等。
这些命令可以通过向DQ线发送特定的序列来实现。
等待DS18B20的温度转换完成。
在DS18B20完成温度转换之前,DQ线处于空闲状态。
当温度转换完成后,DS18B20会通过DQ线发送一个低电平信号,表示可以读取温度值。
读取DS18B20的温度值。
通过向DQ线发送读取命令序列,可以读取DS18B20的温度值。
温度值以二进制补码的形式发送,需要通过代码进行解码并转换为实际温度值。
结束通信并释放资源。
在读取完温度值后,需要向DQ线发送一个复位序列来结束通信,并释放相关资源。
在实际编写代码时,需要注意以下几个问题:保证DQ线的稳定性和可靠性,避免因干扰或信号不稳定导致通信失败或数据错误;严格按照DS18B20的通信协议进行数据传输,确保数据正确无误;对读取的温度值进行校验和处理,以避免异常数据对系统造成影响。
水温控制系统摘要:该水温控制系统采用单片机进行温度实时采集与控制。
温度信号由“一线总线”数字化温度传感器DS18B20提供,DS18B20在-10~+85°C范围内, 固有测温分辨率为0.5 ℃。
水温实时控制采用继电器控制电热丝和风扇进行升温、降温控制。
系统具备较高的测量精度和控制精度,能完成升温和降温控制。
关键字: AT89C51 DS18B20 水温控制Abstract: This water temperature control system uses the Single Chip Microcomputer to carry on temperature real-time gathering and controling. DS18B20, digitized temperature sensor, provides the temperature signal by "a main line". In -10~+85℃the scope, DS18B20’s inherent measuring accuracy is 0.5 ℃. The water temperature real-time control system uses the electricity nichrome wire carring on temperature increiseament and operates the electric fan to realize the temperature decrease control. The system has the higher measuring accuracy and the control precision, it also can complete the elevation of temperature and the temperature decrease control.Key Words:AT89C51 DS18B20 Water temperature control目录1. 系统方案选择和论证 (2)1.1 题目要求 (2)1.1.1 基本要求 (2)1.1.2 发挥部分 (2)1.1.3 说明 (2)1.2 系统基本方案 (2)1.2.1 各模块电路的方案选择及论证 (2)1.2.2 系统各模块的最终方案 (5)2. 硬件设计与实现 (6)2.1系统硬件模块关系 (6)2.2 主要单元电路的设计 (6)2.2.1 温度采集部分设计 (6)2.2.2 加热控制部分 (8)2.2.3 键盘、显示、控制器部分 (8)3. 系统软件设计 (10)3.1 读取DS18B20温度模块子程序 (10)3.2 数据处理子程序 (10)3.3 键盘扫描子程序 (12)3.4 主程序流程图 (13)4. 系统测试 (14)4.1 静态温度测试 (14)4.2动态温控测量 (14)4.3结果分析 (14)附录1:产品使用说明 (15)附录2:元件清单 (15)附录3:系统硬件原理图 (16)附录4:软件程序清单 (17)参考文献 (26)1.系统方案选择和论证1.1题目要求设计并制作一个水温自动控制系统,控制对象为1L净水,容器为搪瓷器皿。
DS18B20单线数字温度传感器DALLAS半导体公司的数字化温度传感器DS1820是世界上第一片支持“一线总线”接口的温度传感器,体积更小、适用电压更宽、更经济。
一线总线独特而且经济的特点,使用户可轻松地组建温度传感器网络,为测量系统的构建引入全新概念。
DS18B20、DS1822 “一线总线”数字化温度传感器同DS1820一样,支持“一线总线”接口,测量温度范围为-55°C~+125°C,在-10~+85°C范围内,精度为±0.5°C,而DS1822的精度较差为± 2°C 。
现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性,适合于恶劣环境的现场温度测量,如:环境控制、设备或过程控制、测温类消费电子产品等。
DS18B20可以程序设定9~12位的分辨率,精度为±0.5°C,分辨率设定,以及用户设定的报警温度存储在EEPROM中,掉电后依然保存。
DS1822与DS18B20软件兼容,是DS18B20的简化版本。
省略了存储用户定义报警温度、分辨率参数的EEPROM,精度降低为±2°C,适用于对性能要求不高,成本控制严格的应用,是经济型产品。
继“一线总线”的早期产品后,DS1820开辟了温度传感器技术的新概念。
DS18B20和DS1822使电压、特性及封装有更多的选择,让我们可以构建适合自己的经济的测温系统。
1、 DS18B20性能特点DS18B20的性能特点:①采用单总线专用技术,既可通过串行口线,也可通过其它I/O口线与微机接口,无须经过其它变换电路,直接输出被测温度值(9位二进制数,含符号位),②测温范围为-55℃-+125℃,测量分辨率为0.0625℃,③内含64位经过激光修正的只读存储器ROM,④适配各种单片机或系统机,⑤用户可分别设定各路温度的上、下限,⑥内含寄生电源。
数字温度传感器DS18B20摘要DS-18B20 数字温度传感器具有耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。
应用范围广泛,适用于冷冻库,粮仓,储罐,电讯机房,电力机房,电缆线槽等测温和控制领域,轴瓦,缸体,纺机,空调,等狭小空间工业设备测温和控制和汽车空调、冰箱、冷柜、以及中低温干燥箱等。
一、引脚图DS18B20引脚定义:(1)DQ为数字信号输入/输出端;(2)GND为电源地;(3)VDD为外接供电电源输入端(在寄生电源接线方式时接地)二、DS18B20的主要特性1.1、电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电1.2、DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯1.3、多个DS18B20可以并联在唯一的三线上,实现组网多点测温1.4、DS18B20在使用中不需要任何外围元件1.5、温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃1.6、可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可实现高精度测温1.7、在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快1.8、测量结果直接输出数字温度信号,以"一线总线"串行传送给CPU,同时可传送CRC校验码,具有极强的抗干扰纠错能力1.9、负压特性:电源极性接反时,芯片不会因发热而烧毁,但不能正常工作。
三、DS18B20的外形和内部结构DS18B20内部结构主要由四部分组成:64位光刻ROM 、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
DS18B20内部结构图四、DS18B20工作原理DS18B20的温度转换时的延时时间由2s 减为750ms。
DS18B20测温原理如图3所示。
最近都在学习和写单片机的程序, 今天有空又模仿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}改进后的效果图:只有一位小数两位小数, 并消除下一位对上一位的影响。