基于单片机的数字温度计设计.docx
《基于单片机的数字温度计设计.docx》由会员分享,可在线阅读,更多相关《基于单片机的数字温度计设计.docx(23页珍藏版)》请在冰豆网上搜索。
![基于单片机的数字温度计设计.docx](https://file1.bdocx.com/fileroot1/2023-1/31/7c9a96fe-c484-4c02-aea5-8c243d074734/7c9a96fe-c484-4c02-aea5-8c243d0747341.gif)
基于单片机的数字温度计设计
1.设计任务与要求
本课题的研究方法是利用单片机和数字温度传感器DS18B20设计一台数字温度计。
单片机作为主控制器,数字温度传感器DS18B20作为测温元件,传感器DS18B20可以读取被测量温度值,进行转换,从而用4位共阳极LED数码管来显示转换后的温度值,可以设定温度的上下限报警功能,实现报警提示。
2.系统的总体设计方案
本设计将利用DS18B20智能温度传感器和单片机小系统,设计一个数字温度采集系统。
并设计一个人机接口电路:
键盘采用独立按键(功能自定义),显示器采用共阴极4位LED显示。
系统的总体设计方案框图如图2.1所示
系统软件设计
图2.1系统的总体设计方案框图
3.硬件设计
本设计采用的是AT89C52单片机为核心的数字温度计,包含了利用温度传感器DS18B20的测温电路、外接键盘、显示电路、报警电路、复位电路和晶振电路。
以DS18B20为主要测温元件进行实时监控温度值。
以4位数码管为显示器件,利用单片机的P0口和电阻排来驱动4位数码管的显示;利用单片机的P1.7来驱动温度传感器DS18B20测温;报警电路利用三极管放大作用驱动报警器报警;按键是利用单片机的P1口和上拉电阻来驱动工作
3.1复位电路设计
复位电路有上电自动复位和按键手动复位两种方式。
上电自动复位是通过外部复位电路的电容充电来实现的,只要电源VCC的上升时间不超过1ms,就可以实现自动上电复位,即接通电源就成了系统的复位初始化。
按键手动复位有电平方式和脉冲方式两种。
其中,按键电平复位是通过使复位端经电阻与VCC电源接通而实现的,而按键脉冲复位则是利用RC微分电路产生的正脉冲来实现的。
本系统的复位电路采用上电复位方式。
复位电路图如图3.1所示:
3.2晶振电路设计
对于每个系统工程的晶振电路,都是用于单片机工作所需要的时钟信号,单片机只有在时钟信号的控制下,其各部件之间才能协调一致工作,时钟信号控制着计算机的工作节奏。
在单片机的TXAL1、TXAL12、之间跨接晶体振荡器和微调电容,可以和单片机内部的振荡器构成一个稳定的自激振荡器,这就是单片机的晶振电路。
这种方式称之为内部的时钟源方式。
电容C1和C2的主要作用是帮助振荡器起振,且振荡器大小对振荡频率有微调作用,在80C51系列中电容的大小30皮法。
另外,振荡器的频率只要由石英晶振的频率来决定本次设计选用12MHz。
本系统的晶振电路如图3.2所示:
图3.2晶振电路图
3.3DS18B20芯片简介
DS18B20主要由4部分组成:
64位ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
DS18B20外形及管脚排列如图3.8和表3-3所示[5]。
DS18B20管脚排列如表3-1所示。
表3-1DS18B20引脚定义:
序号
名称
引脚功能描述
1
GND
地信号
2
DQ
数据输入/输出引脚。
开漏单总线接口引脚。
当被用着在寄生电源下,也可以向器件提供电源。
3
VDD
可选择的VDD引脚。
当工作于寄生电源时,此引脚必须接地。
3.4测温电路设计
数字温度传感器DS18B20的测温电路如图所示3.3所示:
图3.3DS18B20的测温电路
3.5按键模块设计
利用单片机的IO口实现按键的中断输入。
另外需要一个与门实现与中断端口的连接。
按键电路如图3.4所示,期中按键K1为进入/退出设置键;K2为增加键;K3为减少键。
当按下K1键一次时,进入温度报警上线调节,此时显示软件设置的温度报警上线,按K2或K3分别对报警温度进行加一或减一。
当再次按下K1键时,进入温度报警下线调节,此时显示软件设置的温度报警下线,按K2或K3分别对报警温度进行加一或减一。
当第三次按下K1键时,退出温度报警线设置。
显示当前温度。
按键模块电路如图3.4所示
图3.4按键模块电路图
3.6报警电路设计
三极管8550驱动蜂鸣器:
报警电路如图3.5所示三极管来驱动蜂鸣器BUZ1。
图3.5报警电路图
3.7显示电路设计
采用四位共阴极LED数码管来显示温度的大小,可以直接读取。
四位数码管的显示电路如图3.6所示,从左到右依次是百位,十位,个位,十分位。
图3.6显示电路图
4.系统软件设计
系统程序主要包括主程序,读出温度子程序,温度转换命令子程序,计算温度子程序,显示数据刷新子程序和按键扫描处理子程序等。
4.1主程序流程图
主程序的主要功能是负责温度的实时显示、读出并处理DS18B20的测量的当前温度值,温度测量每1s进行一次。
这样可以在一秒之内测量一次被测温度,其程序流程见图4.1所示。
图4.1主程序流程图
4.2读出温度子程序
读出温度子程序的主要功能是读出RAM中的9字节,在读出时需进行CRC校验,校验有错时不进行温度数据的改写。
其程序流程图如图4.2示:
图4.2读出温度子程序流程图
4.3温度转换命令子程序
温度转换命令子程序主要是发温度转换开始命令,当采用12位分辨率时转换时间约为750ms,在本程序设计中采用1s显示程序延时法等待转换的完成。
温度转换命令子程序流程图如图4.3所示:
图4.3温度转换命令子程序流程图
4.4计算温度子程序
计算温度子程序将RAM中读取值进行BCD码的转换运算,并进行温度值正负的判定,其程序流程图如图4.4所示。
图4.4计算温度子程序流程图
4.5显示数据刷新子程序
显示数据刷新子程序主要是对分离后的温度显示数据进行刷新操作,当标志位位为1时将符号显示位移入第一位。
程序流程图如图4.5所示。
图4.5显示数据刷新子程序流程图
4.6报警子程序
设置报警标志位位beep,当温度大于设置的高限报警值或低于设置的低限报警值是,beep=1报警;当温度值在正常范围内时,beep=0.报警流程图如图4.6所示:
图4.6报警子程序流程图
4.7按键扫描处理子程序
按键采用扫描查询方式,设置标志位,当标志位为1时,显示设置温度,否则显示当前温度。
当按下K1键一次时,进入温度报警上线调节,此时显示软件设置的温度报警上线,按K2或K3分别对报警温度进行加一或减一。
当再次按下K1键时,进入温度报警下线调节,此时显示软件设置的温度报警下线,按K2或K3分别对报警温度进行加一或减一。
当第三次按下K1键时,退出温度报警线设置。
显示当前温度。
如下图4.7所示。
图4.7按键扫描处理子程序流程图
5.Protues仿真
5.1Protues测温仿真
通过仿真软件验证该原理图的可行性。
采用protues软件对电路仿真,可以得到预期效果。
数码管仿真图如图5.1所示。
温度传感器的仿真效果图如图5.2所示,此图验证了传感器的温度与数码管显示的数字一致。
图5.1数码管仿真图
图5.2温度传感器的仿真效果图
5.2温度报警线设置仿真
如图5.3是第一次按下K1键显示的上限温度报警值,此时按K2或K3键分别对上限温度报警值进行加一或减一;图5.4是第二次按下K1键显示的下限温度报警值,此时按K2或K3键分别对下限温度报警值进行加一或减一。
图5.3上限温度报警值设置仿真
图5.4下限温度报警值设置仿真
5.3初始置零仿真
当开始仿真时先使数码管显示为“0”,仿真图如图5.5所示。
图5.5初始置零仿真
6.结果分析与心得体会
经过系统的整体调试,本设计达到了规定的设计要求:
能用数码管直接显示、能自由设定温度上下限报警值和实现报警。
本课题所设计的数字温度计包括硬件组成和软件的设计。
该系统在硬件设计上主要是通过其核心控制器件AT89C52将采集到的数字温度值经单片机处理得到相应的温度值,送到4位数码管进行显示,以数字形式显示测量的温度。
整个系统的软件编程就是通过C语言对AT89C52实现其控制功能。
通过为期一周单片机的课程设计使我对单片机的编程及其仿真又加深了印象。
不局限于课本的死知识,增强了动手能力和综合分析能力,更深入了解并掌握了传感器的基本理论知识。
本次设计还存在许多不完善的方面。
在整个设计过程中,由于难度的原因,系统实现的功能有限,与市场上同类产品存在相当的差距;在编程方面,虽然采用C语言编程,但是对其的理解不够透彻,还存在很大的提升空间。
尽管本次设计还不是很完善,但这为我以后的设计之路积累了宝贵的经验。
7.参考文献
[1]余发山,王福忠编著.单片机原理及应用技术.徐州:
中国矿业大学出版社,2008.
[2]胡汉才编著,单片机原理及其接口技术,北京:
清华大学出版社,1996.7
[3]金发庆.传感器技术与应用.北京:
机械工业出版社,2002.34-36
附录全部程序清单
#include
#include
#include//_nop_();延时函数用
#definedmP0//段码输出口
#defineucharunsignedchar
#defineuintunsignedint
sbitDQ=P1^7;//温度输入口
sbitL1=P2^0;//数码管1
sbitL2=P2^1;//数码管2
sbitL3=P2^2;//数码管3
sbitL4=P2^3;//数码管4
sbitbeep=P3^5;//蜂鸣器
sbitset=P1^4;//温度设置切换键
sbitadd=P1^5;//温度加
sbitdec=P1^6;//温度减
inttemp1=0;//显示当前温度和设置温度的标志位为0时显示当前温度
uinth;
uinttemp;
ucharr;
ucharhigh=120,low=20;
ucharsign;
ucharq=0;
uchartt=0;
ucharscale;
ucharcodeditab[16]={0x00,0x01,0x01,0x02,//温度小数部分用查表法
0x03,0x03,0x04,0x04,
0x05,0x06,0x06,0x07,
0x08,0x08,0x09,0x09};
ucharcodetable_dm[12]={0x3f,0x06,0x5b,0x4f,//小数断码表
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x00,0x40};
uchartable_dm1[]={0xbf,0x86,0xdb,0xcf,//共阴LED段码表"0""1""2""3""4""5""6""7""8""9""不亮""-"
0xe6,0xed,0xfd,0x87,
0xff,0xef};//个位带小数点的断码表
uchardatatemp_data[2]={0x00,0x00};//读出温度暂放
uchardatadisplay[5]={0x00,0x00,0x00,0x00,0x00};//显示单元数据,共4个数据和一个运算暂用
voiddelay(uintt)//延时函数
{
for(;t>0;t--);
}
voidscan()
{
intj;
for(j=0;j<4;j++)
{
switch(j)
{
case0:
dm=table_dm[display[0]];L4=0;delay(50);L4=1;//小数
case1:
dm=table_dm1[display[1]];L3=0;delay(50);L3=1;//个位
case2:
dm=table_dm[display[2]];L2=0;delay(50);L2=1;//十位
case3:
dm=table_dm[display[3]];L1=0;delay(50);L1=1;//百位
//else{dm=table_dm[b3];w3=0;delay(50);w3=1;}
}
}
}
ow_reset(void)//DS18B20复位函数
{
charpresence=1;
while(presence)
{
while(presence)
{
DQ=1;//从高拉倒低
_nop_();
_nop_();
DQ=0;
delay(50);//50us
DQ=1;
delay(6);//6us
presence=DQ;//presence=0复位成功,继续下一步
}
delay(45);//延时45us
presence=~DQ;
}
DQ=1;//拉高电平
}
voidwrite_byte(ucharval)//DS18B20写命令函//向1-WIRE总线上写1个字节
{
uchari;
for(i=8;i>0;i--)
{
DQ=1;_nop_();
_nop_();//从高拉倒低
DQ=0;
_nop_();
_nop_();
_nop_();
_nop_();//5us
DQ=val&0x01;//最低位移出
delay(6);//66us
val=val/2;//右移1位
}
DQ=1;
delay
(1);
}
ucharread_byte(void)//DS18B20读1字节函数//从总线上取1个字节
{
uchari;
ucharvalue=0;
for(i=8;i>0;i--)
{
DQ=1;
_nop_();
_nop_();
value>>=1;
DQ=0;
_nop_();
_nop_();
_nop_();
_nop_();//4us
DQ=1;
_nop_();
_nop_();
_nop_();
_nop_();//4us
if(DQ)value|=0x80;
delay(6);//延时66us
}
DQ=1;
return(value);
}
read_temp()//读出温度函数
{
ow_reset();//总线复位
delay(200);
write_byte(0xcc);//发命令
write_byte(0x44);//发转换命令
ow_reset();
delay
(1);
write_byte(0xcc);//发命令
write_byte(0xbe);
temp_data[0]=read_byte();//读温度值的第字节
temp_data[1]=read_byte();//读温度值的高字节
temp=temp_data[1];
temp<<=8;
temp=temp|temp_data[0];//两字节合成一个整型变量。
returntemp;//返回温度值
}
work_temp(uinttem)//温度数据处理函数//二进制高字节的低半字节和低字节的高半字节组成一字节,这个字节的二进制转换为十进制后,就是温度值的百、十、个位值,而剩下的低字节的低半字节转化成十进制后,就是温度值的小数部分
{
ucharn=0;
if(tem>6348)//温度值正负判断
{tem=65536-tem;n=1;}//负温度求补码,标志位置1
display[4]=tem&0x0f;//取小数部分的值
display[0]=ditab[display[4]];//存入小数部分显示值
display[4]=tem>>4;//取中间八位,即整数部分的值
display[3]=display[4]/100;//取百位数据暂存
display[1]=display[4]%100;//取后两位数据暂存
display[2]=display[1]/10;//取十位数据暂存
display[1]=display[1]%10;//个位数据
r=display[1]+display[2]*10+display[3]*100;
if(!
display[3])//符号位显示判断
{
display[3]=0x0a;//最高位为0时不显示
if(!
display[2])
{
display[2]=0x0a;//次高位为0时不显示
}
}
if(n){display[3]=0x0b;}//负温度时最高位显示"-"
}
voidxianshi(inthorl)//设置温度显示转换
{
intn=0;
if(horl>128)
{
horl=256-horl;n=1;
}
display[3]=horl/100;
display[3]=display[3]&0x0f;
display[2]=horl%100/10;
display[1]=horl%10;
display[0]=0;
if(!
display[3])
{
display[3]=0x0a;//最高位为0时不显示
if(!
display[2])
{
display[2]=0x0a;//次高位为0时不显示
}
}
if(n)
{
display[3]=0x0b;//负温度时最高位显示"-"
}
}
voidkeyscan()//按键查询程序
{
inttemp1;//最高温度和最低温度标志位
if(set==0)
{
while
(1)
{
delay(500);//消抖
if(set==0)
{
temp1++;
while(!
set)
scan();
}
if(temp1==1)
{
xianshi(high);
scan();
if(add==0)
{
while(!
add)
scan();
high+=1;
}
if(dec==0)
{
while(!
dec)
scan();
high-=1;
}
}
if(temp1==2)
{
xianshi(low);
if(add==0)
{
while(!
add)
scan();
low+=1;
}
if(dec==0)
{
while(!
dec)
scan();
low-=1;
}
scan();
}
if(temp1>=3)
{
temp1=0;
break;
}
}
}
}
voidBEEP()
{
if(r>=high||r{
beep=!
beep;
}
else
{
beep=0;
}
}
voidmain()//主函数
{
dm=0x00;//初始化端口
L4=0;
L3=0;
L2=0;
L1=0;
for(h=0;h<4;h++)//开机显示"0000"
{
display[h]=0;
}
ow_reset();//开机先转换一次
write_byte(0xcc);//SkipROM
write_byte(0x44);//发转换命令
for(h=0;h<100;h++)//开机显示"0000"
{
scan();
}
while
(1)
{
if(temp1==0)
{
work_temp(read_temp());//处理温度数据
BEEP();
scan();//显示温度值
keyscan();
}
else
keyscan();
}
}
《单片机原理及应用》
课程设计
设计题目:
基于单片机的数字温度计设计
专业班级:
电子信息工程1002班
学生姓名:
李青
学生学号:
0414100214
指导教师:
包长春张云
完成日期:
2013.6.3--2013.6.8
机电工程学院、电子信息工程专业目录