温度测试系统+电路图++程序.docx
《温度测试系统+电路图++程序.docx》由会员分享,可在线阅读,更多相关《温度测试系统+电路图++程序.docx(24页珍藏版)》请在冰豆网上搜索。
温度测试系统+电路图++程序
温度测量系统设计
班级_________
学号_____________
姓名____________
指导老师_______________
温度测量系统
摘要:
该温度控制系统采用单片机进行温度实时采集。
温度信号由“一线总线”数字化温度传感器DS18B20提供,DS18B20在-10~+85°C范围内,固有测温分辨率为0.5℃。
系统具备较高的测量精度和控制精度。
关键字:
AT89S52 DS18B20 温度测试
1.系统方案选择和论证
1.1题目要求
设计并制作一个温度自动控制系统,控制对象为1L净水,容器为搪瓷器皿。
温度可以在一定范围内由人工设定,并能在环境温度降低时实现自动控制,以保持设定的温度基本不变。
1.1.1 基本要求
(1)温度设定范围为40~90℃,最小区分度为1℃,标定温度≤1℃。
(2)用十进制数码管显示实际温度。
1.1.2 发挥部分(未实现)
(1)采用适当的控制方法,当设定温度突变(由40℃提高到60℃)时,减小系统的
调节时间和超调量。
(2)温度控制的静态误差≤0.2℃。
(3)在设定温度发生突变(由40℃提高到60℃)时,自动打印温度随时间变化的曲
线。
1.1.3 说明
(1)如果采用单片机控制,允许使用已有的单片机最小系统板。
(2)数码显示部分可以使用数码显示模块。
(3)在设计报告附一篇4000字以内的报告摘要。
1.2 系统基本方案
根据题目要求系统模块分可以划分为:
温度测量模块,显示电路模块,加热模块,控制模块,系统的框图如图1.2.1所示。
为实现各模块的功能,分别做了几种不同的设计方案并进行了论证。
1.2.1 各模块电路的方案选择及论证
(1)控制器模块
根据题目要求,控制器主要用于对温度测量信号的接受和处理、控制电热丝和风扇使控制对象满足设计要求、控制显示电路对温度值实时显示以及控制键盘实现对温度值的设定等。
对控制器的选择有以下三种方案:
图1.2.1系统基本模块方框图
方案一:
采用FPGA作为系统控制器。
FPGA功能强大,可以实现各种复杂的逻辑功能,规模大,密度高,它将所有器件集成在一块芯片上,减少了体积,提高了稳定性,并且可应用EDA软件仿真、调试,易于进行功能扩展。
FPGA采用并行的I/O口方式,提高了系统的处理速度,适合作为大规模实时系统控制核心。
由温度传感器送来的温度信号,经FPGA程序对其进行处理。
但由于本设计对数据处理的速度要求不高,FPGA的高速处理的优势得不到充分体现,并且其成本偏高,引脚较多,硬件电路布线复杂。
方案二:
采用模拟运算放大器组成PID控制系统。
但要附加显示、温度设定等功能,要附加许多电路,稍显麻烦。
方案三:
采用ATMEL公司的AT89S52作为系统控制器。
单片机算术运算功能强,软件编程灵活、自由度大,可用软件编程实现各种算法和逻辑控制,并且其功耗低、体积小、技术成熟和成本低等优点。
基于以上分析拟订方案二,由AT89S52作为控制核心,对温度采集。
(2)温度采集模块
题目要求温度静态误差小于等于0.2℃,温度信号为模拟信号,本设计要对温度进行控制和显示,所以要把模拟量转换为数字量。
该温度采集模块有以下三种方案:
方案一:
利用热电阻传感器作为感温元件,热电阻随温度变化而变化,用仪表测量出热电阻的阻值变化,从而得到与电阻值相应的温度值。
最常用的的是铂电阻传感器,铂电阻在氧化介质中,甚至在高温的条件下其物理,化学性质不变。
由铂电阻阻值的变化经小信号变送器XTR101将铂电阻随温度变化的转换为4~20mA线形变化电路,再将电流信号转化为电压信号,送到A/D转换器——ADC0809.即将模拟信号转换为数字信号。
该方案线性度优于0.01%。
方案二:
采用温度传感器AD590K。
AD590K具有较高精度和重复性,良好的非线性保证±0.1℃的测量精度。
加上软件非线性补偿可以实现高精度测量。
AD590将温度转化为电流信号,因此要加相应的调理电路,将电流信号转化为电压信号。
送入8为A/D转换器,可以获得255级的精度,基本满足题目要求。
方案三:
采用数字温度传感器DS18B20。
DS18B20为数字式温度传感器,无需其他外加电路,直接输出数字量。
可直接与单片机通信,读取测温数据,电路简单。
如图1.2.2所示。
图1.2.2DS18B20测温电路
基于以上分析和现有器件所限,温度采集模块选用方案三。
DS18B20与传统的热敏电阻相比,他能够直接读出被测温度并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。
并且从DS18B20读出的信息或写入DS18B20的信息仅需要一根口线(单线接口)读写,因而使用DS18B20可使系统结构更趋简单,可靠性更高。
他在测温精度、转换时间、传输距离、分辨率等方面带来了令人满意的效果。
(3)显示模块
根据题目要求,温度要能实时显示温度值。
对键盘和显示模块有下面两种方案:
方案一:
采用液晶显示屏和通用矩阵键盘。
液晶显示屏(LCD)具有功耗小、轻薄短小无辐射危险,平面直角显示以及影象稳定不闪烁,可视面积大,画面效果好,抗干扰能力强等特点。
但由于只需显示三位温度值,信息量比较少,且由于液晶是以点阵的模式显示各种符号,需要利用控制芯片创建字符库,编程工作量大,控制器资源占用较多,其成本也偏高。
方案二:
采用三位LED七段数码管分别显示温度的十位、个位和小数位。
按键采用单列3按键进行温度设定。
数码管具有:
低能耗、低损耗、低压、寿命长、耐老化,对外界环境要求较低。
同时数码管采用BCD编码显示数字,程序编译容易,资源占用较少。
根据以上论述,采用方案二。
本系统中,采用了数码管的动态显示,节省单片机的内部资源。
1.2.2 系统各模块的最终方案
根据以上分析,结合器件和设备等因素,确定如下方案:
1.采用AT89S52单片机作为控制器,分别对温度采集、LED显示。
2.温度测量模块采用数字温度传感器DS18B20。
此器件经软件设置可以实现高分辨率测量。
3.显示用LED数码管显示实时温度值。
图1.2.3系统基本框图
系统的基本框图如图1.2.3所示。
CPU(AT89S52)首先写入命令给DS18B20,然后DS18B20开始转换数据,转换后通过89S52来处理数据。
数据处理后的结果就显示到数码管上。
2. 硬件设计与实现
本系统的执行方法是循环查询执行的,键盘扫描也是用循环查询的办法,由于本系统对实时性要求不是很高,所以没有用到中断方式来处理。
2.1 主要单元电路的设计
2.1.1 温度采集部分设计
本系统采用半导体温度传感器作为敏感元件。
传感器我们采用了DS18B20单总线可编程温度传感器,来实现对温度的采集和转换,直接输出数字量,可以直接和单片机进行通讯,大大简化了电路的复杂度。
DS18B20应用广泛,性能可以满足题目的设计要求。
DS18B20的测温电路如图2.2.1所示。
图2.2.1DS18B20测温电路
(1)DSI8B20的测温功能的实现:
其测温电路的实现是依靠单片机软件的编程上。
当DSI8B20接收到温度转换命令后,开始启动转换。
转换完成后的温度值就以16位带符号扩展的二进制补码形式存储在高速暂存存储器的0,1字节。
单片机可通过单线接口读到该数据,读取时低位在前,高位在后,数据格式以0.0625℃/LSB形式表示。
温度值格式如表2.2.1所示,其中“S”为标志位,对应的温度计算:
当符号位S=0时,直接将二进制位转换为十进制;当S=1时,先将补码变换为原码,再计算十进制值。
DSI8B20完成温度转换后,就把测得的温度值与TH做比较,若T>TH或T表2.2.1DS18B20温度值格式表
LSByte
MSByte
S
S
S
S
S
(2)、DSl820工作过程中的协议
初始化->RoM操作命令->存储器操作命令->处理数据
①初始化单总线上的所有处理均从初始化开始
②ROM操作命令 总线主机检测到DSl820的存在便可以发出ROM操作命令之一这些命令如表2.2.2所示
表2.2.2ROM操作命令表
指令
代码
ReadROM(读ROM)
33H
MatchROM(匹配ROM)
55H
SkipROM(跳过ROM]
CCH
SearchROM(搜索ROM)
F0H
Alarmsearch(告警搜索)
ECH
③存储器操作命令如表2.2.3所示
表2.2.3存储器操作命令表
指令
代码
WriteScratchpad(写暂存存储器)
4EH
ReadScratchpad(读暂存存储器)
BEH
CopyScratchpad(复制暂存存储器)
48H
ConvertTemperature(温度变换)
44H
RecallEPROM(重新调出)
B8H
ReadPowersupply(读电源)
B4H
(3)温度转换算法及分析
由于DS18B20转换后的代码并不是实际的温度值,所以要进行计算转换。
温度高字节(MSByte)高5位是用来保存温度的正负(标志为S的bit11~bit15),高字节(MSByte)低3位和低字节来保存温度值(bit0~bit10)。
其中低字节(LSByte)的低4位来保存温度的小数位(bit0~bit3)。
由于本程序采用的是0.0625的精度,小数部分的值,可以用后四位代表的实际数值乘以0.0625,得到真正的数值,数值可能带几个小数位,所以采取小数舍入,保留一位小数即可。
也就说,本系统的温度精确到了0.1度。
算法核心:
首先程序判断温度是否是零下,如果是,则DS18B20保存的是温度的补码值,需要对其低8位(LSByte)取反加一变成原码。
处理过后把DS18B20的温度Copy到单片机的RAM中,里面已经是温度值的Hex码了,然后转换Hex码到BCD码,分别把小数位,个位,十位的BCD码存入RAM中。
2.1.2 显示部分
本设计中采用动态显示方式驱动4个七段数码管,分别显示温度的十位、个位和小数位。
数码管采用共阴极,由于AT89S52单片机每个I/O的拉电流只有1—2mA。
所以在位码和段码都加上了同相驱动器。
图2.2.4显示部分原理图
3. 系统软件设计
系统的软件设计采用汇编语言,对单片机进行变成实现各项功能。
主程序对模块进行初始化,而后调用读温度、处理温度、显示各模块。
用的是循环查询方式,来显示温度。
3.1读取DS18B20温度模块子程序
每次对DA18B20操作时多要按造DS18B20工作过程中的协议进行。
初始化->RoM操作命令->存储器操作命令->处理数据程序流程图如图3.1.1所示。
3.2 数据处理子程序
由于DS18B20转换后的代码并不是实际的温度值,所以要进行数据处理。
由于本程序采用的是0.0625的精度,小数部分的值,可以用后四位代表的实际数值乘以0.0625,得到真正的数值,数值可能带几个小数位,所以采取四舍五入,保留一位小数即可。
也就说,本系统的温度精确到了0.1度。
首先程序判断温度是否是零下,如果是,则DS18B20保存的是温度的补码值,需要对其低8位(LSByte)取反加一变成原码。
处理过后把DS18B20的温度Copy到单片机的RAM中,里面已经是温度值的Hex码了,然后转换Hex码到BCD码,分别把小数位,个位,十位的BCD码存入RAM中。
数据处理子程序流程图如图3.2.1所示。
图3.1.1 读取DS18B20温度子程序流程图
3.3主程序流程图
总模块流程图如图3.1.1所示。
本软件设计采用循环查询来处理各个模块,温度是缓慢变化量所以可以满足性能要求。
图3.1.1所示为系统主程序流程图
图3.1.1 主程序流程图
4.系统测试
4.1静态温度测试
测试方式:
由于种种条件的限制,采用模拟加热方式进行测试。
利用继电器的指示灯来显示继电器的动作。
红灯表示加热,绿灯表示降温。
测量仪器:
空调温度显示屏
测试结果如表4.1.1所示:
表4.1.1测试结果数据
标准温度/℃
20
22
25
27
28
测量温度/℃
19.8
22.1
24.7
26.8
27.6
误差/℃
0.2
0.1
0.3
0.2
0.4
4.2动态温控测量
测试方式:
加热方式用体温对传感器DS18B20进行加热。
设定控制温度,记录超调温度,稳态误差。
超调温度与加热的功率有关,这里不再测量。
测量仪器:
空调温度显示屏
测量结果如表4.2.1所示:
表4.2.1测试结果数据
设定温度/℃
29
30
33
35
超调温度/℃
1.3
0.9
1.1
0.6
稳态误差/℃
0.2
0.4
0.2
0.4
4.3结果分析
有以上的测量结果可见,系统基本上达到了所要求的指标,静态测温的精度主要由DS18B20来决定。
在控温指标中,影响系统的性能的因素很多。
最关键的是加热系统本身的物理性质及控制算法。
由于条件的限制,在本设计中采用体温进行测试。
附录1:
系统硬件原理图
#include//包含单片机寄存器的头文件
#include//包含_nop_()函数定义的头文件
#include
#include
unsignedcharcodedispcode0[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f};
unsignedchardispcode1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,
0xfd,0x87,0xff,0xef};
unsignedcharTL;//储存暂存器的温度低位
unsignedcharTH;//储存暂存器的温度高位
unsignedcharTN;//储存温度的整数部分
unsignedintTD,i;//储存温度的小数部分
voiddelay1ms()
{
unsignedchari,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
voiddelaynms(intn)
{
unsignedchari;
for(i=0;idelay1ms();
}
sbitDQ=P2^0;
unsignedchartime_DS18B20;//设置全局变量,专门用于严格延时
bitInit_DS18B20(void)
{
bitflag_DS18B20;//储存DS18B20是否存在的标志,flag=0,表示存在;flag=1,表示不存在
DQ=1;//先将数据线拉高
for(time_DS18B20=0;time_DS18B20<2;time_DS18B20++)//略微延时约6微秒
;
DQ=0;//再将数据线从高拉低,要求保持480~960us
for(time_DS18B20=0;time_DS18B20<200;time_DS18B20++)//略微延时约600微秒
;//以向DS18B20发出一持续480~960us的低电平复位脉冲
DQ=1;//释放数据线(将数据线拉高)
for(time_DS18B20=0;time_DS18B20<10;time_DS18B20++)
;//延时约30us(释放总线后需等待15~60us让DS18B20输出存在脉冲)
flag_DS18B20=DQ;//让单片机检测是否输出了存在脉冲(DQ=0表示存在)
for(time_DS18B20=0;time_DS18B20<200;time_DS18B20++)//延时足够长时间,等待存在脉冲输出完毕
;
return(flag_DS18B20);//返回检测成功标志
}
unsignedcharReadOneChar()
{
unsignedchari=0;
unsignedchardat;//储存读出的一个字节数据
for(i=0;i<8;i++)
{
DQ=1;//先将数据线拉高
_nop_();//等待一个机器周期
DQ=0;//单片机从DS18B20读书据时,将数据线从高拉低即启动读时序
dat>>=1;
_nop_();//等待一个机器周期
DQ=1;//将数据线"人为"拉高,为单片机检测DS18B20的输出电平作准备
for(time_DS18B20=0;time_DS18B20<3;time_DS18B20++);//延时约6us,使主机在15us内采样
if(DQ==1)
dat|=0x80;//如果读到的数据是1,则将1存入dat
else
dat|=0x00;//如果读到的数据是0,则将0存入dat
//将单片机检测到的电平信号DQ存入r[i]
for(time_DS18B20=0;time_DS18B20<8;time_DS18B20++)
;//延时3us,两个读时序之间必须有大于1us的恢复期
}
return(dat);//返回读出的十进制数据
}
WriteOneChar(unsignedchardat)
{
unsignedchari=0;
for(i=0;i<8;i++)
{
DQ=1;//先将数据线拉高
_nop_();//等待一个机器周期
DQ=0;//将数据线从高拉低时即启动写时序
DQ=dat&0X01;//利用与运算取出要写的某位二进制数据,
//并将其送到数据线上等待DS18B20采样
for(time_DS18B20=0;time_DS18B20<10;time_DS18B20++)
;//延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样
DQ=1;//释放数据线
for(time_DS18B20=0;time_DS18B20<1;time_DS18B20++)
;//延时3us,两个写时序间至少需要1us的恢复期
dat>>=1;//将dat中的各二进制位数据右移1位
}
for(time_DS18B20=0;time_DS18B20<4;time_DS18B20++)
;//稍作延时,给硬件一点反应时间
}
voiddisplay(unsignedcharx,y)
{
unsignedcharj,k,l,m,n,o;//j,k,l分别储存温度的百位、十位和个位
unsignedinti;
j=x/100;//取百位
k=(x%100)/10;//取十位
l=x%10;//取个位
m=y/100;
n=(y%100)/10;
o=y/10;
if(x>=100)
{
P1=0X01;
P0=~dispcode0[j];
for(i=0;i<1000;i++);
P1=0X02;
P0=~dispcode0[k];
for(i=0;i<1000;i++);
if(o>=5)
n+=1;
else
;
if(n>=5)
m+=1;
else
;
if(m>=5)
l+=1;
else
;
P1=0X04;
P0=~dispcode0[l];
for(i=0;i<1000;i++);
}
elseif((x>=10)&&(x<100))
{
P1=0X01;
P0=~dispcode0[k];
for(i=0;i<1000;i++);
P1=0X02;
P0=~dispcode1[l];
for(i=0;i<1000;i++);
if(o>=5)
n+=1;
else
;
if(n>=5)
m+=1;
else
;
P1=0X04;
P0=~dispcode0[m];
for(i=0;i<1000;i++);
}
elseif((x>=0)&&(x<10))
{
P1=0X01;
P0=~dispcode1[l];
for(i=0;i<1000;i++);
P1=0X02;
P0=~dispcode0[m];
for(i=0;i<1000;i++);
if(o>=5)
n+=1;
else
;
P1=0X04;
P0=dispcode0[n];
for(i=0;i<1000;i++);
}
}
voiddisplayfu(unsignedcharx,y)
{
unsignedchark,l,m,n,o;//j,k,l分别储存温度的百位、十位和个位
P1=0X01;
P0=~0x40;
for(i=0;i<1000;i++);
k=(x%100)/10;//取十位
l=x%10;//取个位
m=y/100;
n=(y%100)/10;
o=y/10;
if(x>=10)
{
P1=0X02;
P0=~dispcode0[k];
for(i=0;i<1000;i++);
if(o>=5)
n+=1;
else
;
if(n>=5)
m+=1;
else
;
if(m>=5)
l+=1;
else
;
P1=0X04;
P0=~dispcode0[l];
for(i=0;i<1000;i++);
}
elseif(x<10)
{
P1=0X02;
P0=~dispcode1[l];
for(i=0;i<1000;i++);
if(o>=5)
n+=1;
else
;
if(n>=5)
m+=1;
else
;
P1=0X04;
P0=~dispcode0[m];
for(i=0;i<1000;i++);
}
}
voidReadyReadTemp(void)
{
Init_DS18B20();//将DS18B20初始化
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneChar(0x44);//启动温度转换
for(time_DS18B20=0;time_DS18B20<100;time_DS18B20++)
;//温度转换需要一点时间
Init_DS18B20();//将DS18B20初始化
WriteOneChar(0xCC);//跳过读序号列号的操作
WriteOneCh