DS18B20在桥梁混凝土测温中应用DS18B20程序
- 格式:doc
- 大小:298.00 KB
- 文档页数:13
(1)先将数据线置高电平“1”。
(2)延时(该时间要求的不是很严格,但是尽可能的短一点)(3)数据线拉到低电平“0”。
(4)延时750微秒(该时间的时间范围可以从480到960微秒)。
(5)数据线拉到高电平“1”。
(6)延时等待(如果初始化成功则在15到60毫秒时间之内产生一个由DS18B20所返回的低电平“0”。
据该状态可以来确定它的存在,但是应注意不能无限的进行等待,不然会使程序进入死循环,所以要进行超时控制)。
(7)若CPU读到了数据线上的低电平“0”后,还要做延时,其延时的时间从发出的高电平算起(第(5)步的时间算起)最少要480微秒。
(8)将数据线再次拉高到高电平“1”后结束。
(1)数据线先置低电平“0”。
(2)延时确定的时间为15微秒。
(3)按从低位到高位的顺序发送字节(一次只发送一位)。
(4)延时时间为45微秒。
(5)将数据线拉到高电平。
(6)重复上(1)到(6)的操作直到所有的字节全部发送完为止。
(7)最后将数据线拉高。
DS18B20的写操作时序图如图DS18B20的读操作(1)将数据线拉高“1”。
(2)延时2微秒。
(3)将数据线拉低“0”。
(4)延时15微秒。
(5)将数据线拉高“1”。
(6)延时15微秒。
(7)读数据线的状态得到1个状态位,并进行数据处理。
(8)延时30微秒。
DS18B20的读操作时序图如图所示。
DS18B20的Protues仿真图源程序代码:#include "reg51.h"#include "intrins.h" // 此头文件中有空操作语句NOP 几个微秒的延时可以用NOP 语句,但本人没用NOP,直接用了I++来延时#define uchar unsigned char#define uint unsigned intuchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};sbit ds18b20_io=P2^0; //单片机与DS18B20的连接口sbit lcdrs=P2^6; //1602与单片机的接口sbit lcden=P2^7;unsigned char flag,tflag,i;unsigned int temper0,temper1,tvalue;float temperature;void delay() //6us 在KEIL中仿真出来的时间,这是调用DELAY所用的时间{i++;i++;}void Delay_50us(unsigned char t) //50us延时程序{unsigned char j;for(;t>0;t--)for(j=20;j>0;j--);}void delay1(uint z) //这个延时主要用在1602中,1602的读写时序没有//DS18B20那么严格{uint x,y;for(x=0;x<z;x++){ for(y=0;y<121;y++){;};};}uchar ds18b20_rst(){unsigned char j;ds18b20_io=1;i++; //1usds18b20_io=0;for(j=0;j<60;j++) //543us{delay();}ds18b20_io=1;for( j=0;j<7;j++) //65us{delay();}if(!ds18b20_io) //如果读到低电平,即复位成功{flag=1;}else flag=0; //如果没有读到低电平,则复位失败Delay_50us(9); //450usds18b20_io=1;return flag;}void ds18b20_writebyte(unsigned char byte){unsigned char j;for(j=0;j<8;j++){ds18b20_io=1;i++;ds18b20_io=0;delay(); //15usdelay();i++;i++;i++;ds18b20_io=byte&0x01;delay(); delay();delay();delay(); //48usdelay(); delay();delay();byte>>=1;ds18b20_io=1;delay();}ds18b20_io=1;}unsigned char ds18b20_readbyte() {unsigned char k,jj,i;jj=0;for(k=0;k<8;k++){ds18b20_io=1;i++; i++;ds18b20_io=0;delay(); //15usdelay(); i++;i++;i++;ds18b20_io=1;delay(); //15usdelay(); i++; i++;i++;if(ds18b20_io) //17us jj=(jj>>1)|0x80;elsejj>>=1;delay();delay(); delay(); //18us }return jj;}void write_com(uchar com){lcdrs=0;P1=com;delay1(5);lcden=1;delay1(5);lcden=0;}void write_data(uchar date){lcdrs=1;P1=date;delay1(5);lcden=1;delay1(5);lcden=0;}void init(){lcden=0;write_com(0x38);write_com(0x0C);write_com(0x06);write_com(0x01);}float read_temp()/*读取温度值并转换*/{if(ds18b20_rst()==1);{ds18b20_writebyte(0xcc);//*跳过读序列号*/ ds18b20_writebyte(0x44);//*启动温度转换*/ Delay_50us(30);}if(ds18b20_rst()==1);{ds18b20_writebyte(0xcc);//*跳过读序列号*/ds18b20_writebyte(0xbe);//*读取温度*/temper0 =ds18b20_readbyte();temper1 =ds18b20_readbyte();Delay_50us(20);}if(temper1&0xf8) //判断是正温度还是负温度{ //如果是高5位是0 为正温度,反则为负温度tflag=1;tvalue=(temper1<<8)|temper0;tvalue=((~tvalue)+1);temperature=tvalue*(0.0625);}else{tflag=0;tvalue=(temper1<<8)|temper0;temperature=tvalue*0.0625; //不用把tvalue进行转换,直接乘0.0625//的精度}return(temperature);}void write_xian(float date){uint bai,shi,ge,xiaozheng,xqian,xbai,xshi,xge;float k,m; //把浮点的DATA转换为整数,得到浮点娄的整数部分bai=(int)(date)/100; //把得到的整数部分拆开分别存在BAI SHI GE 中shi=((int)(date)%100)/10;ge=(int)(date)%10;if (bai!=0) //如果百不为0 则把整数部分全部显示{write_data(0x30+bai);write_data(0x30+shi);write_data(0x30+ge);}else if (shi!=0) //如果十不为0 则把十位和个位显示{write_data(0x30+shi);write_data(0x30+ge);}else write_data(0x30+ge);//如果百和十位都为0 ,则只显示个位数write_data(0x2e);k=date-(int)date; //取浮点娄的小数部分m=k*10000; //把得到的小数变为整数并显示xiaozheng=(int)m;xqian=(xiaozheng)/1000;xbai=((xiaozheng)%1000)/100;xshi=((xiaozheng)%100)/10;xge=(xiaozheng)%10;write_data(0x30+xqian);write_data(0x30+xbai);write_data(0x30+xshi);write_data(0x30+xge);}void main(){temperature=0.0;flag=0;tflag=0;tvalue=0;init();while(1){read_temp();if(tflag==0){write_xian(temperature); write_data(' '); write_data(' '); }if(tflag==1){write_data('-');write_xian(temperature); write_data(' '); write_data(' '); }write_com(0x80);}}。
;---------------------------------------------------------------------;数字温度计;晶振12MHz;用数字温度传感器DS18B20测量温度、显示温度。
;显示段码接P0口,显示位码接P2.2、P2.3、P2.4。
;数字温度传感器DS18B20的数据引脚接单片机的P3.7口。
;显示格式是:百十个.小数c;设计:;日期:2009年12月26日;----------------------------------------------------------------------- DAT BIT p3.7 ;数据通信口TEMPER_L DATA 30H ;读出的温度低字节TEMPER_H DATA 31H ;读出的温度高字节TEMPER EQU 32H ;温度的整数单元T_DOT EQU 33H ;温度的小数点单元ORG 0000HLJMP MAINORG 000BHSJMP TIMER0 ;定时显示;主程序:ORG 0030HMAIN:LCALL INITIAL ;初始化模块LOOP: LCALL DSWD ;调用读出DS18B20温度程序SJMP LOOP ;读出DS18B20温度程序;----------------------------------------------------------------;定时显示子程序,采用循环扫描方式;显示缓冲区40H~47H;----------------------------------------------------------------TIMER0:push acc ;入栈mov dptr,#tabmov a,TEMPER ;将温度的百位分离出来。
mov b,#100div abmovc a,@a+dptr ;查百位的段码。
mov p0,a ;显示在最高位的数码管上。
DS18B20温度传感器程序及仿真程序#include#define uchar unsigned char#define uint unsigned int#define PORT (P2)sbit rs=P3^0;sbit en=P3^2;sbit ds=P3^3;sbit b=P3^4;uchar dat1,dat2,rw;uchar presence;void delay(uint z) //1ms延时{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void ds18b20_rest() //ds18b20复位,初始化函数{uchar count;uint i=2200;ds=0;for(count=240;count>0;count--); //延时480usds=1;while(ds&&(i>0)) i--;for(count=240;count>0;count--); //延时480us}void ds18b20_write(uchar dat) //向ds18b20写⼀个字节{uchar count;uchar i;for(i=8;i>0;i--){ds=0;for(count=1;count>0;count--);if(dat&0x01==0x01)ds=1;elseds=0;for(count=30;count>0;count--);ds=1;dat>>=1;}}uchar ds18b20_read() //从ds18b20读⼀个字节{ uchar i,count,dat;for(i=8;i>0;i--){dat>>=1;ds=0;for(count=1;count>0;count--);ds=1;for(count=1;count>0;count--);if(ds)dat|=0x80;for(count=30;count>0;count--);}return dat;}void ds18b20_change() //ds18b20获取并开始转换{ ds18b20_rest();ds18b20_write(0xcc);ds18b20_write(0x44);delay(1000);ds18b20_rest();ds18b20_write(0xcc);ds18b20_write(0xbe);dat1=ds18b20_read();dat2=ds18b20_read();}void lcd_com(uchar com) //向1602写命令{rs=0;rw=0;PORT=com;delay(1);en=1;delay(1);en=0;}void lcd_dat(uchar dat) //想1602写数据{rs=1;rw=0;PORT=dat;delay(1);en=1;delay(1);en=0;}void lcd_write(uchar c,uchar r,uchar dat) //向1602指定⾏,列,写数据{ lcd_com(0x80+0x40*c+r);lcd_dat(dat);delay(1);}void lcd_init() //1602初始化{lcd_com(0x38);lcd_com(0x0c);lcd_com(0x06);lcd_com(0x01);lcd_write(0,0,0x54);lcd_write(0,1,0x65);lcd_write(0,2,0x6d);lcd_write(0,3,0x70);lcd_write(0,4,0x65);lcd_write(0,5,0x72);lcd_write(0,6,0x61);lcd_write(0,7,0x74);lcd_write(0,8,0x75);lcd_write(0,9,0x72);lcd_write(0,10,0x65);lcd_write(0,11,0x3a);delay(1);lcd_write(1,10,0xdf);lcd_write(1,11,0x43);}void buzzer_sound(a) //蜂鸣器报警函数{if (a>=4)b=1;elseb=0;}void show() //显⽰{unsigned long int dat;uchar flag=0;if(dat2>=240){dat=(~(dat2*256+dat1)+1)*(0.0625*10); flag=1;buzzer_sound(dat%1000/100*2);}else{dat=(dat2*256+dat1)*(0.0625*10); buzzer_sound(dat%1000/100);}if(flag==1){lcd_write(1,9,0x30+dat%10); //+0x30表⽰⽤acsii显⽰lcd_write(1,8,0xa5); //⼩数点lcd_write(1,7,0x30+dat%100/10);lcd_write(1,6,0x30+dat%1000/100);lcd_write(1,5,0x30+dat/1000);lcd_write(1,4,0x2d); //负号}if(!flag){lcd_write(1,9,0x30+dat%10);lcd_write(1,8,0xa5);lcd_write(1,7,0x30+dat%100/10);lcd_write(1,6,0x30+dat%1000/100);lcd_write(1,5,0x30+dat/1000);lcd_write(1,4,0x20); //不显⽰负号}}void main(){lcd_init();while(1){ds18b20_change();// if(dat2>0x03&&dat2<240||dat2>0x01&&dat2>240) // b=0;// else b=1;show();delay(200);}}仿真。
DS18B20测温程序(数码显示)*;************************************************************************** ;*接线方法: *;* 1、用一8P的数据线,一头插在J1,另一头插在J5,接通数码管的段选*;* 2、用一8P的数据线,一头插在J4,另一头插在J6,接通数码管的位选*;* 3、将DS18B20插在主机上的测温部份 *;* 4、用一根单根的数据线,一头插在DS18B20所在数据插针,另一头插到P2.7 * ;**************************************************************************TEMPER_L EQU 36H ;从DS18B20中读回高位,低位暂存区TEMPER_H EQU 35H ;TEMPER_NUM EQU 60H;温度值存储TEMPER_GE EQU 61HTEMPER_SHI EQU 62HTEMPER_SAVE EQU 63HFLAG1 BIT 00HFLAG2 BIT 01HRS BIT p3.0;液晶控制接口RW BIT p3.1E BIT p3.2DQ BIT P2.7;单总线口ORG 0000HA JMP MAINORG 0030HMAIN: MOV SP,#70HLCALL GET_TEMPERLCALL TEMPER_COVLCALL DISPLAYLJMP MAINNOP;**************************************************;读出转换后的温度值;**************************************************GET_TEMPER:SETB DQ ; 定时入口BCD: LCALL INIT_1820JB FLAG1,S22LJMP BCD ;若DS18B20不存在则返回S22: LCALL DELAY1MO V A,#0CCH ; 跳过ROM匹配------0CC命令LCALL WRITE_1820MOV A,#44H ; 发出温度转换命令LCALL WRITE_1820LCALL DELAYCBA CALL INIT_1820JB FLAG1,ABCLJMP CBAABC CALL DELA Y1MOV A,#0CCH ; 跳过ROM匹配LCALL WRITE_1820MOV A,#0BEH ; 发出读温度命令LCALL WRITE_1820LCALL READ_18200 ;READ_1820RET;************************************************************** ;读DS18B20的程序,从DS18B20中读出一个字节的数据;************************************************************** READ_1820:MOV R2,#8RE1:CLR CSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#7DJNZ R3,$MOV C,DQMOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE1RET;******************************************************;写DS18B20的程序;******************************************************WRITE_1820:MOV R2,#8CLR CWR1:MOV R3,#6DJNZ R3,$RRC AMOV DQ,CMOV R3,#23DJNZ R3,$SETB DQNOPDJNZ R2,WR1SETB DQRET;****************************************************;读DS18B20的程序,从DS18B20中读出两个字节的温度数据;****************************************************READ_18200:MOV R4,#2 ; 将温度高位和低位从DS18B20中读出MOV R1,#36H ; 低位存入36H(TEMPER_L),高位存入35H(TEMPER_H) RE00:MOV R2,#8RE01:CLR CSETB DQNOPNOPCLR DQNOPNOPNOPSETB DQMOV R3,#7DJNZ R3,$MOV C,DQMOV R3,#23DJNZ R3,$RRC ADJNZ R2,RE01MOV @R1,ADEC R1DJNZ R4,RE00RET;;****************************************************;将从DS18B20中读出的温度数据进行转换;;****************************************************TEMPER_COV:MOV A,#0F0HANL A,TEMPER_L ; 舍去温度低位中小数点后的四位温度数值SWAP AMOV TEMPER_NUM,A ;得到低四位MOV A,TEMPER_LJNB ACC.3,TEMPER_COV1 ; 四舍五入去温度值INC TEMPER_NUMTEMPER_COV1:MOV A,TEMPER_HANL A,#07HSWAP AORL A,TEMPER_NUM ;得到高四位,再与低四位相或得到值MOV TEMPER_NUM,A ; 保存变换后的温度数据LCALL BIN_BCDRET;;**************************************************** ;将16进制的温度数据转换成压缩BCD码;;**************************************************** BIN_BCD:MOV A,TEMPER_NUMMOV B,#10DIV ABMOV TEMPER_SHI,AMOV TEMPER_GE,BMOV A,TEMPER_SAVECJNE A,TEMPER_GE,ZWFHRET:MOV TEMPER_SAVE,TEMPER_GERETZW:CALL LCDDISPAJMP FHRET;**************************************************** ;DS18B20初始化程序;;**************************************************** INIT_1820:SETB DQNOPCLR DQMOV R0,#250TSR1:DJNZ R0,TSR1 ; 延时520usSETB DQMOV R0,#25H ;96US-25HTSR2:DJNZ R0,TSR2JNB DQ,TSR3;如D0为低则复位成功,DS18B20存在LJMP TSR4 ; 延时TSR3:SETB FLAG1 ; 置标志位,表示DS1820存在LJMP TSR5TSR4:CLR FLAG1 ; 清标志位,表示DS1820不存在LJMP TSR7TSR5:MOV R0,#06BH ;200USTSR6:DJNZ R0,TSR6 ; 延时TSR7:SETB DQ ;拉高总线RET;************************************************* ;数码显示程序;************************************************* Display:MOV DPTR,#disptabMOV A,TEMPER_GEMOVC A,@A+DPTRMOV P1,ACLR P2.2CALL DELAYCALL DELAYSETB P2.2MOV DPTR,#disptabMOV A,TEMPER_SHIMOVC A,@A+DPTRMOV P1,ACLR P2.3CALL DELAYCALL DELAYSETB P2.3RET;************************************************* ;液晶显示程序;*************************************************mov p0,#01h;清屏call enrwmov p0,#38h;设为8位,5*7字型两行 call enrwmov p0,#0Chcall enrwmov p0,#06hcall enrwmov p0,#80hcall enrwmov dptr,#yjtabcall rwrammov p0,#0C0hcall enrwmov dptr,#yjtab1call rwramW_TEM:mov p0,#0CChcall enrwMO V DPTR,#ASCIIMO V A,TEMPER_SHIMO VC A,@A+DPTRMO V P0,Asetb rsclr rwclr ecall delaysetb eMO V DPTR,#ASCIIMO V A,TEMPER_GEMO VC A,@A+DPTRMO V P0,Asetb rsclr rwclr ecall delaysetb eRE Tenrw:clr rsclr rwclr esetb eretrwram:mov r1,#00ha1: mov a,r1movc a,@a+dptrcall rwram2inc r1cjne a,#00h,a1retrwram2:mov p0,asetb rsclr rwclr ecall delaysetb eret;*************************************************;延时子程序;*************************************************DELAY:MOV R6,#250;延时500usDJNZ R6,$RETDELAY1:MOV R7,#20HDJNZ R7,$RETdisptab:db 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H;字形代码表 ;0 1 2 3 4 5 6 7 8 9yjtab: db 'HTTP// ',00hyjtab1:db 'CHENZHOU_TE:**`C',00hASCII: DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39Hend。
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美国达拉斯公司生产的单总线协议的数字温度检测芯片,数据的写入与读取都在一根总线上进行操作,在总线上可以连接多个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是一种单总线数字温度传感器。
测试温度范围-55℃-125℃,温度数据位可配置为9、10、11、12位,对应的刻度值分别为0.5℃、0.25℃、0.125℃、0.0625℃,对应的最长转换时间分别为93.75ms、187.5ms、375ms、750ms。
出厂默认配置为12位数据,刻度值为0.0625℃,最长转换时间为750ms。
从以上数据可以看出,DS18B20数据位越低、转换时间越短、反应越快、精度越低。
单总线,意味着没有时钟线,只有一根通信线。
单总线读写数据是靠控制起始时间和采样时间来完成,所以时序要求很严格,这也是DS18B20驱动编程的难点。
需要注意的是,DS18B20和同一系列的DS18S20,在读写上,时序、命令一致,但因温度值存放的位置不一样,对温度数据的处理也不一样,所以程序不能直接套用。
二.电路设计在WSF-51DB开发板上,利用AT89S52单片机的P1.1脚来驱动DS18B20,上拉电阻阻值为4.7K欧姆。
DS18B20的上拉电阻的阻值是一个需要注意的参数,如果DS18B20放置的位置离电路板较远,需要用较长的电缆来连接时,上拉电阻要相应减小,以弥补线路损耗,而且连接电缆要选用优质的三芯带屏蔽层的电缆,否则不能正常读写数据。
三.软件设计/******************************************************************程序名称:DS18B20驱动*程序功能:读写DS18B20,数码管显示温度值,温度值精度为0.1度。
*开发工具:WSF-51DB开发板* MCU型号:AT89S52-24PU*时钟频率:11.0592-12MHZ*程序作者:吴师傅*版权说明:吴师傅版权所有,转载请注明来源和作者。
*****************************************************************/#i nclude <reg52.h>#i nclude <intrins.h>unsigned char tempflag,fraction,tempr;unsigned char code segmcode[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴极数码管段码0-9 unsigned char code bitcode[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//8位共阴极数码管位码unsigned char code fractioncode[]={0,0,1,2,2,3,4,4,5,6,6,7,8,8,9,9};//将DS18B20的小数部分的0-f刻度转换为0-9刻度的查找表,将精度化为0.1度sbit ser=P2^0;//74HC595串行数据输入sbit oe=P2^1;//74HC595使能sbit rclk=P2^2; //74HC595数据锁存sbit srclk=P2^3;// 74HC595串行时钟sbit DQ=P1^1; //温度总线//延时函数(12MHZ晶振):void Delayus(unsigned char t){ //此函数精确计算:18+6*(t-1)=延时时间(us)while(t--);}//延时ms延时函数:void Delayms(unsigned int t){unsigned int i,j;for(i=t;i>0;i--)for(j=0;j<120;j++);}//任意位数码管显示一个字符函数:void DTDisplayChar(unsigned char segmd,unsigned char bitd )//数码管段码和数码管位码{unsigned char i;unsigned int dat;oe=1;//输出为高阻dat=bitd;dat=dat<<8|segmd; //位码段码合并为一个int型数据for(i=0;i<16;i++)//16位数据从高位依次移入74HC595{ser=(dat&0x8000)?1:0; //判断最高位,为真取1,为假取0srclk=1; //上升沿送数据srclk=0;dat<<=1; //左移取下一位}rclk=1;//74HC595锁存数据rclk=0;oe=0;//输出数据}//DS18B20复位函数:void Reset18B20(void){DQ=0;//拉低,开始复位操作Delayus(100);//延时至少480usDQ=1;//拉高,释放总线控制权while(DQ);//等待器件应答(器件拉低),约15-60us后while(!DQ);//应答脉冲出现后,等待器件拉高,约60-240us后}//DS18B20写命令函数:void Write18B20(unsigned char com){unsigned char i;for(i=0;i<8;i++){DQ=0;//开始写操作_nop_(); _nop_();//至少延时1usDQ=com&0x01;//写数据Delayus(2);//延时,器件在45us内采样DQ=1;//释放总线控制权com>>=1; //右移1位,写下一位}}//DS18B20读数据函数:unsigned char Read18B20(){unsigned char i,rdata=0;for(i=0;i<8;i++){DQ=0;//开始读操作_nop_();_nop_();//至少延时1usDQ=1;//释放总线控制权,15us内要读取数据if(DQ==1) rdata|=0x01<<i;Delayus(10);//延时要大于45us.读0时,45us后器件才拉高总线 }return rdata;}//读出温度函数:void Read18B20Temperature(){unsigned char templ,temph,temp;unsigned int tempv;Reset18B20();//复位Write18B20(0xcc);//写命令,跳过ROM编码命令Write18B20(0x44);//转换命令while(!DQ);//等待转换完成Reset18B20();//复位Write18B20(0xcc);//写命令,跳过ROM编码命令Write18B20(0xbe);//读取暂存器字节命令templ=Read18B20();//读低字节temph=Read18B20();//读高字节Reset18B20();//复位tempv=temph;tempv=tempv<<8|templ;//两个字节合并为一个int型数据temp=(unsigned char)(tempv>>4);//去掉小数部分,化成char型数据if((temph&0x80)==0x80)//如果是负温度{tempflag=1; //负号显示tempr=~temp+1; //实际温度值为读取值的补码fraction=fractioncode[(~templ+1)&0x0f];//取小数部分补码,将16刻度转换为10刻度,精度为0.1度 }else//如果是正温度{tempflag=0;//正温度,负号不显示tempr=temp;//fraction=fractioncode[templ&0x0f];//取小数部分,将16刻度转换为10刻度,精度为0.1度 }}//主函数:int main(void){tempflag=0;while(1){Read18B20Temperature();//读取温度值DTDisplayChar(segmcode[fraction],0x7f);//显示小数部分Delayms(1);DTDisplayChar(segmcode[tempr%10]|0x80,0xbf);//显示个位和小数点 Delayms(1);DTDisplayChar(segmcode[tempr%100/10],0xdf);//显示十位Delayms(1);if(tempflag==1) DTDisplayChar(0x40,0xef);//如果是负温度就显示“-” else DTDisplayChar(segmcode[tempr/100],0xef);//显示百位Delayms(1);DTDisplayChar(0xff,0xff);//均衡数码管亮度}return 0;}。
ds18b20详解及程序最近都在学习和写单⽚机的程序, 今天有空⼜模仿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, 如: 当分辨率为10位时, 低字节为:, ⾼字节不变....由上表可看出, 当输出是负温度时, 使⽤补码表⽰, ⽅便计算机运算(若是⽤C语⾔, 直接将结果赋值给⼀个int变量即可).DS18B20 的使⽤⽅法:由于DS18B20 采⽤的是1-Wire 总线协议⽅式,即在⼀根数据线实现数据的双向传输,⽽对单⽚机来说,我们必须采⽤软件的⽅法来模拟单总线的协议时序来完成对DS18B20芯⽚的访问。
DS18B20多点测温由于本人在前两天找DS18B20多点测温(51 C程序),网上下载了很多,但是都不是很理想,后来,自己总结前人的知识,重新写了这个程序。
其中包括程序一:单个读序列号。
程序二,匹配并且读两个DS18B20,当然,读多个与读两个基本原理一样,只要加上其序列号等即可。
本程序所有显示都是用LCD1602显示。
程序一:度序列号,并用1602显示,1602从左到右分别是低到高位。
#include<reg51。
h>#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7;//ds18b20与单片机连接口sbit RS=P3^0;sbit RW=P3^1;sbit EN=P3^2;unsigned char code str1[]={" "};unsigned char code str2[]={” ”};uchar fCode[8];uchar data disdata[5];uint tvalue;//温度值uchar tflag;//温度正负标志/*************************lcd1602程序**************************/void delay1ms(unsigned int ms)//延时1毫秒(不够精确的){unsigned int i,j;for(i=0;i<ms;i++)for(j=0;j〈100;j++);}void wr_com(unsigned char com)//写指令//{delay1ms(1);RS=0;RW=0;EN=0;P2=com;delay1ms(1);EN=1;delay1ms(1);EN=0;}void wr_dat(unsigned char dat)//写数据//{delay1ms(1);;RS=1;RW=0;EN=0;P2=dat;delay1ms(1);EN=1;delay1ms(1);EN=0;}void lcd_init()//初始化设置//{delay1ms(15);wr_com(0x38);delay1ms(5);wr_com(0x08);delay1ms(5);wr_com(0x01);delay1ms(5);wr_com(0x06);delay1ms(5);wr_com(0x0c);delay1ms(5);}void display(unsigned char *p)//显示//{while(*p!=’\0'){wr_dat(*p);p++;delay1ms(1);}}void init_play()//初始化显示{lcd_init();wr_com(0x80);display(str1);wr_com(0xc0);display(str2);}/******************************ds1820 *********************/ void delay_18B20(unsigned int i)//延时1微秒{while(i——);}void ds1820rst()/*ds1820复位*/{ uchar x=0;DQ = 1; //DQ复位delay_18B20(4);//延时DQ = 0;//DQ拉低delay_18B20(100); //精确延时大于480us DQ = 1; //拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{ uchar i=0;uchar dat = 0;for (i=8;i〉0;i--){ DQ = 0;//给脉冲信号dat>〉=1;DQ = 1;//给脉冲信号if(DQ)dat|=0x80;delay_18B20(10);}return(dat);}void ds1820wr(uchar wdata)/*写数据*/ {uchar i=0;for (i=8; i>0;i——){ DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}read_temp()/*读取温度值并转换*/ {uchar a,b;ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0x44);//*启动温度转换*/ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();tvalue=b;tvalue<〈=8;tvalue=tvalue|a;if(tvalue<0x0fff)tflag=0;else{tvalue=~tvalue+1;tflag=1;}tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数return(tvalue);}/*******************************************************************/void ds1820disp()//温度值显示{ uchar flagdat;disdata[0]=tvalue/1000+0x30;//百位数disdata[1]=tvalue%1000/100+0x30;//十位数disdata[2]=tvalue%100/10+0x30;//个位数disdata[3]=tvalue%10+0x30;//小数位if(tflag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:—if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}}wr_com(0xc0);wr_dat(flagdat);//显示符号位wr_com(0xc1);wr_dat(disdata[0]);//显示百位wr_com(0xc2);wr_dat(disdata[1]);//显示十位wr_com(0xc3);wr_dat(disdata[2]);//显示个位wr_com(0xc4);wr_dat(0x2e);//显示小数点wr_com(0xc5);wr_dat(disdata[3]);//显示小数位}void DispCode(){unsigned char i,temp;ds1820rst();ds1820wr(0x33);for (i=0;i〈8;i++){fCode[i]=ds1820rd();}wr_com(0x80+0x40);for (i=0;i<8;i++){temp = fCode[i]〉>4; //显示高四位if (temp〈10)wr_dat(temp + 0x30);elsewr_dat(temp + 0x37);temp = fCode[i]&0x0f;//显示低四位if (temp〈10)wr_dat(temp+ 0x30);elsewr_dat(temp + 0x37);}}/********************主程序***********************************/ void main(){init_play();//初始化显示DispCode(); //系列号显示delay1ms(1000);while(1){//read_temp();//读取温度// ds1820disp();//显示;}}程序二:匹配序列号,并读温度。
DS18B20在桥梁混凝土测温中应用
DS18B20程序
部门: xxx
时间: xxx
制作人:xxx
整理范文,仅供参考,可下载自行修改
摘要:摘要介绍美国DALLAS公司的单线数字温度传感器DS18B20在其前代产品DS 1820基础上的新特性和与单片机的较详细的接口电路及读写时序,并针对它在桥梁混凝土测温系统的应用中出现的与硬件和软件有关的问题给出解决方法。
关键词:DS18B20 混凝土测温单片机
概述
秦皇岛-沈阳高速铁路客运专线上有许多要架桥的路段,而在远离桥梁厂的野外现场浇制桥梁时,为保证梁身浇注的质量,须做到:①养护时梁内任意两点之间的温度差不能超过规定值;②混凝土浇注后14天的水化热温度曲线须符合所用规格混凝土的水化热温度曲线;③混凝土受太阳照射后桥身的各个部位的热胀冷缩不同,导致桥面和腹板出现日照温差,产生温度应力,此应力不能超过一安全极限值,否则将影响桥梁的承载力。
本系统采用DS18B20和单片机及其外围电路构成完整的温度采集及数据传送电路,用于采集混凝土浇注后14天内的水化热温度及第14天以后,1年内的日照温差,并存入数据库,对桥梁的质量及使用年限进行评估和预测。
一、 DS18B20新特点和结构
DS18B20是美国DALLAS公司继DS1820之后推出的增强型单总线数字温度传感器。
它在测温精度、转换时间、传输距离、分辨率
等方面较DS1820有了很大的改进,给用户带来了更方便的使用和更令人满意的效果。
1. DS18B20的新性能
(1> 可用数据线供电,电压范围:3.0~5.5V;
(2> 测温范围:-55~+125℃,在-10~+85℃时精度为±0.5℃;
(3> 可编程的分辨率为9~12位,对应的可分辨温度分别为0. 5℃、0.25℃、0.125℃和0.0625℃;
(4> 12位分辨率时最多在750ms内把温度值转换为数字;
(5> 负压特性:电源极性接反时,温度计不会因发热而烧毁,但不能正常工作。
2. DS18B20的外形及引脚说明
外形如图1所示。
其体积只有DS1820的一半,引脚定义相同。
1<GND):地
2<DQ):单线运用的数据输入输出引脚
3<VDD):可选的电源引脚
图 1 DS18B20引脚结构图
3. DS18B20内部结构
<1) DS18B20的内部结构如图 2 所示。
b5E2RGbCAP
图 2
DS18B20内部结构图
DS18B20有4个主要的数据部件:
① 64位激光ROM。
64位激光ROM从高位到低位依次为8位CRC、48位序列号和8位家族代码(28H>组成。
②温度灵敏元件。
③非易失性温度报警触发器TH和TL。
可通过软件写入用户报警上下限值。
④配置寄存器。
配置寄存器为高速暂存存储器中的第五个字节。
DS1 8B20在工作时按此寄存器中的分辨率将温度转换成相应精度的数值,其各位定义如图3所示。
其中,TM:测试模式标志位,出厂时被写入0,不能改变;R0、R1:温度计分辨率设置位,其对应四种分辨率如表1所列,出厂时R0、R1置为缺省值:R0=1,R1=1<即12位分辨率),用户可根据需要改写配置寄存器以获得合适的分辨率。
p1EanqFDPw
MSB LSB
图 3 DS18B20配置寄存器结构图
表 1 配置寄存器与分辨率关系表
<2)高速暂存存储器
高速暂存存储器由9个字节组成,其分配如图4所示。
当温度转换命令发布后,经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节。
单片机可通过单线接口读到该数据,读取时低位在前,高位在后,数据格式如图5所示。
对应的温度计算:当符号位S=0时,直接将二进制位转换为十进制;当S= 1时,先将补码变为原码,再计算十进制值。
表 2是对应的一部分温度值。
DXDiTa9E3d
图 4 DS18B20 存储器映像图
图 5 温度值格式图
表 2 DS18B20 温度数据表
4. DS18B20工作原理
DS18B20的读写时序和测温原理与DS1820相同,只是得到的温度值的位数因分辨率不同而不同,且温度转换时的延时时间由2s减为750ms。
DS18B20的读写时序如下。
PROC WRITE
WRITE: MOV R2,#8
CLR C
WR1: CLR DQ
MOV R7,#6
DJNZ R7,$
RRC A
MOV DQ,C
MOV R7,#23
DJNZ R7,$
SETB DQ
NOP
DJNZ R2,WR1
SETB DQ
RET。
读一个字节,出口:A=读入的字节
PROC DREAD DREAD: MOV R2,#8
READL: CLR C
SETB DQ
NOP
NOP
CLR DQ
NOP
NOP
NOP
SETB DQ 。
产生时间片
MOV R7,#7
DJNZ R7,$
MOV C,DQ
MOV R7,#23
DJNZ R7,$
RRC A
DJNZ R2,READL
RETRTCrpUDGiT
二、 DS18B20在桥梁测温中的应用
1. 测温系统要求
由于桥梁施工过程中桥墩、梁身和桥面的二次施工为不同单位负责,故须自备电源,尽量减少功耗;因数据要求长期保存,故要
求容量较大的存储器;要对数据进行分析且形成数据库,从而需要
可靠的通讯接口。
2. 系统设计要点
(1> DS18B20采用三线制供电方式,传输线采用普通的三芯线。
因混凝土的碱性很大,传感器用环氧树脂封装在导热性能良好的薄铁筒内,72个点顺序排列在一根三芯线上。
为避开混凝土浇注时的直接冲力,传感器顺着钢筋走线。
(2> 多次测量并算出温度转换时的平均电流I1和时间t1及温度传感器和MCU均空闲时的平均电流I2。
根据预定更换电池的时间t2得出采样次数N,然后根据电路总功耗,选择适当容量的电池。
P 总=U[I1t1N+I2(t2-Nt1>],U为系统电压。
(3> 为减少功耗,不进行温度采集时,使单片机进入睡眠状态,
采用DS12887的定时中断,唤醒单片机进行温度转换操作。
( 4> 将2字节的温度数据转换为1字节的补码(小数部分四舍五入,此时精度为±1℃>,然后根据测点数n、时钟的年月日时占用的字节<4字节)、采样间隔时间t和要求保存数据的时间t′选取
存储器容量NByte=(n+4>t′/t。
(5> 在VC++6.0开发平台下编写便携式PC机与单片机的串行通讯程序,用于完成修改单片机的采样间隔时间、成批读取单片机外部存储器中的温度数据并将接收到的数据转存入数据库、画各点的水化热温度曲线和画同一截面上点的温度梯度曲线等功能。
3. 硬件构成
该系统采用带8K程序存储器的AT89C52单片机及大容量数据存储器29FC040和 DS12887日历/时钟芯片等构成,如图6所示。
5PC
zVD7HxA
图 6 测温系统硬件电路结构图
(1> DS12887用于产生定时中断,接收到中断后单片机先读取日历和时钟并存储,然后启动温度转换,再读取温度并存储。
单片机构成的采集装置的缺省的采样间隔值为1h(小时>,采样间隔值保存在有断电保存功能DS12887的用户字节中。
测水化热时每小时采
集1次;14天后每天的2点和14点各采集1次。
采样间隔时间只有通过便携式PC经RS232接口进行修改,这样,可避免进入桥梁中的工人或附近居民因好奇而偶然修改了采样值。
(2> 29FC040用于存储一个PC成批读取数据周期内的所有温度值和其对应的采集时间等数据。
(3> 蓄电池的功率应考虑一定的余量,以与存储器时间相匹配。
结论
经实验室和现场调试及实验,发现了DS18B20的一些特点和使用中应注意的事项。
(1> 有很强的承受负压的能力,这样偶尔的误操作不会损坏温度计;
(2> 连接DS18B20的总线电缆(普通三芯线>在只有上拉电阻的情况下可靠传输长度可达45m左右,距离再长时须根据分支点数、总线长度匹配其线间电容及阻抗;
(3> 温度转换时间由DS1820的2s降为750ms,且灵敏度大为提高,在逐渐升温的水中与精度为±0.5℃的温度计几乎同步,且回复性很好;
(4> 和DS1820一样,DS18B20的读写时序须经仔细调整,在反复的调试中找出合适的延时时间;
(5> DS18B20工作时电流高达1.5mA,总线上
挂接点数较多且同时进行转换时要考虑增加总线驱动,可用一单片机端口在温度转换时导通一个MOSFET,使I/O线直接拉到电源从而提供一强的上拉;
(6> 在程序等待DS18B20发出的存在信号对,最好设置一有限的等待时间,否则一旦有温度计损坏时,程序将进入一等待的死循环中。
MESjLBHrnAILg。