课程论文
课程名 传感器与检测技术
专业班级: 姓 名: 学 号: 指导教师:
二O一三 年 月 日
数字温度传感器DS18B20介绍、设计及应用
摘要:传感器作为现代科技的前沿技术,被认为是现代信息技术的三大支柱之一,也是国
内外公认的最具有发展前途的高技术产业和朝阳产业。随着时代的进步和发展,传感器与检测技术已经普及到我们生活,工作,科研,各个领域,已经成为一种比较成熟的技术,本文将介绍数字式集成温度传感器DS18B20的结构、原理和接口技术,以及一种基于单片机控制的数字温度计,本温度计属于多功能温度计,可以设置上下报警温度,当温度不在设置范围内时,可以报警。该温度计具有简单、稳定、实用、精度高等优点。
关键词:传感器,数字温度计,报警, DS18B20,STC89C52RC
1引言
随着人们生活水平的不断提高, 传感器与检测技术、单片机控制技术无疑是人们追求的目标之一,它所给人带来的方便也是不可否定的,其中基于数字温度传感器DS18B20设计的数字温度计就是一个典型的例子,但人们对它的要求越来越高,要为人们工作、科研、生活、提供更好的更方便的设施就需要从单片机技术入手,一切向着数字化控制,智能化控制方向发展。
我们首先介绍数字式集成温度传感器DS18B20的结构、原理和接口技术,然后介绍其设计及应用。本设计所介绍的数字温度计与传统的温度计相比,具有读数方便,测温范围广,测温准确,其输出温度采用数字显示,主要用于对测温比较准确的场所,或科研实验室使用,该设计控制器使用单片机STC89C52RC,测温传感器使用DS18B20,报警提示模块采用蜂鸣器报警,用LCD1602液晶显示器实现温度显示,能很好的达到以上要求。
2数字温度传感器DS18B20介绍
2.1简介
DS18B20是DALLAS公司生产的一线式数字温度传感器,具有3引脚TO-92小体积封装形式;温度测量范围为-55℃~+125℃,可编程为9位~12位A/D转换精度,测温分辨率可达0.0625℃,被测温度用符号扩展的16位数字量方式串行输出;其工作电源既可在远端引入,也可采用寄生电源方式产生;多个DS18B20可以并联到3根或2根线上,CPU只需一根端口线就能与诸多DS18B20通信,占用微处理器的端口较少,可节省大量的引线和逻辑电路。以上特点使DS18B20非常适用于远距离多点温度检测系统。
2.2 DS18B20的内部结构
DS18B20内部结构如图1所示,主要由4部分组成:64位ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。DS18B20的管脚排列如图2所示,DQ为数字信号输入/输出端;GND为电源地;VDD为外接供电电源输入端。
图1 DS18B20的内部结构
图2 DS18B20的管脚排列
ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码,每个DS18B20的64位序列号均不相同。64位ROM的排的循环冗余校验码(CRC=X8+X5+X4+1)。ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。
DS18B20中的温度传感器完成对温度的测量,用16位符号扩展的二进制补码读数形式提供,以0.0625℃/LSB形式表达,其中S为符号位。例如+125℃的数字输出为07D0H,+25.0625℃的数字输出为0191H,-25.0625℃的数字输出为FF6FH,-55℃的数字输出为FC90H。
高低温报警触发器TH和TL、配置寄存器均由一个字节的EEPROM组成,使用一个存储器功能命令可对TH、TL或配置寄存器写入。
高速暂存器是一个9字节的存储器。开始两个字节包含被测温度的数字量信息;第3、4、5字节分别是TH、TL、配置寄存器的临时拷贝,每一次上电复位时被刷新;第6、7、8字节未用,表现为全逻辑1;第9字节读出的是前面所有8个字节的CRC码,可用来保证通信正确。
2.3 DS18B20的工作时序
DS18B20的一线工作协议流程是:初始化→ROM操作指令→存储器操作指令→数据传输。其工作时序包括初始化时序、写时序,如图3(a)(b)所示。
(a)初始化程序
(b)写时序
图3 DS18B20的工作时序图
3数字温度传感器DS18B20设计及应用
3.1 基本设计构想
如图4,预设定的正常温度范围是25℃到30 ℃。
当温度低于25℃时,蜂鸣器报警提示,当温度回升到正常温度范围,停止报警提示;
当温度高于30℃时,蜂鸣器报警提示,当温度回落到正常温度范围,停止报警提示。
图4基本设计构想
(1) 硬件组成和设计原理
图5 温度报警系统仿真原理图
如图5为该温度报警系统仿真原理图,主要分四大模块。温度采集模块,主控模块,显示模块和报警提示模块。
(2) 核心算法设计
图6 核心算法
(3) 软件程序设计调试
※ 程序见 [附录Ⅰ] ※
经仿真调试完全达到了设计预定的要求,之后购买相应元器件认真焊接电路板,制作出设计实物,实物如图7。
图7 实物照片
再调试实物,测试记录,得到以下数据,最终所有要求达到,完成本设计。
表1 测试数据记录表
测试次数 1 2 3 4 5 6 显示情况 24 24.8 24.9 25 25.1 26 报警情况 报警 报警 报警 不报警 不报警 不报警 4总结与体会
经过本学期对传感器与检测技课程的学习,我充分运用所学知识以及前段时
间参加我院电子设计大赛之后所积累的经验,理论与实践相结合,终于完成了我的数字温度报警设计,而且达到了预期的设计要求,也让老师查看了我的设计实物,在此期间让我收获了很多,我很开心,也很感谢老师。
在本次设计的过程中,我发现很多的问题,虽然以前没做过这样的设计但这次设计真的让我长进了很多,单片机课程设计重点就在于软件算法的设计,需要有很巧妙的程序算法,虽然以前写过几次程序,但我觉的写好一个程序并不是一件简单的事,有好多的东西,只有我们去试着做了,才能真正的掌握,只学习理论有些东西是很难理解的,更谈不上掌握。
从这次的课程设计中,我真真正正的意识到,在以后的学习中,要理论联系实际,把我们所学的理论知识用到实际当中,学习单机片机更是如此,程序只有在经常的写与读的过程中才能提高,这就是我在这次课程设计中的最大收获。
5 致谢
6 参考文献
[1] 阎石.数字电子技术基础(第三版). 北京:高等教育出版社,1989 [2] 李朝青.单片机原理及接口技术(简明修订版).杭州:北京航空航天大
学出版社,1998
[3] 李广弟.单片机基础[M].北京:北京航空航天大学出版社,1994
[附录Ⅰ:C程序]
#include #include /*************************************************/ //函数申明// /*************************************************/ void delay(uchar k); //标准延时函数 void delay1(uint s); //LCD延时函数 void init(); //初始化显示 void init_18b20(); //复位ds18b20 void write_18b20(uchar dat); //写ds18b20数据 uchar read_18b20(); //读ds18b20数据 void read_word_18b20(); //读数据并转换温度,进行显示 void disp_tp(); //温度显示 void init_LCD(); //初始化LCD1602 void write_data(uchar date); //写LCD1602显示数据 void write_com(uchar com); //写LCD1602指令 void sw(); //按键扫描,修改报警上下限值 void sw_disp(); //显示修改报警上下限界面 sbit DQ=P1^7; //ds18b20数据线引脚 sbit rs=P2^0; sbit rw=P2^1; sbit en=P2^2; sbit P10=P1^0; //蜂鸣器报警引脚,P10=1时报警 sbit k0=P3^0; //4个按键:k0--加上限值,k1--减上限值,k2--加下限值,k3--减下限值 sbit k1=P3^1; sbit k2=P3^2; sbit k3=P3^3; uint tvalue; //温度值 uchar tflag; //温度正负标志 uint i,j,kk=0,key=0; //kk控制上下限值修改界面显示,key控制温度界面显示 uint temph=30; //初始上限值 uint templ=25; //初始下限值 uchar code dis0[]={\"Welcome!\ uchar code dis1[]={0x00,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x00}; //初始化等待界面,进程的代码 uchar code dis2[]={\"temperature:\ uchar code dis3[]={0x06,0x09,0x06,0x00,0x00,0x00,0x00,0x00, //温度符号代码(。) 0x00,0x00,0x06,0x09,0x08,0x08,0x09,0x06};//温度符号代码 (C) uchar code dis4[]={\"Change password:\uchar code dis5[]={\"H:L:\ uchar data temp_data[5]; //储存温度值的数据 /*************************************************/ //主函数// /*************************************************/ void main() { init(); //初始化显示 init_LCD(); //初始化LCD1602 ss: init_18b20(); //复位ds18b20 read_word_18b20(); //读数据并计算转换温度,显示温度值 if(((tvalue/10)%100) goto ss; } /*************************************************/ //开机初始化显示----欢迎等待界面// /*************************************************/ void init() //初始化显示 { uchar n,a,b,temp; P10=0; P3=0x0f; init_LCD(); //初始化LCD1602 write_com(0x84); for(n=0;n<8;n++) { write_data(dis0[n]); delay1(10); } delay1(100); write_com(0x40); //写1602,RAM地址 for(a=0;a<8;a++) //写入自定义字符,用于LCD显示 { write_data(dis1[a]); } temp=0xc0; //赋初始化显示,进程标志的初始地址 for(b=0;b<16;b++) //显示进程标志的进度 { write_com(temp); //写进程命令 write_data(0); //显示进程标志 delay1(80); temp++; } delay1(500); } /*************************************************/ void init_LCD() //初始化LCD1602 { write_com(0x01); //清屏 write_com(0x38); //8位数据,双列,5*7字形 write_com(0x0c); //开启显示屏,关光标,光标不闪烁 write_com(0x06); //显示地址递增,即写一个数据后,显示位置右移一位 write_com(0x80); //写LCD初始显示地址 } /*************************************************/ void write_com(uchar com) //写LCD1602指令 { rs=0; //选择指令寄存器 rw=0; //选择写 P0=com; //把命令字送入P0 delay1(5); //延时一小会儿,让1602准备接收数据 en=1; //使能线电平变化,命令送入1602的8位数据口 en=0; } /*************************************************/ void write_data(uchar date) //写LCD显示数据 { rs=1; //选择数据寄存器 rw=0; //选择写 P0=date; //把要显示的数据送入P0 delay1(5); //延时一小会儿,让1602准备接收数据 en=1; //使能线电平变化,数据送入1602的8位数据口 en=0; } /*************************************************/ //复位ds18b20// /*************************************************/ void init_18b20() { uchar text=1; while(text) { while(text) { DQ=1; _nop_(); _nop_(); //从高拉倒低 DQ=0; delay(50); //550 us DQ=1; delay(6); text=DQ; //判断DS18B20是否存在 // P3=0x80; //存在,则蜂鸣器发出短暂鸣声,若不存在,则一直蜂鸣报警 } delay(45); text=~DQ; // P3=0x00; } DQ=1; } /*************************************************/ //写18b20数据// /*************************************************/ void write_18b20(uchar dat) { uchar t; for(t=8;t>0;t--) { DQ=1; DQ=0; //从高拉倒低 _nop_(); _nop_(); _nop_(); _nop_(); DQ=dat&0x01; //写数据,从低位开始 delay(6); dat>>=1; //8位数据,一位一位的写入ds18b20 } DQ=1; } /*************************************************/ //读18b20数据// /*************************************************/ uchar read_18b20() { uchar t; uchar value=0; for(t=8;t>0;t--) { DQ=1; value>>=1; DQ=0; _nop_(); _nop_(); _nop_(); _nop_(); DQ=1; _nop_(); _nop_(); _nop_(); _nop_(); if(DQ)value|=0x80; delay(6); } DQ=1; return(value); } /*************************************************/ void read_word_18b20() { uchar x,y; write_18b20(0xcc); //发命令:Skip ROM,跳过读序列号 write_18b20(0x44); //启动温度转换 init_18b20(); write_18b20(0xcc); //发命令:Skip ROM,跳过读序列号 write_18b20(0xbe); //读取温度 x=read_18b20(); //温度值低8为存入x y=read_18b20(); //温度值高8为存入y tvalue=y; //整合温度值的低8位与高8位: tvalue<<=8; //左移8位,即将温度值的高8位数据移入16位整形变量tvalue的高位, tvalue|=x; //再与温度值的低8位相或,即将低8位数据存入tvalue低位中,完成数据整合 if(tvalue<0xfff)tflag=0; else { tflag=1; tvalue=(~tvalue)+1; } tvalue*=0.625;//扩大10倍,换算出温度值,显示一位小数。(若扩大100倍,则可通过换算显示出2位小数) temp_data[0]=tvalue/1000+0x30; //百位(加0x30,将数据转换为ASCII码,LCD才能正常显示) temp_data[1]=(tvalue/100)%10+0x30; //十位 temp_data[2]=(tvalue%100)/10+0x30; //个位 temp_data[3]='.'; //小数点 temp_data[4]=tvalue%10+0x30; //小数位 disp_tp(); //调用温度显示 } /*************************************************/ void disp_tp() //温度显示 { uchar m,z; uchar u=0; if(key==1) init_LCD(),key=0; //清屏 write_com(0x80); for(m=0;m<12;m++) { write_data(dis2[m]); //显示temperature: delay1(5); } write_com(0xc6); if(temp_data[0]==0x30) //若百位为0,则不显示 { u=1; if(temp_data[1]==0x30) //若百位与十位都为0,则不显示 u=2; } for(m=u;m<5;m++) { write_data(temp_data[m]); //显示转换的温度数值 } write_com(0x40); //写1602,RAM地址 for(z=0;z<16;z++) //写入自定义字符(温度符号),用于LCD显示 { write_data(dis3[z]); } write_com(0xcb); for(z=0;z<2;z++) { write_data(z); } } //按键扫描// void sw() { uint v; if(P3!=0x0f) { delay1(10); if(P3!=0x0f) { for(v=0;v<100;v++) 出,返回到温度显示界面 { sw_disp(); if(!k0) { delay1(10); if(!k0)temph++; } if(!k1) { delay1(10); if(!k1)temph--; } if(!k2) { //显示温度符号 //循环扫描按键一段时间后自动退 delay1(10); if(!k2)templ++; } if(!k3) { delay1(10); if(!k3)templ--; } } key=1; } } } void sw_disp() { uchar c; if(kk==0)write_com(0x01),kk=1; write_com(0x80); for(c=0;c<16;c++) { write_data(dis4[c]); //显示Change password: } write_com(0xc1); //上限标志显示(H:) write_data(dis5[0]); write_data(dis5[1]); write_com(0xc5); //上限温度符号显示(。C) write_data(0); write_data(1); write_com(0xc9); //下限标志显示(L:) write_data(dis5[2]); write_data(dis5[3]); write_com(0xcd); //下限温度符号显示 write_data(0); write_data(1); write_com(0xc3); write_data(temph/10+0x30); //上限温度值显示 write_data(temph%10+0x30); write_com(0xcb); write_data(templ/10+0x30); //下限温度值显示 write_data(templ%10+0x30); } //ds18b20复位--标准延时函数---11us// void delay(uchar k) { for (;k>0;k--); } void delay1(uint s) //LCD延时函数 { for(i=0;i 因篇幅问题不能全部显示,请点此查看更多更全内容for(j=0;j<100;j++) {;}