数字温度表设计.docx
《数字温度表设计.docx》由会员分享,可在线阅读,更多相关《数字温度表设计.docx(19页珍藏版)》请在冰豆网上搜索。
数字温度表设计
电子综合设计报告
设计题目:
数字温度表设计
学生姓名:
班级学号:
1
指导教师:
设计时间:
2013.12.9-2013.12.20
一方案设计…………………………………………………………1
二系统的硬件设计…………………………………………………2
1、主控制器……………………………………………………2
2、显示电路……………………………………………………4
3、温度传感器工作原理………………………………………4
4、温度传感器接口电路………………………………………8
三系统的软件设计…………………………………………………8
1、主程序………………………………………………………8
2、温度测量……………………………………………………9
2.1DS18B20复位函数…………………………………9
2.2从DS18B20中读取一个字节………………………9
2.3向DS18B20写一个字节……………………………9
2.4从DS18B20读取数据………………………………10
3、数码管显示…………………………………………………10
四系统的测试………………………………………………………11
五总结………………………………………………………………11
附录源程序清单…………………………………………………12
一、方案设计
本设计主要是介绍了单片机控制下的温度检测系统,详细介绍了其硬件和软件设计,并对其各功能模块做了详细介绍,其主要功能和指标如下:
●利用温度传感器(DS18B20)测量某一点环境温度
●测量范围为0℃~+100℃,精度为±0.5℃
●用数码管进行实际温度值显示
采用AT89C52单片机P2.4口控制温度传感器DS18B20的温度测量,以四位数码感形式输出测量温度,总体设计方框图以及原理图分别如下图所示:
图1.1总体设计方框图
图1.2温度系统原理图
二系统的硬件设计
1、主程序
AT89C52是一种低功耗、高性能CMOS8位微控制器,具有8K在系统可编程Flash存储器。
使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
AT89C52具有以下标准功能:
8k字节Flash,256字节RAM,32位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。
另外,AT89C52可降至0Hz静态逻辑操作,支持2种软件可选择节电模式。
空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。
掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
图2.1时钟电路与复位电路
2、显示电路
显示采用6位数码管,图2.2为温度显示电路
图2.2温度显示电路
3、温度传感器工作原理
DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。
DS18B20的性能特点如下:
•独特的单线接口仅需一个端口引脚进行通讯
•简单的多点分布应用
•无需外部器件
•可通过数据线供电
•零待机功耗
•测温范围-55~+125℃,以0.5℃递增。
华氏器件-67~+2570F,以0.90F递增
•温度以9位数字量读出
•温度数字量转换时间200ms(典型值)
•用户可定义的非易失性温度报警设置
•报警搜索命令识别并标志超过程序限定温度(温度报警条件)的器件
DS18B20内部结构主要由四部分组成:
64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。
DS18B20的管脚排列、各种封装形式如图2.3所示,DQ为数据输入/输出引脚。
开漏单总线接口引脚。
当被用着在寄生电源下,也可以向器件提供电源;GND为地信号;VDD为可选择的VDD引脚。
当工作于寄生电源时,此引脚必须接地。
其电路图2.4所示.。
图2.3外部封装形式图2.4传感器电路图
DS18B20的测温原理如图2.5所示,图中低温度系数晶振的振荡频率受温度的影响很小用于产生固定频率的脉冲信号送给减法计数器1,高温度系数晶振随温度变化其震荡频率明显改变,所产生的信号作为减法计数器2的脉冲输入,图中还隐含着计数门,当计数门打开时,DS18B20就对低温度系数振荡器产生的时钟脉冲后进行计数,进而完成温度测量.计数门的开启时间由高温度系数振荡器来决定,每次测量前,首先将-55℃所对应的基数分别置入减法计数器1和温度寄存器中,减法计数器1和温度寄存器被预置在-55℃所对应的一个基数值。
减法计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当减法计数器1的预置值减到0时温度寄存器的值将加1,减法计数器1的预置将重新被装入,减法计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到减法计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温图2中的斜率累加器用于补偿和修正测温过程中的非线性其输出用,于修正减法计数器的预置值,只要计数门仍未关闭就重复上述过程,直至温度寄存器值达到被测温度值,这就是DS18B20的测温原理。
另外,由于DS18B20单线通信功能是分时完成的,他有严格的时隙概念,因此读写时序很重要。
系统对DS18B20的各种操作必须按协议进行。
操作协议为:
初始化DS18B20(发复位脉冲)→发ROM功能命令→发存储器操作命令→处理数据。
图2.5DS18B20测温原理图
在正常测温情况下,DS1820的测温分辨力为0.5℃,可采用下述方法获得高分辨率的温度测量结果:
首先用DS1820提供的读暂存器指令(BEH)读出以0.5℃为分辨率的温度测量结果,然后切去测量结果中的最低有效位(LSB),得到所测实际温度的整数部分Tz,然后再用BEH指令取计数器1的计数剩余值Cs和每度计数值CD。
考虑到DS1820测量温度的整数部分以0.25℃、0.75℃为进位界限的关系,实际温度Ts可用下式计算:
4、温度传感器接口电路
图2.6温度传感器接口电路
三系统的软件设计
1、主程序
voidmain()
{
uchartemp,temp1;
while
(1)
{
scandisp();
readtemp();
temp1=temper[0];
temp=temper[1];
dispbuf[4]=ditab[temp1];
dispbuf[1]=temp/100;
dispbuf[3]=temp%10;
temp=temp/10;
dispbuf[2]=temp%10;
dispbuf[0]=flag;
dispbuf[5]=11;
}
}
2、温度测量
2.1DS18B20复位函数
voidreset(void)
{
ucharx=0;
DQ=1;
delay(8);
DQ=0;
delay(80);
DQ=1;
delay(14);
x=DQ;
delay(20);
}
2.2从DS18B20中读一个字节
ucharreadbyte(void)
{
uchari=0;
uchardat=0;
for(i=8;i>0;i--)
{
DQ=0;
dat>>=1;
DQ=1;
if(DQ)
dat|=0x80;
delay(4);
}
returndat;
}
2.3向DS18B20写一个字节
voidwritebyte(unsignedchardat)
{
uchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay(5);
DQ=1;
dat>>=1;
}
delay(4);
}
2.4从DS18B20读取数据
voidreadtemp(void)
{
uchara=0,b=0;
reset();
writebyte(0xCC);//跳过序列号
writebyte(0x44);//启动温度转换
reset();
writebyte(0xCC);
writebyte(0xBE);//读9个寄存器,前两个位温度
a=readbyte();//低位
b=readbyte();//高位
if(b>0x0f)//判断是否为负值
{
a=~a+1;
if(a==0)
b=~b+1;
elseb=~b;
flag=10;
}
elseflag=12;
temper[0]=a&0x0f;
a=a>>4;
temper[1]=b<<4;
temper[1]=temper[1]|a;
}
3、数码管显示
voidscandisp()
{
unsignedchari,value;
for(i=0;i<8;i++)
{
P3=0xff;
value=table[dispbuf[i]];
if(i==3)
value|=0x80;
P0=value;
P3=scan[i];
delay(50);
}
}
四系统的测试
4.1测试时的图片
图4.1测量温度结果
五总结
通过近两个星期的单片机课程设计,我终于完成了“数字温度表设计”,心中不免有些高兴,但高兴之余也有我值得深思的。
虽然以前做过类似的实验,但这次的课程设计还是让我学到了很多东西,单片机课程设计重点就在于软件算法的设计,需要有很巧妙的程序算法。
有好多的东西,只有我们去试着做了,才能真正的掌握,只学习理论有些东西是很难理解的,更谈不上掌握。
通过这次的单片机课程设计我认识到了,学习要理论联系实际,把学到的理论知识同实际运用相结合,才能是我们的知识融汇贯通,才能真正的学到知识,真正的做到学以致用。
附录源程序清单
//*******************************************
//包含文件,程序开始
//*******************************************
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitDQ=P2^4;//DS18B20数据线引脚
unsignedcharflag;//负数标志
//行扫描数组
ucharcodescan[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//row0-row7
//数码管显示的段码表
ucharcodetable[13]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
0x40,0x39,0x00};
//小数部分显示查询表
ucharcodeditab[16]={0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,
0x07,0x08,0x08,0x09,0x09};
uchardispbuf[8];//显示缓冲区
uchartemper[2];//存放温度的数组
//*******************************************
//延时函数
//*******************************************
voiddelay(unsignedintus)
{
while(us--);
}
//*******************************************
//DS18B20复位函数
//*******************************************
voidreset(void)
{
ucharx=0;
DQ=1;
delay(8);
DQ=0;
delay(80);
DQ=1;
delay(14);
x=DQ;
delay(20);
}
//*******************************************
//从DS18B20中读一个字节
//*******************************************
ucharreadbyte(void)
{
uchari=0;
uchardat=0;
for(i=8;i>0;i--)
{
DQ=0;
dat>>=1;
DQ=1;
if(DQ)
dat|=0x80;
delay(4);
}
returndat;
}
//*******************************************
//向DS18B20写一个字节
//*******************************************
voidwritebyte(unsignedchardat)
{
uchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
delay(5);
DQ=1;
dat>>=1;
}
delay(4);
}
//*******************************************
//从DS18B20读取数据
//*******************************************
voidreadtemp(void)
{
uchara=0,b=0;
reset();
writebyte(0xCC);//跳过序列号
writebyte(0x44);//启动温度转换
reset();
writebyte(0xCC);
writebyte(0xBE);//读9个寄存器,前两个位温度
a=readbyte();//低位
b=readbyte();//高位
if(b>0x0f)//判断是否为负值
{
a=~a+1;
if(a==0)
b=~b+1;
elseb=~b;
flag=10;
}
elseflag=12;
temper[0]=a&0x0f;
a=a>>4;
temper[1]=b<<4;
temper[1]=temper[1]|a;
}
//*******************************************
//动态扫描显示函数
//*******************************************
voidscandisp()
{
unsignedchari,value;
for(i=0;i<8;i++)
{
P3=0xff;
value=table[dispbuf[i]];
if(i==3)
value|=0x80;
P0=value;
P3=scan[i];
delay(50);
}
}
//*******************************************
//主函数
//*******************************************
voidmain()
{
uchartemp,temp1;
while
(1)
{
scandisp();
readtemp();
temp1=temper[0];
temp=temper[1];
dispbuf[4]=ditab[temp1];
dispbuf[1]=temp/100;
dispbuf[3]=temp%10;
temp=temp/10;
dispbuf[2]=temp%10;
dispbuf[0]=flag;
dispbuf[5]=11;
}
}