课设报告基于DSB温度传感器的温度检测系统.docx
《课设报告基于DSB温度传感器的温度检测系统.docx》由会员分享,可在线阅读,更多相关《课设报告基于DSB温度传感器的温度检测系统.docx(20页珍藏版)》请在冰豆网上搜索。
课设报告基于DSB温度传感器的温度检测系统
大连海事大学
课程设计报告
——基于DS18B20温度传感器的温度检测系统
指导教师:
姓名:
专业:
学号:
一、设计目的
本文采用单片机来实现对温度的检测与显示。
它的主要组成部分有:
STC89C51单片机、温度传感器、键盘电路、显示电路、蜂鸣器报警电路。
它可以实时显示温度和设定温度,实现对温度的测量,设定报警上下限等功能。
二、硬件设备
STC89C51、DS18B20、LCD12864、蜂鸣器、键盘
总体框图
三、硬件部分综述
该系统的总体设计思路如下:
温度传感器DS18B20把所测得的温度发送到STC89C51单片机上,经过51单片机处理,将把温度在显示电路上显示,本系统显示器为点阵字符LCD,12864液晶模块。
检测范围-55摄氏度到+125摄氏度。
本系统除了显示温度以外还可以设置一个温度值,对所测温度进行监控,当温度高于或低于设定温度时,开始报警并启动相应程序
中央微处理器STC89C51:
STC89C51是一个低功耗,高性能CMOS8位单片机,片内含4kBytesISP(In-systemprogrammable)的可反复擦写1000次的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术制造,兼容标准MCS-51指令系统及80S51引脚结构,芯片内集成了通用8位中央处理器和ISPFlash存储单元,功能强大的微型计算机的STC89C51可为许多嵌入式控制应用系统提供高性价比的解决方案。
STC89C51具有如下特点:
40个引脚,4kBytesFlash片内程序存储器,128bytes的随机存取数据存储器(RAM),32个外部双向输入/输出(I/O)口,5个中断优先级2层中断嵌套中断,2个16位可编程定时计数器,2个全双工串行通信口,看门狗(WDT)电路,片内时钟振荡器。
单片机最小系统
温度传感器接口
DS18B20原理与分析:
DS18B20是美国DALLAS半导体公司继DS1820之后最新推出的一种改进型智能温度传感器。
与传统的热敏电阻相比,它能够直接读出被测温度并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。
可以分别在93.75ms和750ms内完成9位和12位的数字量,并且从DS18B20读出的信息或写入DS18B20的信息仅需要一根口线(单线接口)读写,温度变换功率来源于数据总线,总线本身也可以向所挂接的DS18B20供电,而无需额外电源。
因而使用DS18B20可使系统结构更趋简单,可靠性更高。
他在测温精度、转换时间、传输距离、分辨率等方面较DS1820有了很大的改进,给用户带来了更方便的使用和更令人满意的效果。
以下是DS18B20的特点:
(1)独特的单线接口方式:
DS18B20与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。
(2)在使用中不需要任何外围元件。
(3)可用数据线供电,电压范围:
+3.0~+5.5V。
(4)测温范围:
-55-+125℃。
固有测温分辨率为0.5℃。
(5)通过编程可实现9-12位的数字读数方式。
(6)用户可自设定非易失性的报警上下限值。
(7)支持多点组网功能,多个DS18B20可以并联在惟一的三线上,实现多点测温。
(8)负压特性,电源极性接反时,温度计不会因发热而烧毁,但不能正常工作。
LCD12864:
RS、RW、EN为液晶的读写、使能控制端,D0到D7为液晶的数据端口。
液晶显示接口电路
键盘电路:
单片机应用系统中除了复位按键有专门的复位电路,以及专一的复位功能外,其它的按键或键盘都是以开关状态来设置控制功能或输入数据。
键开关状态的可靠输入:
为了去抖动我采用软件方法,它是在检测到有键按下时,执行一个10ms的延时程序后,再确认该键电平是否仍保持闭合状态电平,如保持闭合状态电平则确认为真正键按下状态,从而消除了抖动影响
四、软件设计
系统程序主要包括主程序、读出温度子程序、温度转换子程序、计算温度子程序、显示程序等等。
1.主程序
主要功能是完成DS18B20的初始化工作,并进行读温度,将温度转化成为压缩BCD码并在显示器上显示传感器所测得的实际温度。
2.读出温度子程序
读出温度子程序的主要功能是读出RAM中的9字节,在读出时需要进行CRC校验,校验有错时不进行温度数据的改写。
其程序流程图如图2所示。
3.温度转换命令子程序
温度转换命令子程序主要是发温度转换开始命令,当采用12位分辩率时转换时间约为750ms,在本程序设计中采用1s显示程序延时法等待转换的完成。
温度转换命令子程序流程图如图3所示。
4.计算温度子程序
计算温度子程序将RAM中读取值进行BCD码的转换运算,并进行温度值正负的判定,其流程图如图4所示。
图1主程序流程图图2读出温度子程序流程图
图3温度转换命令子程序流程图图4计算温度子程序流程图
五、实验总结
在本次课程设计中,不仅自己付出了很多心血,也得到了很多老师和同学的支持,为我创造了很多有利条件。
通过这次基于DS18B20传感器测量温度的设计,我学到了许多东西。
首先,这次设计让我把书本上学到的理论知识转化成为现实生活中有价值的实物。
一个好的设计需要通过我们不断的思维,不断的改善。
经过设计之后,我们不像以前那样,遇到问题都不愿意独立思考,只会一味的向别人求助。
现在,我们会通过自己的思考,解决我们自己遇到的问题和困难。
还有,我们学会不能手高眼低,要踏踏实实,从基础学起、做起。
具体到设计时,我们遇到了很多麻烦,比如如何将传感器得到的温度转换成为对应的电信号,如何将电信号输送到单片机进行控制,如何把测得的温度用数字显示出来等等。
最重要的一点是,我们在这次设计中培养了自己的学习能力。
由于好多知识超出了我们的课本范围,这就要求我们自己通过查资料来增加我们的知识,解决遇到的一些问题。
在短时间内从书本资料中帅选出我们所需要的知识,对我们的自主学习能力有很大的帮助。
就那DS18B20来说,由于我们书本上没有介绍到这种温度传感器,所以我们就通过学习DS18B20的说明书,了解它工作的原理以及特性,并弄清楚在实际应用时要注意的事项,对DS18B20进行初始化、编程的要求和规定等。
培养了自主学习的能力,无论以后我们要做什么样的设计,我们都能够通过查阅资料来实现。
六、附录程序
Main函数
#include"Define.h"
#include"Alarm.h"
#include"DS18B20.h"
#include"LedDisplay.h"
#include"KeyScan.h"
ucharnum=0;
ucharn=13,y=7,r=15,s=23,f=59,m=50;
uchardatatable[8]={0};
voiddelay10ms(void)//误差-0.000000000002us
{
unsignedchara,b;
for(b=151;b>0;b--)
for(a=29;a>0;a--);
}
voiddelay1s(void)//误差0us
{
unsignedchara,b,c;
for(c=46;c>0;c--)
for(b=152;b>0;b--)
for(a=70;a>0;a--);
_nop_();//ifKeil,requireuseintrins.h
}
voidmain()
{
Init18b20();
lcd_init();//初始化LCD
hanzi_Disp(0,0,"当前值");
hanzi_Disp(1,0,"上限");
write_digit(1,2,hightemp);
hanzi_Disp(1,4,"下限");
write_digit(1,6,lowtemp);
hanzi_Disp(2,0,"2013年月日");
hanzi_Disp(3,0,"时分秒");
write_sfm(2,1,n);
write_sfm(2,3,y);
write_sfm(2,5,r);
write_sfm(3,0,s);
write_sfm(3,2,f);
write_sfm(3,4,m);
TMOD=0x01;EA=1;ET0=1;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;delay1s();delay1s();
while
(1)
{
Scankey();
Alarm_fun();
}
}
voidTimer0()interrupt1
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
num++;
if(20==num)
{
num=0;m++;
if(60==m)
{
m=0;f++;
if(60==f)
{
f=0;s++;
if(24==s)
{
s=0;r++;
}
}
}
write_sfm(3,4,m);
write_sfm(3,2,f);
write_sfm(3,0,s);
write_sfm(2,5,r);
write_sfm(2,3,y);
write_sfm(2,1,n);
read_temp();//读取当前温度值
ds1820disp(0,3);//显示当前温度值
}
}
Define.h
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
externuinthightemp,lowtemp;
externucharnum;
externucharn,y,r;
externuchars,f,m;
DS18B20.h
#include"Define.h"
voidds1820rst();
voiddelay_18B20(uinti);
uchards1820rd();
voidds1820wr(ucharwdata);
ucharread_temp();
voidds1820disp(uchar,uchar);
voidInit18b20(void);
voidConfig18b20(void);
voidAlarm_fun();
DS18B20.C
#include"Define.h"
#include"DS18B20.h"
#include"LedDisplay.h"
#include"Alarm.h"
#include"KeyScan.h"
#defineNOP()_nop_()/*定义空指令*/
#define_Nop()_nop_()/*定义空指令*/
bitflag;
bittflag=0;//温度符号标志位
sbitDQ=P3^7;//ds18b20与单片机连接口,温度传感器信号线
uinthightemp=300,lowtemp=260;
uchardatadisdata[5];
uinttvalue=0;//温度值
voiddelay_18B20(uinti)//延时1微秒
{
while(i--);
}
voidInit18b20(void)
{
DQ=1;_nop_();DQ=0;
delay_18B20(80);//delay530uS//80
_nop_();DQ=1;
delay_18B20(14);//delay100uS//14
_nop_();_nop_();_nop_();
if(DQ==0)
flag=1;//detect1820success!
else
flag=0;//detect1820fail!
delay_18B20(20);//20
_nop_();_nop_();
DQ=1;
}
voidds1820rst()//ds1820复位
{
ucharx=0;
DQ=1;//DQ复位
delay_18B20(4);//延时
DQ=0;//DQ拉低
delay_18B20(100);//精确延时大于480us
DQ=1;//拉高
delay_18B20(40);
}
uchards1820rd()//读数据
{
uchari=0,dat=0;
for(i=8;i>0;i--)
{
DQ=0;//给脉冲信号
dat>>=1;
DQ=1;//给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(10);
}
return(dat);
}
voidds1820wr(ucharwdata)//写数据
{
uchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=wdata&0x01;
delay_18B20(10);
DQ=1;
wdata>>=1;
}
}
ucharread_temp()//读取温度值并转换
{
uchara,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);
}
voidds1820disp(ucharx,uchary)//温度值显示
{
ucharflagdat;
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也不显示
}
lcd_pos(x,y);
write_dat(flagdat);//显示符号位
write_dat(disdata[0]);//显示百位
write_dat(disdata[1]);//显示十位
write_dat(disdata[2]);//显示个位
write_dat(0x2e);//显示小数点
write_dat(disdata[3]);//显示小数位
hanzi_Disp(x,y+3,"°C");
}
voidAlarm_fun()
{
if(((tvalue>=hightemp)||(tvalue<=lowtemp))&&(key_flag))
{
high_warn();
}
elsebell=0;
}
LcdDisplay.h
#include"Define.h"
voiddelay_1ms(uintx);
voidwrite_cmd(ucharcmd);
voidwrite_dat(uchardat);
voidlcd_pos(ucharX,ucharY);
voidlcd_init();
voidwrite_sfm(ucharx,uchary,uchardat);
voidhanzi_Disp(unsignedcharx,unsignedchary,unsignedchar*s);
voidwrite_digit(ucharx,uchary,uintdat);
LcdDisplay.C
#include"Define.h"
#include"LcdDisplay.h"
/*端口定义*/
#defineLCD_dataP0//数据口
sbitLCD_RS=P2^6;//寄存器选择输入
sbitLCD_RW=P2^5;//液晶读/写控制
sbitLCD_EN=P2^7;//液晶使能控制
sbitLCD_PSB=P3^2;//串/并方式控制
voiddelay_1ms(uintx)
{
uinti,j;
for(j=0;jfor(i=0;i<110;i++);
}
/*写指令数据到LCD*/
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。
*/
voidwrite_cmd(ucharcmd)
{
LCD_RS=0;LCD_RW=0;LCD_EN=0;
P0=cmd;
delay_1ms(5);
LCD_EN=1;
delay_1ms(5);
LCD_EN=0;
}
/*写显示数据到LCD*/
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。
*/
voidwrite_dat(uchardat)
{
LCD_RS=1;LCD_RW=0;LCD_EN=0;
P0=dat;
delay_1ms(5);
LCD_EN=1;
delay_1ms(5);
LCD_EN=0;
}
/*设定显示位置*/
voidlcd_pos(ucharX,ucharY)
{
ucharpos;
if(X==0){X=0x80;}
elseif(X==1){X=0x90;}
elseif(X==2){X=0x88;}
elseif(X==3){X=0x98;}
pos=X+Y;
write_cmd(pos);//显示地址
}
/*LCD初始化设定*/
voidlcd_init()
{
LCD_PSB=1;//并口方式
write_cmd(0x30);//基本指令操作
delay_1ms(5);
write_cmd(0x0c);//显示开,关光标
delay_1ms(5);
write_cmd(0x01);//清除LCD的显示内容
delay_1ms(5);
}
voidhanzi_Disp(unsignedcharx,unsignedchary,unsignedchar*s)
{//x、y为汉字坐标
lcd_pos(x,y);//写地址
while(*s>0)
{
write_dat(*s);//写数据
s++;
}
}
voidwrite_sfm(ucharx,uchary,uchardat)
{//1602液晶刷新时分秒函数4为时,7为分,10为秒
ucharshi,ge;
shi=dat/10;
ge=dat%10;
lcd_pos(x,y);
write_dat(0x30+shi);
write_dat(0x30+ge);
}
voidwrite_digit(ucharx,uchary,uintdat)
{//1602液晶刷新时分秒函数4为时,7为分,10为秒
ucharbai,shi,ge;
bai=dat/100;
shi=dat%100/10;
ge=dat%10;
lcd_pos(x,y);
write_dat(0x30+bai);
write_dat(0x30+shi);
write_dat(0x2e);
write_dat(0x30+ge);
}
KeyScan.h
#include"Define.h"
#include"LcdDisplay.h"
externbitkey_flag;
externucharcount;
sbitSet=P1^0;
sbitUp=P1^1;
sbitDown=P1^2;
sbitEnter=P1^3;
voidScankey();
KeyScan.c
#include"KeyScan.h"
#include"LedDisplay.h"
bitkey_flag=1;
ucharcount=0;
voiddelay1(uintz)//延时函数,约为1ms
{uintx,y;
for(x=z;x>0;x--)
for(y=114;y>0;y--);
}
voidScankey()
{
if(0==Enter)
{
delay1(10);
if(0==Enter)
{
TR0=1;
count=0;
key_flag=~key_flag;
while(!
Enter);
write_cmd(0x0c);
}
}
if(0==Set)
{
delay1(10);
if(0==Set)
{
TR0=0;count++;while(!
Set);
}
}
if(9==count)count=1;
switch(count)
{//光标闪烁点定位
case1:
write_cmd(0x90+3);write_cmd(0x0f);break;//80908898
case2:
write_cmd(0x90+7);break;
case3:
write_cmd(0x88+1);break;
case4:
write_cmd(0x88+3);break;
case5:
write_cmd(0x88+5);break;
case6:
write_cmd(0x98+0);break;
case7:
write_cmd(0x98+2);break;
case8:
write_cmd(0x98+4);break;
}
if(0==Up)
{
delay