1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 基于51单片机的温度监测控制系统仿真程序原理图设计

基于51单片机的温度监测控制系统仿真程序原理图设计

时间:2021-11-08 10:54:12

相关推荐

基于51单片机的温度监测控制系统仿真程序原理图设计

整体方案设计

3.1.1 系统概述

整个系统以STC89C52单片机为核心器件,配合电阻电容晶振等器件,构成单片机的最小系统。其它个模块围绕着单片机最小系统展开。其中包括,传感器采用DS18B20,负责采集温度数据后发给单片机。显示设备采用4位共阴数码管,显示检测到的温度值。按键模块,主要是进行报警值的设置。报警模块采用蜂鸣器+LED的模式,超出报警范围则进行声光报警,同时还有升温和降温装置工作,使得温度恒定在一个范围之内。

原理图:

仿真图:

最小系统模块

3.2.1 STC89C52简介

(1)概述

STC89C52是一个低电压,高性能CMOS 8位单片机,片内含8k bytes的可反复擦写的Flash只读程序存储器和256 bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器和Flash存储单元,功能强大的STC89C52单片机可为您提供许多较复杂系统控制应用场合。

STC89C52有40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中断口,3个16位可编程定时计数器,2个全双工串行通信口,2个读写口线。STC89C52有PDIP、PQFP/TQFP及PLCC等三种封装形式,以适应不同产品的需求。

(2)主要功能特性

 ◆兼容MCS51指令系统;

 ◆8k可反复擦写(>1000次)Flash ROM;

 ◆32个双向I/O口;

◆256x8bit内部RAM ;

 ◆3个16位可编程定时/计数器中断;

◆时钟频率0-24MHz;

 ◆2个串行中断;

 ◆可编程UART串行通道;

 ◆2个外部中断源;

 ◆共8个中断源;

 ◆2个读写中断口线;

 ◆3级加密位;

 ◆低功耗空闲和掉电模式;

◆软件设置睡眠和唤醒功能;

DS18B20传感器电路

3.3.1 DS18B20简介

(1)概述

DS18B20(图3-4)是美国DALLAS半导体公司推出的第一片支持“一线总线”接口的温度传感器,它具有微型化,低功耗,高性能,抗干扰能力强,易配微处理器等优点,可直接将温度转化成数字信号处理器处理。测量的温度范围是-55125℃,测温误差0.5℃。可编程分辨率912位,对应的可分辨温度分别为0.5℃,0.25℃,0.125℃和0.0625℃。相较热电偶传感器而言可实现高精度测温。

(2)特性

独特的1-Wire总线接口仅需要一个管脚来通信;

每个设备的内部ROM上都烧写了一个独一无二的64位序列号;

多路采集能力使得分布式温度采集应用更加简单;

无需外围元件;

供电范围为3.0V至5.5V;

温度可测量范围为:-55℃至+125℃(-67℉至+257℉);

温度范围超过-10℃至85℃之外时具有±0.5℃的精度;

内部温度采集精度可以由用户自定义为9-Bits至12-Bits;

温度转换时间在转换精度为12-Bits时达到最大值750ms;

用户自定义非易失性的的温度报警设置;

定义了温度报警搜索命令和当温度超过用户自定义的设定值时;

与DS1822程序兼容。

(3)管脚定义

Pin1:(VDD),可选的电源引脚;

Pin2:(DQ),单线运用的数据输入/输出引脚;

Pin3:(VDD),接地端,电源负极;

(4)应用领域

该产品适用于冷冻库,粮仓,储罐,电讯机房,电力机房,电缆线槽等。

轴瓦,缸体,纺机,空调,等狭小空间工业设备测温和控制。

汽车空调、冰箱、冷柜、以及中低温干燥箱等。

供热/制冷管道热量计量,中央空调分户热能计量和工业领域测温和控制。

数码管显示模块

3.4.1 数码管简介

数码管是一类价格便宜 使用简单,通过对其不同的管脚输入相对的电流,使其发亮,从而显示出数字能够显示 时间、日期、温度等所有可用数字表示的参数的器件。在电器特别是家电领域应用极为广泛,如显示屏、空调、热水器、冰箱等等。LED数码管(LED Segment Displays)由多个发光二极管封装在一起组成“8”字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极。数码管实际上是由七个发光管组成8字形构成的,加上小数点就是8个。这些段分别由字母a,b,c,d,e,f,g,dp来表示。当数码管特定的段加上电压后,这些特定的段就会发亮,以形成我们眼睛看到的字样了。如:显示一个“2”字,那么应当是a亮b亮g亮e亮d亮f不亮c不亮dp不亮。数码管的外形如图3-8所示。

LED数码管有一般亮和超亮等不同之分,也有0.5寸、1寸等不同的尺寸。小尺寸数码管的显示笔画常用一个发光二极管组成,而大尺寸的数码管由二个或多个发光二极管组成,一般情况下,单个发光二极管的管压降为1.8V左右,电流不超过30mA。发光二极管的阳极连接到一起连接到电源正极的称为共阳数码管(图3-9),发光二极管的阴极连接到一起连接到电源负极的称为共阴数码管(图3-10)。常用LED数码管显示的数字和字符是0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F。

3.4.2 数码管驱动方式的分类

LED数码管要正常显示,就要用驱动电路来驱动数码管的各个段码,从而显示出我们要的数字,因此根据LED数码管的驱动方式的不同,可以分为静态式和动态式两类。

静态驱动也称直流驱动。静态驱动是指每个数码管的每一个段码都由一个单片机的I/O端口进行驱动,或者使用如BCD码二-十进制译码器译码进行驱动。静态驱动的优点是编程简单,显示亮度高,缺点是占用I/O端口多,如驱动5个数码管静态显示则需要5×8=40根I/O端口来驱动,要知道一个89S51单片机可用的I/O端口才32个,实际应用时必须增加译码驱动器进行驱动,增加了硬件电路的复杂性。

动态显示,LED数码管动态显示接口是单片机中应用最为广泛的一种显示方式之一,动态驱动是将所有数码管的8个显示笔划"a,b,c,d,e,f,g,dp"的同名端连在一起,另外为每个数码管的公共极COM增加位选通控制电路,位选通由各自独立的I/O线控制,当单片机输出字形码时,单片机对位选通COM端电路的控制,所以我们只要将需要显示的数码管的选通控制打开,该位就显示出字形,没有选通的数码管就不会亮。通过分时轮流控制各个数码管的的COM端,就使各个数码管轮流受控显示,这就是动态驱动。在轮流显示过程中,每位数码管的点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但只要扫描的速度足够快,给人的印象就是一组稳定的显示数据,不会有闪烁感,动态显示的效果和静态显示是一样的,能够节省大量的I/O端口,而且功耗更低。

3.4.3 数码管驱动电路

本设计由于采用了4位数码管,如果采用静态驱动的话,将会占用单片机32个IO口,导致单片机IO口不够用,因此采用数码管的动态驱动方式,电路如下图(图3-11)所示,把数码管的数据口接到单片机的PO口上,位选端则由单片机的P27、P26、P25、P24进行控制。只需12个IO口,就可以控制4位数码管的显示。在程序中需要轮流点亮每位数码管,并且保持一定的点亮时间

蜂鸣器模块

蜂鸣器是一种一体化结构的电子讯响器,采用直流电压供电,广泛应用于计算机、打印机、复印机、报警器、电子玩具、汽车电子设备、电话机、定时器等电子产品中作发声器件。

蜂鸣器主要分为压电式蜂鸣器和电磁式蜂鸣器两种类型。压电式蜂鸣器主要由多谐振荡器、压电蜂鸣片、阻抗匹配器及共鸣箱、外壳等组成。当接通电源后多谐振荡器起振,输出1.5~2.5kHZ的音频信号,阻抗匹配器推动压电蜂鸣片发声。电磁式蜂鸣器由振荡器、电磁线圈、磁铁、振动膜片及外壳等组成。接通电源后,振荡器产生的音频信号电流通过电磁线圈,使电磁线圈产生磁场。振动膜片在电磁线圈和磁铁的相互作用下,周期性地振动发声。本设计使用的是电磁式蜂鸣器。

此外,蜂鸣器还有有源蜂鸣器与无源蜂鸣器的区别。注意这里的“源”不是指电源,而是指震荡源。也就是说,有源蜂鸣器内部带震荡源,所以只要一通电就会叫;而无源内部不带震荡源,所以如果用直流信号无法令其鸣叫,必须用2K-5K的方波去驱动它。本设计使用的是有源蜂鸣器。

由于蜂鸣器工作时,需要的电流比较大,单片机的IO口输出的电流又比较小,所以这里利用三极管的开关管功能来控制蜂鸣器发音,本设计选用的三极管型号是PNP三极管S8550,而且本设计选用的蜂鸣器属于有源蜂鸣器,即在蜂鸣器内部已经内置了震荡电路,单片机无需连续发出高低电平来驱动它,而只要输出高(或低)电平即可,这大大简化了单片机程序的设计。由于选用的是PNP型而单片机上电IO口默认是高电平的,所以上电时蜂鸣器是不会发出鸣叫的。

继电器电路

继电器是一种电控制器件,是当输入量(激励量)的变化达到规定要求时,在电气输出电路中使被控量发生预定的阶跃变化的一种电器。它具有控制系统(又称输入回路)和被控制系统(又称输出回路)之间的互动关系。通常应用于自动化的控制电路中,它实际上是用小电流去控制大电流运作的一种“自动开关”。故在电路中起着自动调节、安全保护、转换电路等作用。

按继电器的工作原理或结构特征分类的不同,大致可将继电器分为电磁继电器、固体继电器、温度继电器、舌簧继电器、时间继电器、高频继电器、极化继电器、光继电器、声继电器、热继电器、仪表式继电器、霍尔效应继电器、差动继电器等。

本设计中采用的继电器属于电磁式继电器。电磁继电器一般由铁芯、线圈、衔铁、触点簧片等组成的。只要在线圈两端加上一定的电压,线圈中就会流过一定的电流,从而产生电磁效应,衔铁就会在电磁力吸引的作用下克服返回弹簧的拉力吸向铁芯,从而带动衔铁的动触点与静触点(常开触点)吸合。当线圈断电后,电磁的吸力也随之消失,衔铁就会在弹簧的反作用力返回原来的位置,使动触点与原来的静触点(常闭触点)释放。这样吸合、释放,从而达到了在电路中的导通、切断的目的。对于继电器的“常开、常闭”触点,可以这样来区分:继电器线圈未通电时处于断开状态的静触点,称为“常开触点”;处于接通状态的静触点称为“常闭触点”。继电器一般有两股电路,为低压控制电路和高压工作电路。

继电器模块的电路如下图(图3-15)所示。继电器使用的是5V电压触发的。由于继电器由导通到关断瞬间,由于工作线圈有电感的性质,所以会在继电器的线圈的低电压端产生一个瞬间电压尖峰,通常能高达数十倍的线圈额定工作电压。所以这里接入一个二极管在继电器两端,因为二极管的负端通常接到VCC,因此电压尖峰将被抑制。保护了板上的电子元件。当单片机的IO口给PNP三极管一个低电平后后,三极管导通,继电器供电,因此继电器从断开变为闭合,最终将小风扇或加热膜接入5V电压,这样就实现了单片机控制加温或降温的效果。

程序设计

#include <reg52.h>// 包含头文件#include <intrins.h>#define uchar unsigned char// 以后unsigned char就可以用uchar代替#define uint unsigned int// 以后unsigned int 就可以用uint 代替sbit DQ = P1^1;// DS18B20传感器的引脚定义sbit w1 = P2^4; // 数码管第1位的控制引脚sbit w2 = P2^5;// 数码管第2位的控制引脚sbit w3 = P2^6;// 数码管第3位的控制引脚sbit w4 = P2^7; // 数码管第4位的控制引脚sbit Buzzer = P1^0;// 蜂鸣器引脚sbit JdqLow = P2^0;// 温度过低继电器控制(加热)sbit JdqHig = P2^1;// 温度过高继电器控制(降温)sbit LedLow = P2^2;// 温度低指示灯sbit LedHig = P2^3;// 温度高指示灯sbit KeySet = P3^2;// 设置按键sbit KeyDown = P3^3;// 减按键sbit KeyUp = P3^4;// 加按键/* 数码管的显示值: 0 1 2 3 4 56 7 8 9 - */uchar code Array1[]={ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40 };/* 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. */uchar code Array2[]={ 0xBf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef };uchar Buff[4];// 显示缓冲区uchar ShowID=1;// 当前显示的是哪一个数码管int AlarmLow=150;// 默认报警的温度下限值是15度int AlarmHig=300;// 默认报警的温度上限值是30度/*********************************************************/// 毫秒级的延时函数,time是要延时的毫秒数/*********************************************************/void DelayMs(uint time){uint i,j;for(i=0;i<time;i++)for(j=0;j<112;j++);}/*********************************************************/// 延时15微秒/*********************************************************/void Delay15us(void){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}/*********************************************************/// 复位DS18B20(初始化)/*********************************************************/void DS18B20_ReSet(void){uchar i;DQ=0;i=240;while(--i);DQ=1;i=30;while(--i);while(~DQ);i=4;while(--i);}/*********************************************************/// 向DS18B20写入一个字节/*********************************************************/void DS18B20_WriteByte(uchar dat){uchar j;uchar btmp;for(j=0;j<8;j++){btmp=0x01;btmp=btmp<<j;btmp=btmp&dat;if(btmp>0)// 写1{DQ=0;Delay15us();DQ=1;Delay15us();Delay15us();Delay15us();Delay15us();}else// 写0{DQ=0;Delay15us();Delay15us();Delay15us();Delay15us();DQ=1;Delay15us();}}}/*********************************************************/// 读取温度值/*********************************************************/int DS18B20_ReadTemp(void){uchar j;int b,temp=0;DS18B20_ReSet();// 产生复位脉DS18B20_WriteByte(0xcc);// 忽略ROM指令DS18B20_WriteByte(0x44);// 启动温度转换指令DS18B20_ReSet();// 产生复位脉DS18B20_WriteByte(0xcc);// 忽略ROM指令DS18B20_WriteByte(0xbe);// 读取温度指令for(j=0;j<16;j++)// 读取温度数量{DQ=0;_nop_();_nop_();DQ=1;Delay15us();b=DQ;Delay15us();Delay15us();Delay15us();b=b<<j;temp=temp|b;}temp=temp*0.0625*10;// 合成温度值并放大10倍return (temp);// 返回检测到的温度值}/*********************************************************/// 定时器初始化/*********************************************************/void TimerInit(){TMOD = 0x01;// 使用定时器0,工作方式1 TH0 = 248;// 给定时器0的TH0装初值TL0 = 48;// 给定时器0的TL0装初值ET0 = 1;// 定时器0中断使能EA = 1;// 打开总中断TR0 = 1;// 启动定时器0}/*********************************************************/// 显示温度值/*********************************************************/void ShowTemp(int dat){if(dat<0)// 负号{Buff[0]=Array1[10];dat=0-dat;}else// 百位{Buff[0]=Array1[dat/1000];}Buff[1]=Array1[dat%1000/100];// 十位Buff[2]=Array2[dat%100/10];// 个位Buff[3]=Array1[dat%10];// 小数后一位}/*********************************************************/// 报警判断/*********************************************************/void AlarmJudge(int dat){if(dat<AlarmLow)// 判断温度是否过低{LedLow=0;// 温度低指示灯亮LedHig=1;// 温度高指示灯灭JdqLow=0;// 温度过低的继电器闭合(开始加热)JdqHig=1;// 温度过高的继电器断开(停止降温)Buzzer=0;// 蜂鸣器报警}else if(dat>AlarmHig)// 判断温度是否过高{LedLow=1;// 温度低指示灯灭LedHig=0;// 温度高指示灯亮JdqLow=1;// 温度过低的继电器断开(停止加热)JdqHig=0;// 温度过高的继电器闭合(开始降温)Buzzer=0;// 蜂鸣器报警}else// 温度正常{LedLow=1;// 温度低指示灯灭LedHig=1;// 温度高指示灯灭JdqLow=1;// 温度过低的继电器断开(停止加热)JdqHig=1;// 温度过高的继电器断开(停止降温)Buzzer=1;// 蜂鸣器停止报警}}/*********************************************************/// 按键扫描/*********************************************************/void KeyScanf(){if(KeySet==0)// 如果设置按键被按下{/* 设置温度下限 */LedLow=0;// 点亮绿色灯(代表当前正在设置温度下限)LedHig=1;// 熄灭红色灯Buzzer=1;// 关闭蜂鸣器ShowTemp(AlarmLow);// 显示温度下限值DelayMs(10);// 延时去抖while(!KeySet);// 等待按键释放DelayMs(10);// 延时去抖while(1){if(KeyDown==0)// 如果“减”按键被按下{if(AlarmLow>-550)// 判断当前温度下限是否大于-55度{AlarmLow--;// 温度下限值减去0.1度ShowTemp(AlarmLow);// 刷新显示改变后的温度下限值DelayMs(200);// 延时}}if(KeyUp==0)// 如果“加”按键被按下{if(AlarmLow<1250)// 判断当前温度下限是否小于125度{AlarmLow++;// 温度下限值加上0.1度ShowTemp(AlarmLow);// 刷新显示改变后的温度下限值DelayMs(200);// 延时}}if(KeySet==0)// 如果“设置”按键被按下{break;// 退出温度下限值的设置,准备进入上限值的设置}}/* 设置温度上限 */LedLow=1;// 熄灭绿色灯LedHig=0;// 点亮红色灯(代表当前正在设置温度上限)ShowTemp(AlarmHig);// 显示温度上限值DelayMs(10);// 延时去抖while(!KeySet);// 等待按键释放DelayMs(10);// 延时去抖while(1){if(KeyDown==0)// 如果“减”按键被按下{if(AlarmHig>-550)// 判断当前温度上限是否大于-55度{AlarmHig--;// 温度上限值减去0.1度ShowTemp(AlarmHig);// 刷新显示改变后的温度上限值DelayMs(200);// 延时}}if(KeyUp==0)// 如果“加”按键被按下{if(AlarmHig<1250)// 判断当前温度上限是否小于125度{AlarmHig++;// 温度上限值加上0.1度ShowTemp(AlarmHig);// 刷新显示改变后的温度上限值DelayMs(200);}}if(KeySet==0)// 如果“设置”按键被按下{break;// 准备退出设置模式}}/* 退出设置模式 */LedLow=1;// 熄灭绿灯LedHig=1;// 熄灭红灯DelayMs(10);// 延时去抖while(!KeySet);// 等待按键释放DelayMs(10);// 延时去抖}}/*********************************************************/// 主函数/*********************************************************/void main(){int temp;uchar i;TimerInit();// 定时器0的初始化(数码管的动态扫描)Buff[0]=Array1[0];// 刚上电显示4个0Buff[1]=Array1[0];Buff[2]=Array1[0];Buff[3]=Array1[0];for(i=0;i<8;i++)// 由于传感器刚上电读出的温度不稳定,因此先进行几次温度的读取并丢弃{DS18B20_ReadTemp();DelayMs(120);}while(1){EA=0;// 屏蔽中断temp=DS18B20_ReadTemp();// 读取温度值EA=1;// 恢复中断ShowTemp(temp);// 显示温度值AlarmJudge(temp);// 判断是否需要报警for(i=0;i<100;i++)// 延时并进行按键扫描{KeyScanf();DelayMs(10);}}}/*********************************************************/// 定时器0服务程序/*********************************************************/void Timer0(void) interrupt 1{TH0 = 248;// 给定时器0的TH0装初值TL0 = 48;// 给定时器0的TL0装初值P0=0x00;// 先关闭所有显示w1=1;w2=1;w3=1;w4=1;if(ShowID==1) // 判断是否显示第1位数码管{w1=0; // 打开第1位数码管的控制开关P0=Buff[0]; // 第1位数码管显示内容}if(ShowID==2) // 判断是否显示第2位数码管{w2=0; // 打开第2位数码管的控制开关P0=Buff[1]; // 第2位数码管显示内容}if(ShowID==3) // 判断是否显示第3位数码管{w3=0; // 打开第3位数码管的控制开关P0=Buff[2]; // 第3位数码管显示内容}if(ShowID==4) // 判断是否显示第4位数码管{w4=0; // 打开第4位数码管的控制开关P0=Buff[3]; // 第4位数码管显示内容}ShowID++; // 切换到下一个数码管的显示if(ShowID==5)ShowID=1;}

附: http://www.jh-/archives/7212

.

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。