1.1 设计背景
温度控制广泛应用于人们的生产和生活中,人们使用温度计来采集温度,通过人工操作加热、通风和降温设备来控制温度,这样不但控制精度低、实时性差,而且操作人员的劳动强度大。即使有些用户采用半导体二极管作温度传感器,但由于其互换性差,效果也不理想。在某些行业中对温度的要求较高,由于工作环境温度不合理而引发的事故时有发生。对工业生产可靠进行造成影响,甚至操作人员的安全。为了避免这些缺点,需要在某些特定的环境里安装数字温度测量及控制设备。本设计由于采用了新型单片机对温度进行控制,以其测量精度高,操作简单。可运行性强,价格低廉等优点,特别适用于生活,医疗,工业生产等方面的温度测量及控制。
本设计是一个数字温度测量及控制系统,能测柜内的温度,并能在超限的情况下进行控制、调整,并报警。保证环境保持在限定的温度中。
1.2电路的总体框图
温度控制系统采用A TC52八位机作为微处理单元进行控制。采用4X4键盘来设定监控范围,把设定温度的最高值和最低值存入单片机的数据存储器,用于作为监控的基准温度,还可以通过键盘完成温度检测功能的转换。实时的更新监控温度,并将温度用1602液晶屏显示。温度传感器把采集的信号与单片机里的数据相比较来控制温度控制器,当超出监控范围时就发出报警信号。
系统框图如图1.1:
图1.1第2章系统的硬件设计
2.1 系统的硬件选择
选择DS18B20作为本系统的温度传感器:
市面上有多种温度传感器,根据系统的设计要求,选择DS18B20作为本系统的温度传感器,选择单片机ATC52为测控系统的核心来完成数据采集、处理、显示、报警等功能。选用数字温度传感器DS18B20,省却了采样/保持电路、运放、数/模转换电路以及进行长距离传输时的串/并转换电路,简化了电路,缩短了系统的工作时间,降低了系统的硬件成本。
微处理器ATC52:ATC52是一个低功耗,高性能CMOS 8位单片机,片内含8k Bytes ISP(In-system programmable)的可反复擦写1000次的Flash只读程序存储器,器件采用ATMEL公司的高密度、非易失性存储技术制造,兼容标准MCS-51指令系统及80C51引脚结构,芯片内集成了通用8位处理器和ISP Flash存储单元,功能强大的微型计算机的ATC52可为许多嵌入式控制应用系统提供高性价比的解决方案。ATC52具有如下特点:40个引脚,8k Bytes Flash片内程序存储器,128 bytes的随机存取数据存储器(RAM),32个外部双向输入/输出(I/O)口,5个中断优先级2层中断嵌套中断,2个16位可编程定时计数器,2个全双工串行通信口,看门狗(WDT)电路,片内时钟振荡器。
该系统的总体设计思路如下:温度传感器DS18B20把所测得的温度发送到A TC52单片机上,经过51单片机处理,将把温度在显示电路上显示,本系统显示器为点阵字符LCD,1602液晶模块。本系统除了显示温度以外还可以设置两个个温度值,对所测温度进行监控,当温度高于或低于设定温度时,开始报警并启动相应程序。
相关外围电路包括蜂鸣器,键盘为4×4型,以及其他的升高或降低温度的电路。
图2.1系统总原理图
2.2 温度传感电路设计
DS18B20内部结构主要由四部分组成:位光刻ROM ,温度传感器,非挥发的温度报警触发器TH 和TL ,高速暂存器。DS18B20的管脚排列如图2.2所示。
图 2.2 DS18B20管脚图
在硬件上,DS18B20与单片机的连接有两种方法,一种是VCC 接外部电源,GND 接地,I/O 与单片机的I/O 线相连;另一种是用寄生电源供电,此时UDD 、GND 接地,I/O 接单片机I/O 。无论是内部寄生电源还是外部供电,I/O 口线要接5K Ω左右的上拉电阻.我们采用的是第一种连接方法,如图2.3所示:把DS18B20的数据线与单片机的13管脚连接,再加上上拉电阻。
图 2.3 温度传感电路图
1234
5
678I/O GND NC NC
NC
NC NC VCC DS18B20
DS18B 201
2
3
GND
I/O
VCC
表3-1 DS18B20控制命令
指令约定代码操作说明
温度转换44H 启动DS18B20进行温度转换
读暂存器BEH 读暂存器9个字节内容
写暂存器4EH 将数据写入暂存器的TH、TL字节
复制暂存器48H 把暂存器的TH、TL字节写到E2RAM中
重新调E2RAM B8H 把E2RAM中的TH、TL字节写到暂存器TH、TL字节读电源供电方式B4H 启动DS18B20发送电源供电方式的信号给主CPU CPU对DS18B20的访问流程是:先对DS18B20初始化,再进行ROM操作命令,最后才能对存储器操作,数据操作。DS18B20每一步操作都要遵循严格的工作时序和通信协议。如主机控制DS18B20完成温度转换这一过程,根据DS18B20的通讯协议,须经三个步骤:每一次读写之前都要对DS18B20进行复位,复位成功后发送一条ROM指令,最后发送RAM指令,这样才能对DS18B20进行预定的操作.
2.3 键盘电路的设计
如图2.4所示,用A TC52的并行口P1接4×4矩阵键盘,以P0作输入线,作输出线;液晶显示器上显示每个按键的“1---16”序号。对应的按键的序号排列如图3.4所示
图2.4
图2.5中微处理单元是ATC52单片机,X 1和X 2接12M 的两脚晶振,接两个30PF 的起振电容,J 1是上拉电阻.单片机的P 1口8位引脚与行列式键盘输出脚相连,控制和检测行列式键盘的输入.行线通过上拉电阻接到+5V 上,无按键按下时,行线处于高电平状态,有键按下时,行线的电平状态将由与此行线相连接的列线的电平决定.键盘输入的信息主要进程是:
1 CPU 判断是否有键按下.
2 确定是按下的是哪个键.
3 把此键所代表的信息翻译成计算机可以识别的代码或者其他的特征符号
.
图2.5
1 2 3 4 5 6 7 8 9 10 11 12 13
14
15
16
2.4 显示电路的设计
液晶显示器是一种将液晶显示器件,连接器件,集成电路,PCB线路板,背光源,结构器件装配在一起的组件。
根据显示内容和方式的不同可以分为,数显LCD,点阵字符LCD,点阵图形LCD在此设计中我们采用点阵字符LCD,这里采用常用的2行16个字的1602液晶模块。
图2.6
2.5 报警电路设计
采用蜂鸣器来报警电路简单并且经济适用。其原理图如图3.7
图3.7第3章系统的软件设计
3.1 系统的总体设计
主程序是系统的监控程序,在程序运行的过程中必须先经过初始化,包括键盘程序,中断程序,以及各个控制端口的初始化工作。流程图如4.1 所示。系统在初始化完成后就进入温度测量程序,实时的测量当前的温度并通过显示电路在LCD上显示。程序中以中断的方式来重新设定温度的上下限。根据硬件设计完成对温度的控制。按下4*4键盘上的1键可以选择修改上限或者下限,按2键可以对选择的位做加1,按键2可以对选择的位做减1,最后在1602上显示。系统软件设计的总体流程图
图3.1
3.2 程序的构架
程序总共分为4个板块,分别为程序的初始化,温度的转换获取,键盘的扫描,温度的显示。因为18B20每次转换温度在12为精度的时候需要最少750ms的时间为了节约CPU在这我采用定时器0中断进行计时,到达时间久获取温度并显示,可以达到实时的更新。对键盘循环扫描,没当有按键按下时就就不进行温度装换,不然会造成冲突。最后在主程序里面进行各得到的温度的显示和处理,当达到设定的报警温度时就实现上下限的报警。由51单片机支持多种语言编程,我选择用移植性较好的C语言来编写用于对硬件控制的源程序。
第4章程序的详细介绍
4.1 初始化
程序开始进行头文件定义,位定义,全局变量的设定,初始化函数的编写
/*****************************************************/
/***********头文件定义,位定义,全局变量的设定********/
/****************************************************/
#include #include #include #define uchar unsigned char #define uint unsigned int int count=0; /全局变量定义/ int buf[4]={20,0,15,0}; uchar flag=0,fun=0, key=0; float High=25.00,Low=15.00; sbit ds = P3^6; /位定义1602,蜂鸣器,18B20/ sbit bell = P3^7; sbit lcdrs = P2^0; sbit lcdrw = P2^1; sbit lcden = P2^2; sbit led = P3^3; void delay(uint z) /延迟函数 / { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } 5.2 键盘扫描函数 对P0口的各位高低电平的读数确定所按键的值并返回该值/*******************************/ /************键盘扫描***********/ /*******************************/ uchar keynum() { uchar num,temp; P0=0xfe; /置第一行为低/ temp=P0; temp=temp&0xf0; while(temp!=0xf0) /确定第一行是否有按键按下/ { flag=1; /置标志位为1/ delay(5); /去抖动操作/ temp=P0; temp=temp&0xf0; /与操作低四位清零/ while(temp!=0xf0) { temp=P0; switch(temp) { case 0xee:num=1;/确定所按键是哪一位/ break; /并返回为数字/ case 0xde:num=2; break; case 0xbe:num=3; break; case 0x7e:num=4; break; } while(temp!=0xf0) { temp=P0; temp=temp&0xf0; } } } P0=0xfd; temp=P0; temp=temp&0xf0; while(temp!=0xf0){ flag=1; delay(5); temp=P0; temp=temp&0xf0; while(temp!=0xf0) { temp=P0; switch(temp) { case 0xed:num=5; break; case 0xdd:num=6; break; case 0xbd:num=7; break; case 0x7d:num=8; break; } while(temp!=0xf0) { temp=P0; temp=temp&0xf0; } } } P0=0xfb; temp=P0; temp=temp&0xf0; while(temp!=0xf0) { flag=1; delay(5); temp=P0; temp=temp&0xf0; while(temp!=0xf0) { temp=P0; switch(temp) { case 0xeb:num=9;break; case 0xdb:num=10; break; case 0xbb:num=11; break; case 0x7b:num=12; break; } while(temp!=0xf0) { temp=P0; temp=temp&0xf0; } } } P0=0xf7; temp=P0; temp=temp&0xf0; while(temp!=0xf0) { flag=1; delay(5); temp=P0; temp=temp&0xf0; while(temp!=0xf0) { temp=P0; switch(temp) { case 0xe7:num=13; break; case 0xd7:num=14; break; case 0xb7:num=15; break; case 0x77:num=16; break; } } } P0=0xff; return num; } 4.3 1602显示函数 对使能端电平的设定,进行读写操作,1602的数据接口为P0口,因此我们只要在允许时将要写入的值传送到P0口就可以实现向1602写数据显示了。 void write_com(uchar com) /向1602写命令/ { lcdrw = 0; /写端口拉低/ lcdrs = 0; /读端口拉低/ lcden = 0; /使能端拉低/ P1 = com; /读P1口初值/ delay(5); /延迟等待/ lcden = 1; delay(5); lcden = 0; } void write_date(uchar date) 向1602写数据 { lcdrw = 0; lcdrs = 1; lcden = 0; P1 = date; delay(5); lcden = 1; delay(5); lcden = 0; } void init_1602() 1602初始化 { lcden = 0; write_com(0x38); write_com(0x0c);write_com(0x06); write_com(0x01); } void write_string(uchar *str,uchar length)向1602写一段字符 { uchar i; for(i=0;i write_date(str[i]); } } 4.4 18B20函数 向18B20发命令,读数据,通过使能端高低电平的改变进行数据传送的允许和禁止。可以实现对18B20的控制。 Void dsreset(void) /初始化/ { uint i; ds = 0; i = 103; while(i>0)i--; ds = 1; i = 4; while(i>0)i--; } bit tempreadbit(void) /读一位数据/ { uint i; bit dat; ds = 0;i++; ds = 1;i++;i++; dat = ds; i = 8; while(i>0)i--; return (dat); } uchar tempread(void) /读一字节数据/{ uchar i,j,dat; dat = 0; for(i=0;i<8;i++) { j = tempreadbit(); dat = (j<<7)|(dat>>1); } return (dat); } void tempwritebyte(uchar dat) /向18B20写一字节数据/ { uint i; uchar j; bit testb; for(j=0;j<8;j++) { testb = dat&0x01; dat = dat>>1; if(testb) { ds = 0; i++;i++; ds = 1; i=8;while(i>0)i--; } else { ds = 0; i = 8; while(i>0)i--; ds =1; i++;i++; } } void tempchange(void) /启动温度转换/ { dsreset(); delay(2); tempwritebyte(0xcc); tempwritebyte(0x44); } uint get_temp() /获取温度值到外部返回值为温度的100倍/ { uint temp; uchar a,b; float t; dsreset(); delay(1); tempwritebyte(0xcc); tempwritebyte(0xbe); a = tempread(); b = tempread(); temp = b; temp<<=8; temp = temp|a; t = temp * 0.0625; if(temp>0) temp = t*100 + 0.5; else temp = t*100 -0.5; return temp; } 4.5 显示函数 通过对温度获取函数的调用和1602的调用来显示温度值 void display(int v) { uchar count; uchar date[]={0,0,0,0,0};uint tmp = abs(v); date[0] = tmp / 10000; date[1] = tmp%10000/1000; date[2] = tmp%1000/100; date[3] = tmp%100/10; date[4] = tmp%10; write_com(0xc0+3); if(v<0) { write_string("- } else { write_string("+ } if(date[0]!=0) { write_date('0'+date[0]); } write_com(0xc0+5); for(count=1;count!=5;count++) { write_date('0'+date[count]); if(count==2) { write_date('.'); } } } 4.6键盘处理函数 可以实现加减1的操作,并赋值给上下限值和1602显示。 void keydeal() { int t; switch(key) { case 5: /功能键值加1/ fun++;fun=fun%5; /不大于4/ break; /***************处理按键值*******************/ case 6: switch(fun) /确认修改的位数/ { case 2: t=buf[1]; t++ ; if(t>=100) t=0; buf[1]=t; break; case 1: t=buf[0]; t++; if(t>=100) t=0; buf[0]=t; break; case 4: t=buf[3]; t++; if(t>=100) t=0; buf[3]=t; break; case 3: t=buf[2]; t++; if(t>=100) t=0; buf[2]=t; break; } break; case 7: switch(fun) /减键处理设置一个变量存要修改位值/ { case 2: t=buf[1]; t--; if(t<0) t=99; buf[1]=t; break; case 1: t=buf[0]; t--; if(t<0) t=99; buf[0]=t; break; case 4: t=buf[3]; t--; if(t<0) t=99; buf[3]=t; break; case 3: t=buf[2]; t--; if(t<0) t=99; buf[2]=t; break; } break; default: break; } /**********显示及赋值给上下限*********/ High=buf[0]*100+buf[1]; Low=buf[2]*100+buf[3]; write_com(0x80); write_date('H'); write_date('0'+buf[0]/10); write_date('0'+buf[0]%10); write_date('.');write_date('0'+buf[1]/10); write_date('0'+buf[1]%10); write_com(0x80+9); write_date('L'); write_date('0'+buf[2]/10); write_date('0'+buf[2]%10); write_date('.'); write_date('0'+buf[3]/10); write_date('0'+buf[3]%10); } void timer0() interrupt 1 { count++; TH0 = (0xffff-50000)/256; TL0 = (0xffff-50000)%256; } 4.7 主函数 主函数为整个程序的入口,实现初始化的调用,键盘扫描,温度转换的刷新及温度的显示 void main() { float wendu; TMOD=0x01; /定时器寄存器的初始化设置/ TH0 = (0xffff-50000)/256; TL0 = (0xffff-50000)%256; EA=1;ET0 = 1;TR0=1; tempchange(); init_1602(); while(1) { key=keynum(); if(flag==1) /有按键按下就进行键盘处理/ keydeal(); flag=0; if(count==18) /到达时间显示温度和进行下一次转换/ { count=0;write_com(0xc0); wendu=get_temp(); display(wendu); wendu=wendu/100; /温度处理/ tempchange(); /启动温度转换/ if(wendu>=High) /处理温度是否达到上下限的值/ bell=~bell; /报警处理/ if(wendu<=Low) led=~led; } } } 在本次毕业设计中,不仅自己付出了很多心血,也得到了很多老师和同学的支持,为我创造了很多有利条件,在这里,我要特别感谢我的老师王玲老师,在毕业设计的开始,王老师给了我很多帮助,指导我了解了很多单片机的相关知识,并在当我设计遇到困难时,及时的给予帮助和鼓励,同时,对我其他学科的鼓励也渗透在毕业设计的同时,给了我莫大的信心,通过这次设计,我对51单片机有了更多的理解,并通过实践和硬件的设计对单片机的运行和C语言程序的执行过程有了更深层次的理解。同时发现电路,数电,模电在运用中的重要性,在实现过程中遇到的困难的解决过程就是不断学习和经验的积累过程,让我不断的进步。 参考文献 [1] 张毅刚. MCS-51单片机原理及应用. 哈尔滨:哈尔滨工业大学出版社,2004 [2] 李玉峰,倪虹霞MCS-51系列单片机原理与接口技术. 北京:人民邮电出版社,2004 [3] 沙占友. 单片机外围电路设计. 北京:电子工业出版社,2003 [4] 吴金戌,沈庆阳,郭庭吉.《8051单片机实践与应用》[M].北京:清华大学出版社,2002. [5] 李群芳,张士军,黄建《单片微型计算机》(第三版).北京:电子工业出版社,2008. [6] 韩国栋冯长江等《Altium Designer Winter 09 电路设计与入门提高》北京:化学工业出版社 2009.附录元器件清单 名称型号封装形式数量 单片机A TC51 DIP40 1个LCD显示器1602 DIP16 1个 晶振11.0592M MAXIAL0.4 1个 三极管8055 TO—92B 1个 电阻排10k X8 DIP8 1个 电阻若干个按键ANJIAN 16个温度传感器DS18B20 PORT—3 1片 瓷片电容30pF 2片下载本文