资源描述
武汉理工大学《计算机控制技术》课程设计说明书
目录
1 意义与要求 1
1.1 实际意义 1
1.2 技术要求 1
2 设计内容及步骤 1
2。1 方案设计 1
2。2 详细设计 2
2。2。1 主要硬件介绍 2
2。2。2 电路设计方法 3
2.2.3 绘制流程图 6
2.2。4 程序设计 7
2.3 调试和仿真 7
3 结果分析 8
4 课程设计心得体会 9
参考文献 10
附录 11
电加热炉温度控制系统设计
1 意义与要求
1。1 实际意义
在现实生活当中,很多场合需要对温度进行智能控制,日常生活中最常见的要算空调和冰箱了,他们都能根据环境实时情况,结合人为的设定,对温度进行智能控制。工业生产中的电加热炉温度监控系统和培养基的温度监控系统都是计算机控制系统的典型应用。通过这次课程设计,我们将自己动手设计一个小型的计算机控制系统,目的在于将理论结合实践以加深我们对课本知识的理解。
1。2 技术要求
要求利用所学过的知识设计一个温度控制系统,并用软件仿真。功能要求如下:
(1)能够利用温度传感器检测环境中的实时温度;
(2)能对所要求的温度进行设定;
(3)将传感器检测到得实时温度与设定值相比较,当环境中的温度高于或低于所设定的温度时,系统会自动做出相应的动作来改变这一状况,使系统温度始终保持在设定的温度值。
2 设计内容及步骤
2.1 方案设计
要想达到技术要求的内容,少不了以下几种器件:单片机、温度传感器、LCD显示屏、直流电动机等。其中单片机用作主控制器,控制其他器件的工作和处理数据;温度传感器用来检测环境中的实时温度,并将检测值送到单片机中进行数值对比;LCD显示屏用来显示温度、时间的数字值;直流电动机用来表示电加热炉的工作情况,转动表示电加热炉通电加热,停止转动表示电加热炉断电停止加热。
整体思路是这样的:首先我们通过按键设定所需要的温度值,然后利用温度传感器检测电加热炉的实时加热温度,并送至单片机与设定值进行比较。若检测值小于设定值,则无任何动作,电加热炉继续导通加热;若检测值大于设定值,则单片机控制光电耦合器导通,继电器动作,电加热炉断电停止加热。一旦炉温低于设定值,单片机又控制光电耦合器断开,继电器开关分离,电加热炉开始导通加热。这个过程中所设定的温度值和传感器检测到得温度值都要在LCD显示屏上显示出来,以方便操作人员观察。另外,还可以加上时钟模块,以方便计时。
这个设计思路相对比较简单,利用所学过的知识容易实现,加上光电耦合器用于隔离强电和弱电,比较安全,正好符合我们自动化专业用弱电控制强电的目的,正所谓学以致用。
2。2 详细设计
2.2。1 主要硬件介绍
1.单片机
这里选用AT89C51单片机作为控制系统的处理器。AT89C51是一种带4K字节闪存可编程可擦除只读存储器的低电压、高性能CMOS 8位微处理器.
2.温度传感器
温度传感器有很多种型号,这里我选用DS18B20温度传感器。数字温度传感器DS18B20具有独特的单总线接口方式,支持多节点,使分布式温度传感器设计大为简化.测温时无需任何外围原件,可以通过数据线直接供电,具有超低功耗工作方式。测温范围为—55到+125摄氏度,可直接将温度转换值以16位二进制数字码的方式串行输出,因此特别适合单线多点温度测量系统。由于传输的是串行数据,可以不需要放大器和A/D转换器,因而这种测温方式大大提高了各种温度测控系统的可靠性,降低了成本,缩小了体积。
3.开关器件
由于单片机与电动机之间需要用开关器件连接,并且前者用弱电控制,后者由强电控制,这就尤其需要注意安全问题。于是我想到了在课本中学过的高性能安全开关器件光电耦合器.光电耦合器是由一个发光器件和和一个光电转换器件组成,这里所用的光电耦合器OPTOCOUPLER-NPN是由一个发光二极管和一个光敏晶体管所组成。当发光二极管发光,就会使得光敏晶体管导通,继电器通电动作,将开关吸合,电动机回路断开。
2.2。2 电路设计方法
1.显示部分电路
显示电路截图如下图所示。
图2。1 显示部分电路图
这里我选用LCDLM016L液晶显示屏作为系统的显示器件,如图所示,LCDLM016L采用标准的16脚接口,仿真时隐藏了背光正极和背光负极两个引脚.它通过D0-D78位数据端来与单片机进行数据和指令传输,这里我们将它与单片机的P0口连接.
在显示屏上显示的内容包括设定的温度值SET、传感器检测到的环境温度SA以及时钟,这个时钟是可以调整的,这样方便工作人员在对系统进行操作时有一个时间概念。
2.温度检测电路
温度传感器与单片机的连接情况如下图所示。
图2.2 温度检测电路图
温度传感器18B20将检测到的环境实时温度进行A/D转换和放大,然后串行送入单片机P1。7口,便于单片机将此数值与设定的温度值进行比较,然后先做出相应反应。在仿真时,我们只能通过按18B20上的加减按钮来调节实时温度,是一个模拟的过程.
3.键盘电路
键盘电路如下图所示.
图2。3 键盘电路图
这里减排设计得比较简单,“MS”键是切换调整对象的,调整对象包括时、分、温度设定值三项,“+”键是向上加调整对象的值,“—”键是向下减调整对象的值,“ON/OFF”键是打开和关闭系统自动调节功能的开关键。
4.电气开关及工作电路
电器开关及工作电路如下图所示。
图2.4 电气开关及工作电路图
如图所示,光电耦合器1脚接电源,2脚接单片机P3.7脚。工作过程用以下三个阶段来描述:
(1)单片机将温度传感器送入的值与设定值进行比较,若送入值小于设定值,则P3.7脚保持高电平,这样发光二极管不发光,光敏晶体管保持高阻态,继电器也不会工作,电动机和灯泡维持导通,相当于电炉继续加热,指示灯亮;
(2)一旦送入值比设定值大,单片机将会控制P3。7脚变为低电平,发光二极管导通发光,光敏晶体管受光照影响导通,继而继电器工作,电磁铁将单刀双掷开关吸向左端,使电动机和灯泡同时停止工作,这就相当于电炉断电,停止加热;
(3)电炉短路一段时间后,必然导致炉温降低,而温度传感器DS18B20在不间断地检测炉温,当检测值低于设定值后,单片机又控制P3。7脚恢复高电平,光电耦合器恢复高阻态,继电器断电,单刀双掷开关被弹回右端,电动机和灯泡又开始工作,这相当于电炉从新开始加热.
2.2.3 绘制流程图
N
N
Y
Y
将P3.7口置1
设定值<采集值?
将P3.7口置0
设定值>=采集值?
送入单片机进行温度值比较
按键扫描、温度采集
时钟定时器0初始化,DS18B20初始化
延时500ms启动
初始化P1口,初始化24C02
LCD初始化
读出24C02保存的数据赋于K
开始
2。2。4 程序设计
由于整个程序工程量比较大,我采用模块化设计方法来设计这个程序.首先定义在后面将会用到的变量,不可能一次定义准确,所以边定义边补充。然后编写子函数,包括LCM初始化子函数、显示指定坐标的一个字符子函数、ds18b20初始化函数、ds18b20延迟子函数、读取ds18b20当前温度子函数、液晶显示子函数、键盘扫描子函数、设定工作模式子函数、按键加法子函数、按键减法子函数、24C02读写驱动程序、定时器t0中断子函数等子程序,最后是主函数。
2。3 调试和仿真
在Keil软件中编写完程序后,编译生成。Hex文件,单片机可以执行.Hex文件.在Protues软件中,给单片机加载所生成的。Hex文件,按下运行按钮,系统开始仿真。系统仿真截图如下图所示。
图2。5系统仿真图(一)
上一张是当温度采样值小于设定值,电热炉处于工作状态时的仿真截图。以下这张是当温度采样值高于设定值后,系统自动做出反应,使电热炉断电停止工作的仿真截图。
图2。6系统仿真图(二)
3 结果分析
由以上仿真结果可以知道,此次的设计基本成功。当采样温度低于设定值的时候,系统不会对电热炉做出相应动作,电热炉保持加热。一旦采样温度高于设定值,系统就会做出反应,使电加热炉断电停止加热。当温度降下来后,系统又会自动控制电加热炉重新开始加热.系统的反应速度也是十分精确的,会在很短的时间内作出相应动作。另外,由于在电路中加入了EPROM24C02,使得该系统具有掉电保护功能,来电后自动恢复正常工作.除此之外,该系统还有一个比较实用的小功能—电子钟,这样的话工作人员可以利用它准确掌握系统已经工作的时间,也就是说可以把它当做一个定时器来用.在安全保护方面,该系统也有相当不错的表现,由于使用了光电耦合器和就电磁继电器,将强电部分和弱电部分充分隔离,十分安全。综合以上分析,该系统的设计十分成功.
4 课程设计心得体会
一个星期很快就过去了,计算机控制技术课程设计也告一段落.本次课程设计,我的题目是《设计一个电加热炉温度控制系统》。说到电加热炉,我们都比较熟悉,在日常生活中我们经常用到,特别是冬天用它来煮火锅。我们也会发现这样一个问题,一般的电加热炉是没有温度自动控制的,当温度上升到我们需要的程度时,它仍然继续加热,这不仅会影响到加热效果,还会造成电能的浪费。那么就有必要设计一种能自动调节炉温的系统,把它应用到日常生活中,将会给人们带来极大的方便。
在设计的过程中,我也遇到一些麻烦,比如说怎样来实现电动机回路的自动通断调节、怎样来实现时钟的调整等等,这些问题都令我十分棘手。通过去图书馆查阅相关资料和上网搜索各硬件的原理以及应用,我最终都一一解决了这些问题。由于我们是三个同学做同一个题目,在设计过程中,我们遇到困难的时候也经常相互讨论,相互请教,最终一起解决问题,在此也感谢我的“战友”们。
总的来说,此次课程设计的过程比较轻松,从拿到问题到彻底解决问题,这是一个令人振奋并享受的过程.经过去图书馆大量的查阅书籍,我也学到了很多在课本上没有的知识,收获颇丰。这段过程让我懂得了一个道理,那就是学生要学的绝对不该仅仅是课本上的东西,有些东西只有走进图书馆,你才可能学习到。也只有这样,我们才能成为一个见多识广、渊博的人。
参考文献
[1] 于海生.微型计算机控制技术.清华大学出版社,2004
[2] 谭浩强.C程序设计(第三版)。 清华大学出版社,2006
[3] 戴焯。 传感与检测技术. 武汉理工大学出版社,2006
[4] 张毅刚. 单片机原理及应用。 高等教育出版社,2003
[5] 柯节成。 简明电子元件器件手册. 高等教育出版社,2005
附录
系统的完整程序如下:
/***********************************************************
电加热炉温度控制系统
问题描述:当温控开关打开时,若测得环境温度大于设定温度,则继电器吸合,电加热炉停止工作;若测得环境温度小于设定温度,则继电器释放,电加热炉继续工作。
***********************************************************/
#include〈reg51.h〉
#include<intrins.h>
#include 〈absacc。h>
#define uchar unsigned char
#define uint unsigned int
#define BUSY 0x80 //lcd忙检测标志
#define DATAPORT P0 //定义P0口为LCD通讯端口
#define PLAYE_ADDR XBYTE[0XBFFF] //语音报警地址
sbit RED_ALARM=P1^0; //红色指示灯
sbit WRITE_ALARM=P1^1; //白色指示灯
sbit GREEN_ALARM=P1^2; //绿色指示灯
sbit BLUE_ALARM=P1^3;
sbit P1_4=P1^4; //时钟调整
sbit P1_5=P1^5; //时钟加
sbit P1_6=P1^6; //时钟减
sbit DQ = P1^7; //定义ds18b20通信端口
sbit LCM_RS=P2^0; //数据/命令端
sbit LCM_RW=P2^1; //读/写选择端
sbit LCM_EN=P2^2;
sbit sda=P2^3; //IO口定义
sbit scl=P2^4; //LCD使能信号
sbit ad_busy=P3^2; //adc中断方式接口
sbit RECLED_EOC=P3^5; //ISD1420放音结束查询标志
sbit OUT=P3^7;
uchar ad_data; //ad采样值存储
uchar seconde; //定义并初始化时钟变量
uchar minite;
uchar hour;
uchar mstcnt=0;
uchar temp1,temp2,temp; //温度显示变量
uchar t,set;
uchar K;
bit ON_OFF=0;
bit outflag;
bit write=0;
uchar code str0[]={”—-- : : -—— "};
uchar code str1[]={"SET: C SA: . C”};
void delay_LCM(uint); //LCD延时子程序
void initLCM( void); //LCD初始化子程序
void lcd_wait(void); //LCD检测忙子程序
void WriteCommandLCM(uchar WCLCM,uchar BusyC); //写指令到ICM子函数
void WriteDataLCM(uchar WDLCM); //写数据到LCM子函数
void DisplayOneChar(uchar X,uchar Y,uchar DData) //显示指定坐标的一个字符子函数
void DisplayListChar(uchar X,uchar Y,uchar code *DData);//显示指定坐标的一串字符子函数
void init_timer0(void); //定时器初始化
void displayfun1(void);
void displayfun2(void);
void displayfun3(void);
void displayfun4(void);
void keyscan(void ); //键盘扫描子程序
void set_adj(void);
void inc_key(void);
void dec_key(void);
void delay_18B20(unsigned int i);
void Init_DS18B20(void) ;
uchar ReadOneChar(void);
void WriteOneChar(unsigned char dat);
void ReadTemperature(void);
void ad0809(void);
void playalarm(void);
/*********延时K*1ms,12。000mhz**********/
void delay_LCM(uint k)
{
uint i,j;
for(i=0;i〈k;i++)
{
for(j=0;j<60;j++)
{;}
}
}
/**********写指令到LCM子函数************/
void WriteCommandLCM(uchar WCLCM,uchar BusyC)
{
if(BusyC)lcd_wait();
DATAPORT=WCLCM;
LCM_RS=0; // 选中指令寄存器
LCM_RW=0; // 写模式
LCM_EN=1;
_nop_();
_nop_();
_nop_();
LCM_EN=0;
}
/**********写数据到LCM子函数************/
void WriteDataLCM(uchar WDLCM)
{
lcd_wait( ); //检测忙信号
DATAPORT=WDLCM;
LCM_RS=1; // 选中数据寄存器
LCM_RW=0; // 写模式
LCM_EN=1;
_nop_();
_nop_();
_nop_();
LCM_EN=0;
}
/***********lcm内部等待函数*************/
void lcd_wait(void)
{
DATAPORT=0xff;
LCM_EN=1;
LCM_RS=0;
LCM_RW=1;
_nop_();
while(DATAPORT&BUSY)
{ LCM_EN=0;
_nop_();
_nop_();
LCM_EN=1;
_nop_();
_nop_();
}
LCM_EN=0;
}
/**********LCM初始化子函数***********/
void initLCM( )
{
DATAPORT=0;
delay_LCM(15);
WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
delay_LCM(5);
WriteCommandLCM(0x38,0);
delay_LCM(5);
WriteCommandLCM(0x38,0);
delay_LCM(5);
WriteCommandLCM(0x38,1);//8bit数据传送,2行显示,5*7字型,检测忙信号
WriteCommandLCM(0x08,1); //关闭显示,检测忙信号
WriteCommandLCM(0x01,1); //清屏,检测忙信号
WriteCommandLCM(0x06,1); //显示光标右移设置,检测忙信号
WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
}
/****************显示指定坐标的一个字符子函数*************/
void DisplayOneChar(uchar X,uchar Y,uchar DData)
{
Y&=1;
X&=15;
if(Y)X|=0x40; //若y为1(显示第二行),地址码+0X40
X|=0x80; //指令码为地址码+0X80
WriteCommandLCM(X,0);
WriteDataLCM(DData);
}
/***********显示指定坐标的一串字符子函数***********/
void DisplayListChar(uchar X,uchar Y,uchar code *DData)
{
uchar ListLength=0;
Y&=0x01;
X&=0x0f;
while(X<16)
{
DisplayOneChar(X,Y,DData[ListLength]);
ListLength++;
X++;
}
}
/***********ds18b20延迟子函数(晶振12MHz )*******/
void delay_18B20(unsigned int i)
{
while(i—-);
}
/**********ds18b20初始化函数**********************/
void Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(8); //稍做延时
DQ = 0; //单片机将DQ拉低
delay_18B20(80); //精确延时 大于 480us
DQ = 1; //拉高总线
delay_18B20(14);
x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay_18B20(20);
}
/***********ds18b20读一个字节**************/
unsigned char ReadOneChar(void)
{
uchar i=0;
uchar dat = 0;
for (i=8;i〉0;i——)
{
DQ = 0; // 给脉冲信号
dat〉>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/*************ds18b20写一个字节****************/
void WriteOneChar(uchar dat)
{
unsigned char i=0;
for (i=8; i〉0; i——)
{
DQ = 0;
DQ = dat&0x01;
delay_18B20(5);
DQ = 1;
dat>>=1;
}
}
/**************读取ds18b20当前温度************/
void ReadTemperature(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned char t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
delay_18B20(100); // this message is wery important
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
delay_18B20(100);
a=ReadOneChar(); //读取温度值低位
b=ReadOneChar(); //读取温度值高位
temp1=b<<4;
temp1+=(a&0xf0)>〉4;
temp2=a&0x0f;
temp=((b*256+a)〉>4); //当前采集温度值除16得实际温度值
}
/***************液晶显示子函数1正常显示*****************/
void displayfun1(void)
{
WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
DisplayListChar(0,0,str0);
DisplayListChar(0,1,str1);
DisplayOneChar(3,0,hour/10+0x30); //液晶上显示小时
DisplayOneChar(4,0,hour%10+0x30);
DisplayOneChar(6,0,minite/10+0x30); //液晶上显示分
DisplayOneChar(7,0,minite%10+0x30);
DisplayOneChar(9,0,seconde/10+0x30); //液晶上显示秒
DisplayOneChar(10,0,seconde%10+0x30);
DisplayOneChar(4,1,K/10+0x30); //液晶上显示设定的温度
DisplayOneChar(5,1,K%10+0x30);
DisplayOneChar(11,1,temp1/10+0x30); //液晶上显示测得的温度
DisplayOneChar(12,1,temp1%10+0x30);
DisplayOneChar(14,1,temp2/10+0x30);
if(ON_OFF==0) //若温控标志为0
{
DisplayOneChar(14,0,0x4f); // 液晶上显示不控温的标志
DisplayOneChar(15,0,0x46);
}
else
{
DisplayOneChar(14,0,0x4f); // 液晶上显示控温的标志
DisplayOneChar(15,0,0x4e);
if(outflag==1)
DisplayOneChar(0,0,0x7c);
else
DisplayOneChar(0,0,0xef);
}
}
/************液晶显示子函数2***************/
void displayfun2(void)
{
WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
DisplayListChar(0,0,str0);
DisplayListChar(0,1,str1);
DisplayOneChar(6,0,minite/10+0x30);
DisplayOneChar(7,0,minite%10+0x30);
DisplayOneChar(9,0,seconde/10+0x30);
DisplayOneChar(10,0,seconde%10+0x30);
DisplayOneChar(4,1,K/10+0x30);
DisplayOneChar(5,1,K%10+0x30);
DisplayOneChar(11,1,temp1/10+0x30);
DisplayOneChar(12,1,temp1%10+0x30);
DisplayOneChar(14,1,temp2/10+0x30);
WriteCommandLCM(0x0f,1); //显示屏打开,光标显示,闪烁,检测忙信号
DisplayOneChar(3,0,hour/10+0x30);
DisplayOneChar(4,0,hour%10+0x30);
}
/**************液晶显示子函数3*****************/
void displayfun3(void)
{
WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
DisplayListChar(0,0,str0);
DisplayListChar(0,1,str1);
DisplayOneChar(3,0,hour/10+0x30);
DisplayOneChar(4,0,hour%10+0x30);
DisplayOneChar(9,0,seconde/10+0x30);
DisplayOneChar(10,0,seconde%10+0x30);
DisplayOneChar(4,1,K/10+0x30);
DisplayOneChar(5,1,K%10+0x30);
DisplayOneChar(11,1,temp1/10+0x30);
DisplayOneChar(12,1,temp1%10+0x30);
DisplayOneChar(14,1,temp2/10+0x30);
WriteCommandLCM(0x0f,1); //显示屏打开,光标显示,闪烁,检测忙信号
DisplayOneChar(6,0,minite/10+0x30);
DisplayOneChar(7,0,minite%10+0x30);
}
/**************液晶显示子函数4 *****************/
void displayfun4(void)
{
WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
DisplayListChar(0,0,str0);
DisplayListChar(0,1,str1);
DisplayOneChar(3,0,hour/10+0x30);
DisplayOneChar(4,0,hour%10+0x30);
DisplayOneChar(6,0,minite/10+0x30);
DisplayOneChar(7,0,minite%10+0x30);
DisplayOneChar(9,0,seconde/10+0x30);
DisplayOneChar(10,0,seconde%10+0x30);
DisplayOneChar(11,1,temp1/10+0x30);
DisplayOneChar(12,1,temp1%10+0x30);
DisplayOneChar(14,1,temp2/10+0x30);
WriteCommandLCM(0x0f,1); //显示屏打开,光标显示,闪烁,检测忙信号
DisplayOneChar(4,1,K/10+0x30);
DisplayOneChar(5,1,K%10+0x30);
}
/**************键盘扫描子函数******************/
void keyscan(void)
{
uchar xx; //局部变量
P1=0xff;
if(P1!=0xff)
{
delay_LCM(50);
if(P1!=0xff)
{
xx=P1;
switch(xx) // 根据按键状态,调用不同的子函数
{
case 0xfe:set_adj(); break;
case 0xfd:inc_key(); break;
case 0xfb:dec_key(); break;
case 0xf7:{delay_LCM(150);ON_OFF=!ON_OFF;while(!BLUE_ALARM);} break;
default:break;
}
}
}
}
/**************设定工作模式子函数****************/
void set_adj(void)
{
delay_LCM(100);
set++;
if(set>=4)set=0;
while(!RED_ALARM);
}
/****************按键加法子函数******************/
void inc_key(void)
{
delay_LCM(150);
switch(set)
{
case 0:if(P1==0xf7){delay_LCM(150);ON_OFF=!ON_OFF;} break;
case 1:hour++; if(hour〉=23)hour=23; break;
case 2:minite++; if(minite〉=59)minite=59;break;
case 3:K++;if(K>=99)K=99; break;
default:break;
}
while(!WRITE_ALARM);
}
/****************按键减法子函数*****************/
void dec_key(void)
{
delay_LCM(150);
switch(set)
{
case 0:if(P1==0xf7){delay_LCM(150);ON_OFF=!ON_OFF;} break;
case 1:hour-—; if(hour<=0)hour=0; break;
case 2:minite——;if(minite〈=0)minite=0;break;
case 3:K—-;if(K<=1)K=1; break;
default:break;
}
while(!GREEN_ALARM);
}
/************24C02读写驱动程序**************/
void delay1(uchar x)
{
uint i;
for(i=0;i〈x;i++);
}
void flash()
{ ; ; }
void x24c02_init() //24c02初始化子程序
{
scl=1;
flash();
sda=1;
flash();
}
void start() //启动I2C总线
{
sda=1;
flash();
scl=1;
flash();
展开阅读全文