当前位置:文档之家› 基于51单片机与DS18B20的数字温度计设计

基于51单片机与DS18B20的数字温度计设计

四川师范大学课程设计报告基于单片机的DS18B20数字温度计设计学生姓名院系名称物理与电子工程学院专业名称电子信息工程班级学号指导教师完成时间基于单片机的DS18B20数字温度计设计学生姓名:指导老师:内容摘要:随着现代信息化技术的飞速发展和传统工业改造的逐步实现,能独立工作的温度检测系统已广泛应用于各种不同的领域。

本文介绍了一个基于STC89C52单片机和数字温度传感器DS18B20的测温系统,并用LED数码管显示温度值,易于读数。

系统电路简单、操作简便,能任意设定报警温度并可查询最近的10个温度值,系统具有可靠性高、成本低、功耗小等优点。

关键词:单片机数字温度传感器温度计目录1 引言 (4)2 设计要求 (4)2.1 基本要求 (4)2.2 扩展功能 (4)3 总体方案设计 (4)3.1 方案论证 (4)3.1.1 方案一 (4)3.1.2 方案二 (5)3.2 总体设计框图 (5)4 硬件设计 (5)4.1 单片机系统 (5)4.2 数字温度传感器模块 (6)4.2.1 DS18B20性能 (6)4.2.2 DS18B20外形及引脚说明 (7)4.2.3 DS18B20接线原理图 (7)4.2.4 DS18B20时序图 (7)4.2.5 数据处理 (9)4.3 显示电路 (10)4.4 声光报警电路 (10)4.5 键盘输入电路 (11)5 软件设计 (11)5.1 主程序模块 (11)5.2 读温度值模块 (12)5.3 中断模块 (14)5.4 温度查询模块 (15)5.5 温度设定、报警模块 (16)5.6 数码管驱动模块 (18)6 源程序 (19)7 总结 (26)参考文献: (28)1 引言随着人们生活水平的不断提高,单片机控制无疑是人们追求的目标之一,它所给人带来的方便是不可否定的,各种数字系统的应用也使人们的生活更加舒适。

数字化控制、智能控制为现代人的工作、生活、科研等方面带来方便。

其中数字温度计就是一个典型的例子。

数字温度计与传统的温度计相比,具有读数方便、测温范围广、测温精确、功能多样话等优点。

其主要用于对测温要求准确度比较高的场所,或科研实验室使用,该设计使用STC89C52单片机作控制器,数字温度传感器DS18B20测量温度,单片机接受传感器输出,经处理用LED数码管实现温度值显示。

2 设计要求2.1 基本要求实现实时温度显示,测温范围0~500C,误差50C以内。

2.2 扩展功能温度报警,能任意设定温度范围实现声光报警;每隔10分钟记录一次温度数据,至少能查询过去10个时刻的温度情况。

3 总体方案设计3.1 方案论证3.1.1 方案一由于本设计是测温电路,可以使用热敏电阻之类的器件,将随被测温度变化的电压或电流采样,进行A/D转换后就可以用单片机进行数据处理,实现温度显示。

这种设计需要用到A/D转换电路,增大了电路的复杂性,而且要做到高精度也比较困难。

3.1.2 方案二考虑到在单片机属于数字系统,容易想到数字温度传感器,可选用DS18B20数字温度传感器,此传感器为单总线数字温度传感器,起体积小、构成的系统结构简单,它可直接将温度转化成串行数字信号给单片机处理,即可实现温度显示。

另外DS18B20具有3引脚的小体积封装,测温范围为-55~+125摄氏度,测温分辨率可达0.0625摄氏度,其测量范围与精度都能符合设计要求。

以上两种方案相比较,第二种方案的电路、软件设计更简单,此方案设计的系统在功耗、测量精度、范围等方面都能很好地达到要求,故本设计采用方案二。

3.2 总体设计框图本方案设计的系统由单片机系统、数字温度传感器、LED显示模块、按键控制模块、温度报警模块组成,其总体架构如下图1。

图1 系统总体方框图4 硬件设计4.1 单片机系统1.本设计采用STC89C52单片机作为控制器,完成所有功能的控制,包括:●DS18B20数字温度传感器的初始化和读取温度值●LED数码管显示驱动与控制●按键识别和响应控制●温度设置和报警●温度值的存储和读取2.单片机系统电路原理图:图2 单片机系统原理图4.2 数字温度传感器模块4.2.1 DS18B20性能●独特的单线接口仅需一个端口引脚进行通信●简单的多点分布应用●无需外部器件●可通过数据线供电●零待机功耗●测温范围-55~+125℃,以0.5℃递增●可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃●温度数字量转换时间200ms,12位分辨率时最多在750ms内把温度转换为数字●应用包括温度控制、工业系统、消费品、温度计和任何热感测系统●负压特性:电源极性接反时,传感器不会因发热而烧毁,但不能正常工作4.2.2 DS18B20外形及引脚说明图3 DS18B20外形及引脚●GND:地●DQ:单线运用的数据输入/输出引脚●VD:可选的电源引脚4.2.3 DS18B20接线原理图单总线通常要求接一个约4.7K左右的上拉电阻,这样,当总线空闲时,其状态为高电平。

图4 DS18B20接线原理图4.2.4 DS18B20时序图主机使用时间隙来读写DS18B20的数据位和写命令字的位。

1.初始化时序如下图:图5 DS18B20初始化时序2.DS18B20读写时序:图6 DS18B20读写时序4.2.5 数据处理高速暂存存储器由9个字节组成,其分配如表5所示。

当温度转换命令发布后,经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节。

单片机可通过单线接口读到该数据,读取时低位在前,高位在后。

图7 字节分配下表为12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际温度。

例如+125℃的数字输出为07D0H,实际温度=07D0H*0.0625=2000*0.0625=125℃。

例如-55℃的数字输出为FC90H,则应先将11位数据位取反加1得370H(符号位不变,也不作运算),实际温度=370H*0.0625=880*0.0625=55℃。

可见其中低四位为小数位。

图8 DS18B20温度数据表4.3 显示电路LED数码管显示采用动态扫描方式,能简化电路布线,节约单片机I/O端口。

段码和位码由单片机P0送出,分别用74HC673N锁存。

图9 数码管驱动显示电路4.4 声光报警电路当温度超过设定温度值时,实现声光报警,蜂鸣器鸣叫、8个发光二极管点亮。

蜂鸣器由单片机P2^3口控制,用三极管驱动,发光二极管接单片机P1口,由74HC673N锁存。

图10 声光报警电路4.5 键盘输入电路四个键分别连接单片机P3^4、P3^5、P3^6、P3^7构成独立式键盘,分别实现加、减、报警温度设定功能键和温度查询功能键。

图11 键盘输入电路5 软件设计5.1 主程序模块主程序需要调用3个子程序,分别为:●实时温度显示子程序:驱动数码管把实时温度值送出在LED数码管显示●查询记录温度值子程序:查询过去存储的温度值,最多可查询10个值●温度设定、报警子程序:设定报警温度值,当温度超过该值时产生报警,即驱动蜂鸣器鸣叫、8个发光二极管发光主程序流程图:开始定时器初始化、启动显示实时温度温度设定、报警查询记录温度值图12 主程序流程图5.2 读温度值模块读温度值模块需要调用4个子程序,分别为:●DS18B20初始化子程序:让单片机知道DS18B20在总线上且已准备好操作●DS18B20写字节子程序:对DS18B20发出命令●DS18B20读字节子程序:读取DS18B20存储器的数据●延时子程序:对DS18B20操作时的时序控制1.读温度值模块流程图:图13 读温度值子程序流程图2.DS18B20初始化子程序流程图:图14 DS18B20初始化子程序流程图3.DS18B20写字节和读字节子程序流程图:图15 DS18B20写字节子程序流程图图16 DS18B20读字节子程序流程图5.3 中断模块中断采用T0方式1,初始值定时为50ms。

中断模块需调用两个子程序:●读温度值子程序:定时读取温度值,实时更新温度值●记录温度值子程序:定时记录温度值,供查询使用把这两个子程序放在中断的原因是,不会因为调整报警温度或查询历史温度值而停止更新温度值和记录温度值。

中断模块流程图:图17中断模块流程图5.4 温度查询模块温度查询模块需要接受按键输入,进入查询界面后,按加减键分别查询上一个和下一个历史温度值,并驱动数码管显示需要查询的温度值。

温度查询模块流程图如下:图18 温度查询模块流程图5.5 温度设定、报警模块此模块跟温度查询模块类似,需要接受按键输入,进入模块界面后,按加减键分别上调和下调设定报警温度值,当实时温度值超过设定值时驱动蜂鸣器发声,并点亮8位发光二极管,实现声光报警。

温度设定、报警模块流程图如下:图19 温度设定、报警模块流程图5.6 数码管驱动模块本设计数码管通过锁存器接单片机P0口,采用动态扫描驱动7段LED数码管进行显示,需调用延时子程序以稳定显示。

模块流程图如下:图20 数码管驱动模块流程图6 源程序#include<reg52.h>#define uchar unsigned char#define uint unsigned int/*************************变量定义************************************/ sbit DQ=P2^2;//ds18b20 端口sbit beep=P2^3;//蜂鸣器使能端sbit dula=P2^6;//数码管段选使能sbit wela=P2^7;//数码管位选使能sbit add=P3^5;//加键sbit sub=P3^4;//减键sbit alarm=P3^6;//设定报警功能键sbit record=P3^7;//查询温度记录功能键uchar code tabled[]={0x3f,0x06,0x5b,0x4f,0x66, 0x6d,0x7d,0x07,0x7f,0x6f, //0~9的七段数码管段码0x40,0x63,0x39};//- c 的段码uchar code tablew[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f};//1~8个数码管的位选码uchar recordtable[10];//存储过去的十个温度值uchar temperature;//温度值uchar countsec,recordnum,count;//计数变量uint countmin;//计数变量uchar alanum=30;//报警温度值,初始值为30摄氏度uchar z=65;//消抖延时函数入口参数/**********************函数声明***************************************/ void delay1(uchar MS);//动态扫描延时子程序void delay(uchar i);//DS18B20工作延时子程序void Init_DS18B20();//DS18B20初始化子程序void WriteOneChar(unsigned char dat);//向DS18B20写一字节数据uchar ReadOneChar(void);//向DS18B20读一字节数据void GetTemperature();//由DS18B20产生温度值void Display(uchar wei,uchar duan);//数码管驱动子程序void Alarm();//温度报警void Showtemperature(uchar tt);//温度显示void Keeprecord();//记录温度值void Showrecord();//显示记录的温度值/*********************主函数*******************************************/ void main(){TMOD=0x01;//定时器初始化,定时器0方式1TH0=(65536-50000)/256;//50msTL0=(65536-50000)%256;EA=1;//开中断ET0=1;TR0=1;//启动定时器while(1){Showtemperature(temperature);//显示实时温度Alarm();//温度设定、报警Showrecord();//查询温度记录值}}/************************动态扫描延时函数********************************/ void delay1(uchar MS){int i,j;for(i=80;i>0;i--)for(j=MS;j>0;j--);}/************************DS18B20工作延时函数*****************************/ void delay(uchar i){while(i--);}/*************************DS18B20初始化函数******************************/ void Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位delay(8); //稍做延时DQ = 0; //单片机将DQ拉低delay(80); //精确延时大于480usDQ = 1; //拉高总线delay(10);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay(5);while(!x){x=DQ;}}/*************************读一个字节**************************************/ uchar ReadOneChar(void){unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay(5);}return(dat);}/**************************写一个字节*************************************/ void WriteOneChar(unsigned char dat){unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay(5);DQ = 1;dat>>=1;}delay(5);}/*************************产生温度值***************************************/ void GetTemperature(){uchar tempL,tempH;//分别为数据低位和高位uint temp;Init_DS18B20();WriteOneChar(0xCC); // 跳过读序列号的操作WriteOneChar(0x44); // 启动温度转换delay(200);Init_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度tempL=ReadOneChar();//读出温度低位LSBtempH=ReadOneChar();//读出温度高位MSBtemp=tempH*16+tempL/16;//tempL右移四位去掉小数位temperature=temp&0xff;//测量0~50度,只取temp低八位}/**********************数码管驱动函数*************************************/void Display(uchar wei,uchar duan){dula=0;P0=0xff;wela=1;P0=tablew[wei];wela=0;P0=0;dula=1;P0=tabled[duan];dula=0;delay1(1);}/**********************温度显示函数**************************************/ void Showtemperature(uchar tt){Display(2,tt/10);//显示温度数值Display(3,tt%10);Display(4,11);//显示摄氏度单位Display(5,12);}/********************温度值设定、报警函数**********************************/ void Alarm(){bit flag;if(alarm==0){delay1(80); //延时消抖if(alarm==0){flag=1;//第一次按键进入设置}}while(flag){if(add==0){delay1(z);//延时消抖if(add==0){alanum++;//add键按下,上调设定值if(alanum==51){alanum=0;//最大值为50摄氏度,循环显示}}}if(sub==0){delay1(z);//延时消抖if(sub==0){alanum--;//sub键按下,下调设定值if(alanum==255){alanum=50;//最小值为0摄氏度,循环显示}}}Showtemperature(alanum);Display(0,10);//选中数码管的其他空闲位Display(1,10);//区别于实时温度显示“----”Display(6,10);Display(7,10);if(alarm==0){delay1(80); //延时消抖if(alarm==0){flag=0;//第二次按键退出设置}}if(temperature>alanum)//此处设置报警可以保证调整设定值时即可及时报警{beep=0;//温度大于设定值,声光报警P1=0;}else{beep=1;//温度不大于设定值即不报警P1=0xff;}}if(temperature>alanum)//此处设置报警即保证即使没有进入设置界面任然可以报警{beep=0;//温度大于设定值,声光报警P1=0;else{beep=1;//温度不大于设定值即不报警P1=0xff;}}/***********************温度记录函数**************************************/ void Keeprecord(){uchar i=9;if(countmin==1200)//1分钟{countmin=0;count++;if(count==10)//10分钟{count=0;recordnum++;//记录一次加一,最大记录10个值if(recordnum==10){recordnum=10;}do{recordtable[i]=recordtable[i-1];}while(--i);recordtable[0]=temperature;//最新值填入第一个位置}}}/************************查询记录的温度值*************************************/ void Showrecord(){bit flag;uchar a;if(record==0){delay1(80); //延时消抖if(record==0){flag=1;//record第一次按键置位进入标志}}while(flag)//进入查询Display(0,recordtable[a]/10);//显示温度数值Display(1,recordtable[a]%10);Display(2,11);//显示摄氏度单位Display(3,12);Display(4,10);//数码管第6、7位选中,温度值与记录数之间用--间隔Display(5,10);Display(6,(a+1)/10);//显示第几个记录值Display(7,(a+1)%10);if(add==0){delay1(z);//延时消抖if(add==0)//add按下,查看下一个值{if(recordnum==0){a=0;}else{a++;if(a==recordnum)//循环显示{a=0;}}}}if(sub==0)//sub按下,查看上一个值{delay1(z);if(sub==0){if(recordnum==0){a=0;}else{a--;if(a==255)//循环显示{a=recordnum-1;}}}}if(record==0){delay1(80);if(record==0)//record第二次按下,退出查看{flag=0;}}}}/***********定时器中断0,用于温度检测时间间隔和记录数据时间间隔**************/ void timer0() interrupt 1{TH0=(65536-50000)/256;TL0=(65536-50000)%256;//50mscountsec++;countmin++;if(countsec==20)//1s{countsec=0;GetTemperature();//一秒钟更新一次温度值}Keeprecord();//定时记录温度值}7 总结此次课程设计中,难点在于DS18B20的使用,即对它的时序控制、初始化以及字节读写方法,任何一个环节出错或是时序控制不到位的话就不能得到正确的数据。

相关主题