DS18B20介绍、流程图和程序源代码 docx

发布时间:2020-04-30 15:38:58   来源:文档文库   
字号:

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开辟了温度传感器技术的新概念。DS18B20DS1822使电压、特性及封装有更多的选择,让我们可以构建适合自己的经济的测温系统。

1    DS18B20性能特点

DS18B20的性能特点:①采用单总线专用技术,既可通过串行口线,也可通过其它I/O口线与微机接口,无须经过其它变换电路,直接输出被测温度值(9位二进制数,含符号位),②测温范围为-55-+125℃,测量分辨率为0.0625,③内含64位经过激光修正的只读存储器ROM,④适配各种单片机或系统机,⑤用户可分别设定各路温度的上、下限,⑥内含寄生电源。

2    DS18B20内部结构

DS18B20内部结构主要由四部分组成:64位光刻ROM温度传感器非挥发的温度报警触发器THTL高速暂存器。DS18B20的管脚排列如图1所示。64位光刻ROM是出厂前被光刻好的,它可以看作是该DS18B20的地址序列号不同的器件地址序列号不同。 

8位产品系列号

48位产品序号

8CRC编码

   DS18B20高速暂存器共9个存单元,如表所示:

序号

寄存器名称

   

序号

寄存器名称

   

0

温度低字节

16位补码形式存放

45

保留字节12

1

温度高字节

6

计数器余值

2

TH/用户字节1

存放温度上限

7

计数器/

3

HL/用户字节2

存放温度下限

8

CRC

CRC校验

   12位转化为例说明温度高低字节存放形式及计算:12位转化后得到的12位数据,存储在18B20的两个高低两个8位的RAM中,二进制中的前面5位是符号位。如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度(等价说明:高8位字节的低3位和低8位字节的高4位组成温度整数值的二进制数;或者说:12位测量时,所测数值乘以0.0625(=1/16),即右移4位后去掉了二进制数的小数部分);如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625才能得到实际温度(等价说明:当温度小于0时,整数部分就是各位取反,小数部分则是各位取反后加1

8

S

S

S

S

S

26

25

24

8

23

22

21

20

2-1

2-2

2-3

2-4

说明:温度测量分辨率有四种,即

9位测量分辨率0.5

10位测量分辨率0.25

11位测量分辨率0.125

12位测量分辨率0.0625

9~12位的测量,无论采用哪种分辨率,温度整数的有效位均是表中26~20

12位为例:

温度值

二进制数

十六进制数

+125

0000 0111 1101 0000

07D0H

+25.0625

0000 0001 1001 0001

0191H

+10.125

0000 0000 1010 0010

00A2H

+0.5

0000 0000 0000 1000

0008H

0

0000 0000 0000 0000

0000H

-0.5

1111 1111 1111 1000

FFF8H

-10.125

1111 1111 0101 1110

FF5EH

-25.0625

1111 1110 0110 1111

FF6FH

-125

1111 1100 1001 0000

FC90H

1DS18B20控制方法

在硬件上,DS18B20与单片机的连接有两种方法,一种是VCC接外部电源,GND接地,I/O与单片机的I/O线相连;另一种是用寄生电源供电,此时UDDGND接地,I/O接单片机I/O。无论是内部寄生电源还是外部供电,I/O口线要接5kΩ左右的上拉电阻。DS18B20有六条控制命令,如表所示:

   

约定代码

                

温度转换

44H

启动DS18B20进行温度转换

读暂存器

BEH

读暂存器9个字节内容

写暂存器

4EH

将数据写入暂存器的THTL字节

复制暂存器

48H

把暂存器的THTL字节写到E2RAM

重新调E2RAM

B8H

E2RAM中的THTL字节写到暂存器THTL字节

读电源供电方式

B4H

启动DS18B20发送电源供电方式的信号给主CPU

CPUDS18B20的访问流程是:先对DS18B20初始化,再进行ROM操作命令,最后才能对存储器操作,数据操作DS18B20每一步操作都要遵循严格的工作时序和通信协议。如主机控制DS18B20完成温度转换这一过程,根据DS18B20的通讯协议,须经三个步骤:每一次读写之前都要对DS18B20进行复位,复位成功后发送一条ROM指令,最后发送RAM指令,这样才能对DS18B20进行预定的操作。



Initialization procedurereset and presence pulses







C51程序

#include

#include

unsigned char code displaybit[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f};

unsigned char code displaycode[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71,0x00,0x40};

unsigned char code dotcode[32]={0,3,6,9,12,16,19,22, 25,28,31,34,38,41,44,48, 50,53,56,59,63,66,69,72,

75,78,81,84,88,91,94,97};

unsigned char displaycount;

unsigned char displaybuf[8]={16,16,16,16,16,16,16,16};

unsigned char timecount;

unsigned char readdata[8];  

sbit DQ=P3^7;

bit sflag;

bit resetpulse( void)

{

unsigned char i ;

DQ=0;

for(i=255;i>0;i--) ;

DQ=1;

for(i=60;i>0;i--);

return(DQ);

for(i=200;i>0;i--);

}

Void write command to ds18b20 (unsigned char command)

{

unsigned char i;

unsigned char j;

for(i=0;i<8;i++) {

if((command & 0x01)==0)

{ DQ=0;

for(j=35;j>0;j--);

DQ=1; }

Else

{ DQ=0;

for(j=2;j>0;j--);

DQ=1;

for(j=33;j>0;j--); }

command=_cror_(command,1); }

}

unsigned char readdatafromds18b20(void)

{ unsigned char i;

unsigned char j;

unsigned char temp;

temp=0;

for(i=0;i<8;i++)

{ temp=_cror_(temp,1);

DQ=0;

_nop_();

_nop_();

DQ=1;

for(j=10;j>0;j--);

if(DQ==1)

{ temp=temp | 0x80; }

else

{ temp=temp | 0x00; }

for(j=200;j>0;j--);

}

return(temp);

}

void main(void)

{ TMOD=0x01;

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

ET0=1;

EA=1;

while(resetpulse());

writecommandtods18b20(0xcc);

writecommandtods18b20(0x44);

TR0=1;

while(1) { ; }

}

void t0(void) interrupt 1 using 0

{ unsigned char x;

unsigned int result;

TH0=(65536-4000)/256;

TL0=(65536-4000)%256;

if(displaycount==2)

{ P0=displaycode[displaybuf[displaycount]] | 0x80; }

else

{ P0=displaycode[displaybuf[displaycount]]; }

P2=displaybit[displaycount];

displaycount++;

if(displaycount==8)

{ displaycount=0; }

timecount++;

if(timecount==150)

{ timecount=0;

while(resetpulse());

writecommandtods18b20(0xcc);

writecommandtods18b20(0xbe);

readdata[0]=readdatafromds18b20();

readdata[1]=readdatafromds18b20();

for(x=0;x<8;x++)

{ displaybuf[x]=16; }

sflag=0;

if((readdata[1] & 0xf8)!=0x00)

{ sflag=1;

readdata[1]=~readdata[1];

readdata[0]=~readdata[0];

result=readdata[0]+1;

readdata[0]=result;

if(result>255)

{ readdata[1]++; } }

readdata[1]=readdata[1]<<4;

readdata[1]=readdata[1] & 0x70;

x=readdata[0];

x=x>>4;

x=x & 0x0f;

readdata[1]=readdata[1] | x;

x=2;

result=readdata[1];

while(result/10)

{ displaybuf[x]=result%10;

result=result/10;

x++; }

displaybuf[x]=result;

if(sflag==1)

{ displaybuf[x+1]=17; }

x=readdata[0] & 0x0f;

x=x<<1;

displaybuf[0]=(dotcode[x])%10;

displaybuf[1]=(dotcode[x])/10;

while(resetpulse());

writecommandtods18b20(0xcc);

writecommandtods18b20(0x44);

}

}

;这是关于DS18B20的读写程序,数据脚P2.2,晶振11.0592MHz

;温度传感器18B20汇编程序,采用器件默认的12位转化,最大转化时间750微秒

;可以将检测到的温度直接显示到AT89C51的两个数码管上

;显示温度0099,很准确无需校正!

ORG 0000H

;单片机内存分配申明!

TEMPER_L EQU 29H ;用于保存读出温度的低8

TEMPER_H EQU 28H ;用于保存读出温度的高8

FLAG1 EQU 38H ;是否检测到DS18B20标志位

a_bit equ 20h ;数码管个位数存放内存位置

b_bit equ 21h ;数码管十位数存放内存位置

MAIN: LCALL GET_TEMPER ;调用读温度子程序

;进行温度显示,这里我们考虑用网站提供的两位数码管来显示温度

;显示范围0099,显示精度为1

;因为12位转化时每一位的精度为0.0625,我们不要求显示小数所以可以抛弃29H的低4

;28H中的低4位移入29H中的高4,这样获得一个新字节,这个字节就是实际测量获得的温度

;这个转化温度的方法可是我想出来的哦~~非常简洁无需乘于0.0625系数

MOV A,29H

MOV C,40H ;28H中的最低位移入C

RRC A

MOV C,41H

RRC A

MOV C,42H

RRC A

MOV C,43H

RRC A

MOV 29H,A

LCALL DISPLAY ;调用数码管显示子程序

CPL P1.0

AJMP MAIN

; 这是DS18B20复位初始化子程序

INIT_1820: SETB P2.2 ; 数据脚

NOP

CLR P2.2 ;主机发出延时537微秒的复位低脉冲

MOV R1, #3

TSR1: MOV R0, #107

DJNZ R0, $

DJNZ R1, TSR1

SETB P2.2 ;然后拉高数据线

NOP

NOP

NOP

MOV R0, #25H

TSR2: JNB P2.2, TSR3 ;等待DS18B20回应

DJNZ R0, TSR2

LJMP TSR4 ; 延时

TSR3: SETB FLAG1 ; 置标志位,表示DS1820存在

CLR P1.7 ; 检查到DS18B20就点亮P1.7LED

LJMP TSR5

TSR4: CLR FLAG1 ; 清标志位,表示DS1820不存在

CLR P1.1

LJMP TSR7

TSR5: MOV R0, #117

TSR6: DJNZ R0, TSR6 ; 时序要求延时一段时间

TSR7: SETB P2.2

RET

; 读出转换后的温度值

GET_TEMPER: SETB P2.2

LCALL INIT_1820 ;先复位DS18B20

JB FLAG1, TSS2

CLR P1.2

RET ; 判断DS1820是否存在?DS18B20不存在则返回

TSS2: CLR P1.3 ;DS18B20已经被检测到!!!!!!!!!!!!!!!!!!

MOV A, #0CCH ; 跳过ROM匹配

LCALL WRITE_1820

MOV A, #44H ; 发出温度转换命令

LCALL WRITE_1820

;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒

LCALL DISPLAY

LCALL INIT_1820 ;准备读温度前先复位

MOV A, #0CCH ; 跳过ROM匹配

LCALL WRITE_1820

MOV A, #0BEH ; 发出读温度命令

LCALL WRITE_1820

LCALL READ_18200; 将读出的温度数据保存到35H/36H

CLR P1.4

RET

;DS18B20的子程序(有具体的时序要求)

WRITE_1820: MOV R2, #8 ;一共8位数据

CLR C

WR1: CLR P2.2

MOV R3, #5

DJNZ R3, $

RRC A

MOV P2.2, C

MOV R3, #21

DJNZ R3, $

SETB P2.2

NOP

DJNZ R2, WR1

SETB P2.2

RET

; DS18B20的程序, DS18B20中读出两个字节的温度数据

READ_18200: MOV R4,#2 ; 将温度高位和低位从DS18B20中读出

MOV R1,#29H ; 低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)

RE00: MOV R2,#8 ; 数据一共有8

RE01: CLR C

SETB P2.2

NOP

NOP

CLR P2.2

NOP

NOP

NOP

SETB P2.2

MOV R3,#8

RE10: DJNZ R3,RE10

MOV C,P2.2

MOV R3,#21

RE20: DJNZ R3,RE20

RRC A

DJNZ R2,RE01

MOV @R1,A

DEC R1

DJNZ R4,RE00

RET

;显示子程序

display: MOV A,29H ;29H中的十六进制数转换成10进制

MOV B,#10 ;10进制/10=10进制

DIV A B

MOV b_bit ,A ;十位在a

MOV a_bit ,B ;个位在b

MOV DPTR, #numtab ;指定查表启始地址

MOV R0,#4

dpl1: MOV R1,#250 ;显示1000

dplop:MOV A, a_bit ;取个位数

MOVC A,@A+DPTR ;查个位数的7段代码

MOV P0,A ;送出个位的7段代码

CLR P2.7 ;开个位显示

ACALL d1ms ;显示1ms

SETB P2.7

MOV A, b_bit ;取十位数

MOVC A,@A+DPTR ;查十位数的7段代码

MOV P0,A ;送出十位的7段代码

CLR P2.6 ;开十位显示

ACALL d1ms ;显示1ms

SETB P2.6

DJNZ R1,dplop ;100次没完循环

DJNZ R0,dpl1 ; 4100次没完循环

RET

;1MS延时

d1ms: MOV R7,#80

DJNZ R7,$

RET

;实验板上的7段数码管09数字的共阴显示代码

numtab: DB 0CFH,03H,5DH,5BH,93H,0DAH,0DEH,43H,0DFH,0DBH

END



#include "reg51.h"

#include "INTRINS.H"

#include "LCD.h"

#define CLR_RI (RI=0)

#define CLR_TI (TI=0)

unsigned char code ID[2][8]={ 0x28,0x1D,0x25,0x1D,0x00,0x00,0x00,0x80,

0x28,0x0e,0x9e,0x1c,0x00,0x00,0x00,0x32};

unsigned char currSensorNo=0;

sbit TMDAT = P1^7;

sbit RUN_LED = P1^6;

/*------------------------------------------------------------------------------------------------*/

void serial_initial()

{

TMOD=0X20;

SCON=0X50;

PCON=0X00;

TL1=TH1=0XE8;

TR1=1;

}

/*------------------------------------------------------------------------------------------------*/

void send(unsigned char count,unsigned char SEND_Buf[])

{ unsigned char i;

for(i=0;i

{ SBUF=SEND_Buf[i];

while(!TI);

CLR_TI; }

}

/*--------------------------------- delay N ms---------------------------------------------------*/

void Delay_ms (unsigned int Nms )

{ unsigned char i;

while(Nms--)

for(i=0; i<125; i++) ;

}

/*----------------------------------------- delay N count----------------------------------------------*/

void Delay_Count (unsigned char Count )

{ while(Count>0) Count--; }

/*---------------------------------------------- start Reset Pulse----------------------------------------------*/

void tmreset(void)

{ TMDAT=0;

Delay_Count(103);

TMDAT=1;

Delay_Count(4);

}

/*---------------------------------------- ACK--------------------------------------------------*/

void tmpre(void)

{ while(TMDAT);

while(~TMDAT);

Delay_Count(4);

}

/*------------------------------------Read a bit from 1820---------------------------------------------*/

bit tmrbit(void)

{ int i=0;

bit dat;

TMDAT=0;i++;

TMDAT=1;i++;i++;

dat = TMDAT;

Delay_Count(8);

return dat;

}

/*-------------------------------- Read a byte from 1820-----------------------------------------------*/

unsigned char tmrbyte(void)

{ unsigned char i,j,dat=0;

for(i=1;i<=8;i++)

{ j=tmrbit();

dat=(j<<7)|(dat>>1); }

return dat;

}

/*-------------------------------- Read a byte from 1820------------------------------------------------*/

void tmwbyte(unsigned char dat)

{ signed char i=0;

unsigned char j;

bit testb;

for(j=1;j<=8;j++)

{ testb=dat & 0x01;

dat = dat>>1;

if(testb)

{ TMDAT=0;

i++;i++;

TMDAT=1;

Delay_Count(8); }

else

{ TMDAT=0;

Delay_Count(8);

TMDAT=1;

i++;i++; }

}

}

/*------------------------------------- send convert command to 1820----------------------------------------------*/

void tmstart(void)

{ unsigned char i;

tmreset();

tmpre();

Delay_ms(1);

/* tmwbyte(0xcc);*/

tmwbyte(0x55);

for(i=0;i<8;i++)

tmwbyte(ID[currSensorNo][i]);

tmwbyte(0x44);

}

/*------------------------------------- Read tempreature from 1820--------------------------------------*/

unsigned int tmrtemp_all(void)

{ unsigned char a,b;

unsigned int y3;

unsigned char i;

tmreset();

tmpre();

Delay_ms(1);

/*tmwbyte(0xcc);*/

tmwbyte(0x55);

for(i=0;i<8;i++)

tmwbyte(ID[currSensorNo][i]);

tmwbyte(0xbe);

a = tmrbyte();

b = tmrbyte();

y3 = ((unsigned int)b) << 8;

return ((y3+a) & 0x7ff) ;

}

/*---------------------------------Start Test tempreature, All--------------------------------------------*/

void Display_AllTemp(void )

{unsigned int last;

unsigned char i,Dot;

RUN_LED=0;

Part=0;

LED_DISPLAY();

Delay_ms(1);

tmstart();

Delay_ms(800);

last=tmrtemp_all();

RUN_LED=1;

Dot= (last & 0x0f)*6.25 ;

Digit[0]= Dot%10;

Digit[1]=Dot/10;

last=(last>>4) & 0x7f ;

if( (last == 0x7f) ) // erro

{ for(i=0;i<5;i++) Digit[i]=16; }

else

{ for(i=2;i<5;i++)

{ Digit[i] = last %10;

last = last/10; }

if(Digit[4]==0)Digit[4]=17;

Part=1;

}

Digit[5]=currSensorNo;

LED_DISPLAY();

}

/*------------------------------------------------------------------------------------*/

/* void Read_Id()

{ unsigned char i,id[8];

tmreset();

tmpre();

Delay_ms(1);

tmwbyte(0x33);

for(i=0;i<8;i++)

id[i]=tmrbyte();

send(8,id);

} */

/*---------------------------------------- Main------------------------------------------------*/

void main(void)

{ unsigned char id[8]={1,2,3,4,5,6,7,8};

serial_initial();

send(8,id);

for(;;)

{ RUN_LED=!RUN_LED;

/* Read_Id();*/

TX_C =!TX_C ;

currSensorNo=(currSensorNo==1)?0:1;

Display_AllTemp();

/*Change();*/

send(6,Digit);

Delay_ms(1000);

_nop_();

}

}

本文来源:https://www.2haoxitong.net/k/doc/b73570743b68011ca300a6c30c2259010202f31b.html

《DS18B20介绍、流程图和程序源代码 docx.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式