基于DS18B20的多点温度测量及报警.docx
《基于DS18B20的多点温度测量及报警.docx》由会员分享,可在线阅读,更多相关《基于DS18B20的多点温度测量及报警.docx(36页珍藏版)》请在冰豆网上搜索。
基于DS18B20的多点温度测量及报警
《微型计算机控制技术》
课程设计报告
课题名称多点温度检测系统设计
专业自动化(交通信息与工程)
班级自动化一班
学生姓名
指导教师李曙光
2015年7月3日
一、设计题目
多点温度检测系统设计
二、任务要求
(1)使用ds18b20为温度传感器;
(2)检测点数为2点以上,检测温度范围为-40到40度之间,测量相应时间小于1s;
(3)完成温度数据的实时显示;
(4)设计一报警电路,当采集的温度越限(超过键盘设置的上下限)时产
生声光报警。
三、总体设计方案
3.1控制模块
1)主要功能
采用Atmel公司的AT89S51单片机,它作为系统的核心部分,和温度采集单元之间,它直接对温度传感器进行指令操作,获取温度传感器的温度数据后进行各种处理,然后通过显示模块显示出温度值,工作过程中,接收来自键盘控制模块的信号,并对其作出相应的响应,同时,它不断检测DS18B20测取的温度值是否超过了设定的上限温度或下限温度,如果超过则对报警模块发出指令令其报警。
2)器件选择
AT89S51是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。
使用Atmel公司高密度非易失性存储器技术制造。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S51在众多嵌入式控制应用系统中得到广泛应用。
AT89S51具有完整的输入输出、控制端口、以及内部程序存储空间。
与我们通常意义上的微机原理类似,可以通过外接A/D,D/A转换电路及运放芯片实现对传感器传送信息的采集,且能够提供以点阵或LCD液晶及外接按键实现人机交互,能对内部众多I/O端口连接步进电机对外围设备进行精确操控,具有强大的工控能力。
图一AT89S51管脚图
3.2温度显示模块
1)主要功能
实时显示两个DS18B20温度传感器采集到的温度,在按键的设置下显示设定的报警温度上、下限值。
2)器件选择
该模块采用两个四位的八段译码管和一块八位锁存器74HC573组成,采用扫描显示的方式显示八位数据。
数码管分为共阳型和共阴型,共阳极型就是发光管的正极都连在一起,作为一条引线,负极分开。
八段数码发光管就是8个发光二极管组成的,在空间排列成为8字型带个小数点,只要将电压加在阳极和阴极之间相应的笔画就会发光。
8个发光二极管的阳极并接在一起,8个阴极分开,因此称为共阳八段数码管。
相反则为共阴八段数码管。
图二数码管显示字段
(a)八段数码管结构(b)共阴型数码管(c)共阳型数码管
图三八段LED数码显示管原理和结构
3.3温度采集模块
1)主要功能
实时测量两个侧两点的温度
2)器件选择
该模块采用DALLAS公司的DS18B20温度传感器,该温度传感器将温度检测与数字数据输出全集成于一个芯片上,它的一个工作周期分为温度检测和数据处理两个部分,它采用单数据总线进行数据传输,由于本设计采用两点测量温度,两个温度传感器的输出数据脚共连在单片机的数据引脚上,因此在进行温度检测和数据处理中需要首先利用DS18B20的ROM操作指令对温度传感器的ROM—ID进行识别,以针对特定的温度传感器进行操作。
(对DS18B20的操作指令见附录文件)
DS18B20的主要特征:
1)全数字温度转换及输出
2)先进的单总线技术
3)最高12位的分辨率时的最大工作周期为750毫秒
4)可选择寄生工作方式
5)检测温度范围为-55°C~+125°C
6)内置EEPROM,限温度报警
7)64位光刻ROM,内置产品序列号,方便多机挂接
8)多种封装形式,适应不同硬件
图四DS18B20的不同封装形式
3.4键盘控制模块
1)主要功能
通过按键进行工作模式的切换,并且用按键进行上限温度和下限温度的更改
2)器件选择
该模块采用几个按钮开关和相应的几个10K电阻组成,当按下按钮是,得到一个低电平信号送入单片机,松开开关后变回高电平信号,单片机识别此信号并对此做出响应。
图五按键
3.5报警模块
1)功能实现
当两个DS18B0中任意一个测取的温度超过设定的温度上、下限时,蜂鸣器响,以此报警。
2)器件选择
该模块采用蜂鸣器来实现,蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。
蜂鸣器主要分为有源蜂鸣器和无源蜂鸣器两种类型。
有源蜂鸣器与无源蜂鸣器的区别(注意:
这里的“源”不是指电源,而是指震荡源):
有源蜂鸣器内部带震荡源,所以只要一通电就会叫;而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫。
必须用2K-5K的方波去驱动它。
有源蜂鸣器往往比无源的贵,就是因为里面多个震荡电路。
无源蜂鸣器的优点是:
1.便宜
2.声音频率可控,可以做出“多来米发索拉西”的效果
3.在一些特例中,可以和LED复用一个控制口
有源蜂鸣器的优点是:
程序控制方便。
综上所述,本实验采用无缘蜂鸣器。
图六:
有源和无源蜂鸣器的外观a)有源b)无源
四、各硬件模块电路设计
图七单片机端口分配图
总的硬件仿真图附于附录中。
下面是各模块硬件仿真连线图:
4.1单片机最小系统硬件仿真图
4.2温度显示模块硬件仿真图
4.3温度采集模块硬件仿真图
4.4按键控制模块硬件仿真图
4.5报警模块硬件仿真图
4.6硬件实现
初始显示界面(显示两点测量温度)
设定温度上限显示界面(显示温度上限值30°和第二点测量温度)
设定温度下限显示界面(显示温度下限值0°和第二点测量温度)
五、各个软件模块设计和流程图
5.1软件设计总流程图
首先,读取第一个DS18B20测得的温度存入数组temp_buff中,然后读取第二个DS18B20测得的温度存入数组temp1_buff中,随后进行按键扫描和按键处理,对接下来要显示的模式进行选择,然后对数码要管显示的数据进行处理,根据选择的不同的模式读取相应的缓存,经过数码管扫描读出相应的温度,最后,依次判断两个点的测量温度是否超过设定的温度报警值,若超过,蜂鸣器报警,若未超过,继续从开始处循环。
5.2DS18B20初始化
DS18B20的通信方式属于单总线通信方式,需按一定的通信协议。
单总线的所有处理过程均从初始化开始。
其中初始化序列包括一个由主机发出的复位脉冲和其后由从机发出的存在脉冲,存在脉冲让主机知道DS18B20在总线上并且已准备就绪。
5.3读DS18B20测得的温度
首先对DS18B20进行初始化,然后通过跳过ROM匹配指令、温度转换指令,将DS18B20采集到的数据转化为温度,再通过初始化、跳过ROM匹配指令、读温度暂存器指令,将得到的温度读取出来,最后对得到的温度数据进行处理,令TN=温度整数部分,TD=温度小数部分,以便后续进行使用。
5.4数码管显示数据处理
1)前四位数码管显示数据处理
由于数码管数量有限,所以用前四位显示第一个DS18B20测得的温度和设定的报警温度(包括上限温度和下限温度),通过K1键进行三种模式的切换。
若无按键按下或者按下三次K1键(mode=0),将第一个DS18B20测出的温度存入temp[]前四位,后续对其进行译码,经过译码后,前四位数码管显示第一个DS18B20测得的温度:
若按下一次K1键(mode=1),将设定的报警温度上限存入temp[]前四位,后续对其进行译码,经过译码后,前四位数码管显示设定的报警温度上限:
若按下两次K1键(mode=2),将设定的报警温度下限存入temp[]前四位,后续对其进行译码,经过译码后,前四位数码管显示设定的报警温度下限。
2)后四位数码管显示数据处理
将第二个DS18B20测得的温度存入temp[],后续对其进行译码,译码后实时显示第二点的测量温度
5.5按键处理
检测键盘扫描是否有返回值,判断是否有按键按下。
若无按键按下,则进行数码管显示数据处理;若有按键按下且为K1键,mode自加1,并判断mode是否大于2,若大于2,mode清零后输出,若不大于2,直接输出mode;若有按键按下且为K2键,判断mode是否为1,若为1,上限报警温度自加1(不超过125°),若不为1,进行下限报警温度自加1(不超过125°);若有按键按下且为K3键,判断mode是否为1,若为1,上限报警温度自减1(不低于-50°),若不为1,进行下限报警温度自减1(不超过-50°)。
六.设计总结及参考资料
6.1设计总结
本次课程设计我们将两个DS18B20和AT89C51单片机相结合实现了多点温度测量。
对单片机的独立控制外设而言难度不大,但由于不会用同一个I/O口控制多个DS18B20,因此用两个独立的I/O口分别对其控制,故编写的程序有些繁琐。
本次设计的不足是,第二个DS18B20测得温度的小数部分一直无法显示,经过多次调试仍然没有结果,但基本功能都已实现。
虽然课程设计结束了,但我们仍会努力将这一问题解决。
经过本次设计实验,充分认识到自己实际操作方面的不足以及程序编写不够熟练等问题,因此需要多加练习。
同时也更加明确了我们在接下来的学习中的侧重方向,作为工科专业应该更加注重理论与实际的结合,并且持之以恒地坚持,只有这样不断提高自己的专业素养。
6.2参考文献
[1]李群芳.单片机微型计算机与接口技术第三版.电子工业出版社,2010.1
[2]谢自美.电子线路设计.实验测试(第二版)[M].武汉:
华中科技大学出版社,2000.
[3]丘玉娟.用串行ROM和AT89C51实现电子密码锁[J].电脑知识与技术.2005,11(3):
34~36
[4]李金平•电子系统设计•电子工业出版社•2009
七.附件
附件一:
完整源程序
#include
#include
//--定义使用的IO--//
sbitLSA=P2^2;
sbitLSB=P2^3;
sbitLSC=P2^4;//译码器
sbitDQ=P3^7;//定义第一个18B20单总线端口
sbitDQ1=P3^6;//定义第二个18B20单总线端口
sbitkey1=P1^0;//模式切换(上限,下限,当前)
sbitkey2=P1^1;//温度上/下限++
sbitkey3=P1^2;//温度上/下限--
sbitBEEP=P1^5;//定义蜂鸣器接口
//--定义全局变量--//
unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x80,0x40,0x00};
//数码管表,其中display[10]"."display[11]"-"display[12]"不显示"
unsignedcharmode=0,KEY;//mode是模式切换变量,KEY=key_back(按键返回值)
unsignedcharn=0;//数码管位数
unsignedinttemp_buff[9],temp1_buff[9],*p,*q,id_buff[8],id1_buff[8];//利用指针和数组进行数据传输
unsignedcharsymbol,symbol1;//正负标志位
unsignedcharsflag,tltemp;//负温度标志和临时暂存变量
unsignedcharTL;//存储暂存器的温度低位
unsignedcharTH;//存储暂存器的温度高位
unsignedcharTN,TN1;//TN:
第一个DS18B20测得温度的整数部分,TN1:
第二个DS18B20测得温度的整数部分
unsignedcharTD,TD1;//TD:
第一个DS18B20测得温度的小数部分,TD1:
第二个DS18B20测得温度的小数部分
chartemp[8];//温度数据显示的缓存
charH_temp=30;//上限报警温度
charL_temp=0;//下限报警温度
bitflag;
//--函数声明--//
charcabs(charval);//取绝对值函数
voiddelay(unsignedchar);//短延时函数
voiddelay1ms(unsignedint);//长延时函数
bitInit18B20(void);//第一个DS18B20初始化函数
bitInit118B20(void);//第二个DS18B20初始化函数
voidWrite0neChar(unsignedchar);//向第一个DS18B20写一个字节
voidWrite0neChar1(unsignedchar);//向第二个DS18B20写一个字节
unsignedcharRead0neChar(void);//从第一个DS18B20读一个字节
unsignedcharRead0neChar1(void);//从第二个DS18B20读一个字节
voidRead_18B20(unsignedchar);//读第一个DS18B20
voidRead1_18B20(unsignedchar);//读第二个DS18B20
ReadTemperature(void);//读第一个DS18B20的温度
ReadTemperature1(void);//读第二个DS18B20的温度
voidbeep(void);//蜂鸣器函数
voidcheck_alarm(void);//检测第一个DS18B20是否超过限值并报警
voidcheck1_alarm(void);//检测第二个DS18B20是否超过限值并报警
unsignedcharkey_scan();//按键扫描
voidkey_action(key);//按键处理
voiddisplay_transaction();//第一个DS18B20显示数据处理
voiddisplay_transaction1();//第二个DS18B20显示数据处理
//--短延时--//
voiddelay(unsignedcharus)
{
while(us--);
}
//--长延时--//
voiddelay1ms(unsignedintx)
{unsignedchari,j;
for(i=0;ifor(j=1;j<120;j++);
}
//--蜂鸣器--//
voidbeep(void)
{BEEP=0;
delay1ms
(1);
BEEP=~BEEP;
delay1ms
(1);
}
//--按键扫描--//
unsignedcharkey_scan(void)
{unsignedcharkey_back;
key_back=0;
if(!
key1|!
key2|!
key3)
{delay1ms(10);
if(!
key1|!
key2|!
key3)
{delay1ms(10);
if(!
key1)key_back=1;
elseif(!
key2)key_back=2;//检测哪个按键按下
elseif(!
key3)key_back=3;
while(!
key1|!
key2|!
key3);//等待按键释放
}
}
return(key_back);
}
//--按键处理--//
voidkey_action(key_back)
{if(key_back==1)
{mode++;
if(mode>2)
mode=0;
}
elseif(key_back==2)
{if(mode==1)
{H_temp++;
if(H_temp>125)
H_temp=125;
}
else
{L_temp++;
if(L_temp>125)
L_temp=125;
}
}
elseif(key_back==3)
{if(mode==1)
{H_temp--;
if(H_temp<-50)
H_temp=-50;
}
else
{
L_temp--;
if(L_temp<-50)
L_temp=-50;
}
}
}
//--前四位数码管显示数据处理--//
voiddisplay_transaction()
{
if(!
mode)
{temp[0]=TD;//显示小数点
temp[1]=TN%10;
temp[2]=TN/10;
if(symbol==0)//如果温度为正值
temp[3]=12;//不显符号
else//if(symbol==1)温度为负值
temp[3]=11;//显示负号
}
elseif(mode==1)
{temp[0]=12;
temp[1]=cabs(H_temp)%10;
//此处调用求绝对值处理,是显示负温度的关键,下同
temp[2]=cabs(H_temp)/10;
if(H_temp>0||H_temp==0)
temp[3]=12;
else
temp[3]=11;
}
elseif(mode==2)
{temp[0]=12;
temp[1]=cabs(L_temp)%10;
temp[2]=cabs(L_temp)/10;
if(L_temp>0||L_temp==0)
temp[3]=12;
else//如果温度小于0temp[3]=11;
}
}
//--后四位数码管显示数据处理--//
voiddisplay_transaction1()
{
temp[7]=TD1;//显示小数点
temp[6]=TN1%10;//显示个位
temp[5]=TN1/10;//显示十位
if(symbol1==0)//如果温度为正值
temp[4]=12;//不显符号
else//if(symbol==1)温度为负值
temp[4]=11;//显示负号
}
//--检测第一个DS18B20是否超过限值并报警--//
voidcheck_alarm(void)
{
if((TN>H_temp)||(TNbeep();
}
//--检测第一个DS18B20是否超过限值并报警--//
voidcheck1_alarm(void)
{
if((TN1>H_temp)||(TN1beep();
}
/////////////////////////以下是对18B20的操作////////////////////////////////
//--第一个DS18B20初始化--//
bitInit18B20(void)
{
DQ=1;
_nop_();
DQ=0;
delay(80);
_nop_();
DQ=1;
delay(14);
_nop_();
_nop_();
flag=DQ;
delay(20);
_nop_();
_nop_();
return(flag);
}
//--第二个DS18B20初始化--//
bitInit118B20(void)
{
DQ1=1;
_nop_();
DQ1=0;
delay(80);
_nop_();
DQ1=1;
delay(14);
_nop_();
_nop_();
flag=DQ1;
delay(20);
_nop_();
_nop_();
return(flag);
}
//--向第一个DS18B20写一个字节--//
voidWrite0neChar(unsignedcharm)
{
unsignedchari;
for(i=0;i<8;i++)
{
DQ=0;
_nop_();
DQ=m&0x01;
delay(3);
_nop_();
_nop_();
DQ=1;
m>>=1;
}
}
//--向第二个DS18B20写一个字节--//
voidWrite0neChar1(unsignedcharm)
{
unsignedchari;
for(i=0;i<8;i++)
{
DQ1=0;
_nop_();
DQ1=m&0x01;
delay(3);
_nop_();
_nop_();
DQ1=1;
m>>=1;
}
}
//--从第一个DS18B20读一个字节--//
unsignedcharRead0neChar(void)
{
unsignedchari=0,dat=0;
for(i=0;i<8;i++)
{//拉低总线
DQ=0;
dat>>=1;
DQ=1;//释放总线
if(DQ==1)
dat|=0x80;
delay
(2);
_nop_();
}
return(dat);
}
//--从第二个DS18B20读一个字节--//
unsignedcharRead0neChar1(void)
{
unsignedchari=0,dat=0;
for(i=0;i<8;i++)
{
DQ1=0;//拉低总线
dat>>=1;
DQ1=1;//释放总线
if(DQ1==1)
dat|=0x80;
delay
(2);//延时等待数据稳定
_nop_();
}
return(dat);
}
//--读第一个DS18B20--//
voidRead_18B20(unsignedcharj)
{
unsignedchari;
for(i=0;i{
*p=Read0neChar();
p++;
}
}
//--读第二个DS18B20--//
voidRead1_18B20(unsignedcharj)
{