找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10808|回复: 6
打印 上一主题 下一主题
收起左侧

基于AT89C51单片机温度报警系统设计与制作

[复制链接]
跳转到指定楼层
楼主
ID:331034 发表于 2018-5-16 09:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、摘要
我们介绍的是一种基于单片机控制的数字温度报警,本温度系统具有多功能性,即可以当数字温度计使用,显示当前环境温度,又可以作为报警器使用,设置报警温度,当温度不在设置范围内时,可以报警,并采取措施使温度下降。
该温度报警系统控制器使用单片机AT89C51,测温传感器使DS18B20,用2位共阳极LED数码管,实现温度显示,能准确达到以上要求。
二、设计方案
1、方案一
由于本设计是测温电路,可以使用热敏电阻之类的器件利用其感温效应,在将随被测温度变化的电压或电流采集过来,进行A/D转换后,就可以用单片机进行数据的处理,在显示电路上,就可以将被测温度显示出来,这种设计需要用到A/D转换电路,感温电路比较麻烦。
2、 方案二
进而考虑到用温度传感器,在单片机电路设计中,大多都是使用传感器,所以这是非常容易想到的,所以可以采用一只温度传感器DS18B20,此传感器,可以很容易直接读取被测温度值,进行转换,就可以满足设计要求。
从以上两种方案,很容易看出,采用方案二,电路比较简单,软件设计也比较简单,故采用了方案二。
温度报警系统电路设计总体设计方框图如图1所示
  


三、模块功能分析
1、单片机主板电路
单片机AT89C51具有低电压供电和体积小等特点,该模块包括中央处理CPU -AT89C51、时钟电路及复位电路;2、DS18B20温度传感器与单片机的接口电路
DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。
DS18B20是采用电源供电方式,此时DS18B20的1脚接地,2脚作为信号线,3脚接电源。
该电路完成了信号的采集、转换和传输。
图4
3、上下限报警调整电路
   分别调整温度的上下限报警设置,有“+“、”“-”、“确定”等键
图5上下限报警调整电路

4、温度显示电路
显示当前测得的温度,数码管采用74LS247驱动
5、报警电路
当环境温度超过设定温度时,蜂鸣器鸣叫,红灯点亮,发生报警;当人员发现警报时,可按图8中的按钮,暂时中断蜂鸣器的鸣叫。6、控制电路
  该电路的作用是:当测量温度超过设定温度时,小风扇以下转动,加快仪器散热,使温度保持在设定温度以下。
图9控制电路
四、整体构造及功能
整体电路图如下:
实现的总体功能:
l 实现对环境温度的测量和显示
l 能通过按键设置报警温度
l 温度超过设置值时,产生光声报警
l 报警同时系统自带小风扇转动以降低温度
主程序
主程序的主要功能是负责温度的实时显示、读出并处理DS18B20的测量的当前温度值,温度测量每1s进行一次。这样可以在一秒之内测量一次被测温度,其程序流程见下图所示

附录:
源程序
/*******************************************************************/
/*温度报警器*/
/*******************************************************************/
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define Tube P0                       //数码管端口
#define Key P1                        //键盘端口
sbit DQ = P1^4;                       //温度传感器DS18B20数据传输端
sbit BUZZER = P1^5;                       //蜂鸣器端口
sbit RUN = P1^6;                          //运行指示灯端口
sbit SET = P1^7;                          //设置指示灯端口
sbit Feng = P3^3;                         //风扇端口
bit Status;                           //设置状态标志位
bit Warning;                              //警报标志位
bit Int;                                  //外部中断标志位
uchar OP1L;                           //原P1端低4位状态
uchar NP1L;                           //现P1端低4位状态
uchar FinT;                           //最终测得温度
uchar LimT;                           //警报温度下限
uchar Count;                              //定时器计数
/*******************************************************************/
#include"Delay.h"
#include"Display.h"
#include"Initialize.h"
#include"Error.h"
#include"KeyScan.h"
#include"Measure.h"
#include"Interrupt.h"
/*******************************************************************/
/*主程序*/
/*******************************************************************/
void main()
{
    Initialize();                         //初始化
    do{                                   //开机自检,跳过默认初始的85℃
        Measure();
    }while( FinT == 0X55);
    while(1){
        KeyScan();                        //键盘扫描
        Measure();                        //获取测量温度
        Display();                        //显示
    }
}
/*******************************************************************/
/*初始化*/
/*******************************************************************/
void Initialize()
{
    Status = 0;                       //初始化设置状态标志位
    Warning = 0;                          //初始化警报标志位
    BUZZER = 1;                       //初始化蜂鸣器状态
    RUN = 0;                              //初始化运行指示灯
    SET = 1;                              //初始化设置指示灯
Feng = 1;                             //初始化风扇端口

    OP1L = 0X00;                          //初始化原P1低4位
    NP1L = 0X00;                          //初始化新P1低4位
    LimT = 0X1B;                          //初始化警报温度下限为27℃
Count = 0X00;                         //初始化定时器计数单元
EA = 1;                           //开总中断
    EX0 = 1;                              //开外部中断0中断允许
    IT0 = 1;                              //设置外部中断0为边沿触发方式
}
/*******************************************************************/
/*温度测量*/
/*******************************************************************/
void InitDS18B20();                       //初始化DS18B20
void WriteDS18B20( uchar ch );        //写DS18B20数据
uchar ReadDS18B20();                      //读DS18B20数据
void Measure()
{  
    uchar TemH;                       //保存传感器发送数据高8位
    uchar TemL;                       //保存传感器发送数据低8位      
    InitDS18B20();
    WriteDS18B20( 0XCC );             //跳过ROM
    _nop_();                          
    InitDS18B20();         
    WriteDS18B20( 0XCC );             //跳过ROM
    _nop_();              
    WriteDS18B20( 0X44 );             //发送温度转换指令
    Delay1ms( 25 );
    Delay1ms( 25 );
    Delay1ms(25 );
    Delay1ms( 25 );                   //等待1s转换
    InitDS18B20();
    WriteDS18B20( 0XCC );             //跳过ROM
    WriteDS18B20( 0XBE );             //发送温度转换指令
    TemL = ReadDS18B20();                 //读低位温度值
    TemH = ReadDS18B20();                 //读高位温度值                                                         
    Delay1ms( 2 );
   
    TemH = ( TemH<<4 )|( TemL>>4 );       //保留温度值整数部分
   
    FinT = TemH;
    if( FinT > LimT ){                //判断是否警报
        Warning = 1;
    }
    else{
        Warning = 0;
    }   
}
uchar ReadDS18B20()                       //读DS18B20数据
{
    uchar ch;
    uchar q ;
    for( q=0; q<8; q++ ){
        ch = ch >> 1;
        DQ = 0;
        _nop_();
        DQ = 1;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        if( DQ == 1 ){
           ch = ch | 0X80;
        }
        else{
           ch = ch &0X7f;
        }
        Delay15us( 3 );
        DQ = 1;
    }  
    return( ch );
}
void WriteDS18B20( uchar ch )         //写DS18B20数据
{
    uchar i;
    for( i=0; i<8; i++ )
    {
        DQ=0;
        Delay15us( 1 );
        DQ = ch & 0X01;
        Delay15us( 3 );
        DQ = 1;
        ch = ch >> 1;
        _nop_();
    }
}
void InitDS18B20()                    //初始化DS18B20
{
    DQ = 0;
    Delay15us( 33 );                      //至少延时480us
    DQ = 1;
    Delay15us( 10 );                      //至少延时100us
}
/*******************************************************************/
/*显示*/
/*******************************************************************/
void  Display()
{  
    uchar T;
        
    if( Status == 1 ){                //判断状态
        T = LimT;
    }
    else{
        T = FinT;
    }
           
    T = T % 10 + T / 10 *16;         //将2进制码转化为BCD码         
    Tube = T;                             //数码管显示
    RUN = Warning;                    //运行指示灯显示
    BUZZER = !Warning ||Int;         //蜂鸣器
Feng = !Warning;                      //风扇
    SET = !Status;                    //设置指示灯显示
    Delay1ms( 20 );
}
/*******************************************************************/
/*键盘扫描*/
/*******************************************************************/
void KeyScan()
{
    NP1L = Key;                       //读取按键状态         
    NP1L = NP1L &0X0F;
    NP1L = NP1L ^ 0X0F;
        
    if( NP1L != OP1L ){   
        switch(NP1L){                     //判断按键
           case 0X01:                     //按键为“设置”
               Status = 1;            //进入设置状态
               break;
           case 0X02:                     //按键为“+1”
               if( Status== 1){          //判断是否为设置状态
                   LimT++;            //警报温度下限+1
                   LimT =LimT % 100; //超过99清零
                   Delay1ms(255);
               }
               else{
                   Error();
               }
               break;
           case 0X04:                     //按键为“-1”
               if( Status== 1){          //判断是否为设置状态
                   LimT--;            //警报温度下限-1
                   if(LimT < 0 ){        
                       LimT = 0X63;       //低于0变为99
                   }
                   Delay1ms(255);
               }
               else{
                   Error();
               }
               break;
           case 0X08:                     //按键为“确认”
               Status = 0;            //返回测温状态
               break;
           default:                       //多键按下
               Error();                   //出错复位
               break;
        }
        NP1L = 0X00;                      //重新初始化
    }
}
/*******************************************************************/
/*中断服务*/
/*******************************************************************/
void Int0( void ) interrupt 0
{
    Int = 1;                              //外部中断标志位置1
    EX0 = 0;                              //关外部中断0中断允许
    TMOD = 0X01;                          //设置定时器0工作在模式1
    TH0 = 0X3C;                       
    TL0 = 0XB0;                       //为T0赋初值,令其定时50ms
    Count = 0X3C;                         //设置计数次数  
    ET0 = 1;                              //开T0中断允许
    TR0 = 1;                              //开T0中断
}
/*******************************************************************/
void Timer0( void )    interrupt1
{
    if( Count == 0 ){                     //判断定时计数是否结束
        ET0 = 0;                          //关T0中断允许
        TR0 = 0;                          //关T0中断
        Int = 0;                          //外部中断标志位置0
        EX0 = 1;                          //开外部中断0中断允许
    }
    else{
        TL0 = 0XB0;                    //重新赋T0初值
        TH0 = 0X3C;
        Count --;                         //定时计数减1
    }
}
/*******************************************************************/
/*延迟函数*/
/*******************************************************************/
void Delay15us( uchar n )             //延迟n*15us
{  
    do{
        _nop_(); _nop_();_nop_();
        _nop_(); _nop_();_nop_();
        _nop_(); _nop_();_nop_();
        _nop_(); _nop_();_nop_();
        _nop_();
        n--;
    }while( n );      
}
void Delay1ms( uchar delay )          //延迟delay*1ms
{
    uchar i;
    while( delay-- )
    {
        for( i=0; i<124; i++);
    }
}
/*******************************************************************/
/*报错复位*/
/*******************************************************************/
void Error()
{
    Tube = 0XAA;                          //出错显示
    BUZZER = 0;                       //鸣蜂鸣器
    RUN = 1;                              //LED警报
    Delay1ms( 255 );                      //延迟
    Delay1ms( 255 );
    Delay1ms( 255 );
    Delay1ms( 255 );
    Delay1ms( 255 );
    ( *(void(*)())0 )();                  //软复位
}
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:421519 发表于 2018-11-6 09:35 | 只看该作者
为什么初始化 Initialize和测量程序编译错
回复

使用道具 举报

板凳
ID:401656 发表于 2018-12-1 21:16 | 只看该作者
#include"Delay.h"
#include"Display.h"
#include"Initialize.h"
#include"Error.h"
#include"KeyScan.h"
#include"Measure.h"
#include"Interrupt.h"

这个不能打开呀,,是换成void函数吗?
回复

使用道具 举报

地板
ID:401656 发表于 2018-12-18 20:48 | 只看该作者
_nop_();   这个是什么啊
回复

使用道具 举报

5#
ID:401656 发表于 2018-12-24 16:02 | 只看该作者
没有仿真吗??急求仿真啊
回复

使用道具 举报

6#
ID:853241 发表于 2020-12-2 17:42 | 只看该作者
祁醉醉 发表于 2018-12-18 20:48
_nop_();   这个是什么啊

空操作,空占机器周期
回复

使用道具 举报

7#
ID:991726 发表于 2021-12-15 22:18 | 只看该作者
有原理图吗  protues那种
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表