找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于STC89C51的温度报警器实现

[复制链接]
跳转到指定楼层
楼主
ID:271749 发表于 2018-1-5 03:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 zhouyuan12 于 2018-1-5 05:32 编辑

#include <reg52.h>

#include "eepom52.h"

#define uchar unsigned char

#define uint  unsigned int


//数码管段选定义      0    1    2    3   4    5 6      7     8     9      

uchar codesmg_du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,

                              0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};     //断码

//数码管位选定义

uchar code smg_we[]={0xef,0xdf,0xbf,0x7f};

uchar dis_smg[8] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};   

uchar smg_i = 3;    //显示数码管的个位数

sbit dq   = P2^4;     //18b20 IO口的定义

sbit beep = P2^5;   //蜂鸣器IO口定义

uchar a_a;


uint temperature ;  //

bit flag_300ms ;

uchar key_can;          //按键值的变量

uchar menu_1;        //菜单设计的变量

uint t_high = 300,t_low = 100;

bit flag_lj_en;           //按键连加使能

bit flag_lj_3_en;        //按键连3次连加后使能加的数就越大了

uchar key_time,flag_value;     //用做连加的中间变量

bit key_500ms  ;

uchar flag_clock;

uchar zd_break_en,zd_break_value;  //自动退出设置界面





/***********************1ms延时函数*****************************/

void delay_1ms(uint q)

{

   uint i,j;

   for(i=0;i<q;i++)

          for(j=0;j<120;j++);

}


/***********************小延时函数*****************************/

void delay_uint(uint q)

{

   while(q--);

}



/***********************数码显示函数*****************************/

void display()

{

   uchar i;

   for(i=0;i<smg_i;i++)

   {                                          

          P3 = smg_we;                  //位选

          P1 = dis_smg;            //段选        

          delay_1ms(1);                     

          P3 = 0xff;                    //位选

          P1 = 0xff;                    //消隐

         

   }     

}


/******************把数据保存到单片机内部eepom******************/

void write_eepom()

{

   SectorErase(0x2000);

   byte_write(0x2000, t_high %256);

   byte_write(0x2001, t_high /256);

   byte_write(0x2002, t_low %256);

   byte_write(0x2003, t_low /256);

   byte_write(0x2055, a_a);     

}


/******************把数据从单片机内部eepom中读出来*****************/

void read_eepom()

{

   t_high  = byte_read(0x2001);

   t_high <<= 8;

   t_high  |= byte_read(0x2000);

   t_low   =byte_read(0x2003);

   t_low <<= 8;

   t_low   |= byte_read(0x2002);

   a_a      = byte_read(0x2055);

}


/***********************18b20初始化函数*****************************/

void init_18b20()

{

   bit q;

   dq = 1;                         //把总线拿高

   delay_uint(1);          //15us

   dq = 0;                         //给复位脉冲

   delay_uint(80);            //750us

   dq = 1;                         //把总线拿高 等待

   delay_uint(10);            //110us

   q = dq;                         //读取18b20初始化信号

   delay_uint(20);            //200us

   dq = 1;                         //把总线拿高 释放总线

}


/*************18b20内的数据***************/

void write_18b20(uchar dat)

{

   uchar i;

   for(i=0;i<8;i++)

   {                                  //写数据是低位开始

          dq = 0;                  //把总线拿低写时间隙开始

          dq = dat & 0x01; //18b20总线写数据了

          delay_uint(5);        //60us

          dq = 1;                  //释放总线

          dat >>= 1;

   }     

}


/*************读取18b20内的数据***************/

uchar read_18b20()

{

   uchar i,value;

   for(i=0;i<8;i++)

   {

          dq = 0;                  //把总线拿低读时间隙开始

          value >>= 1;   //读数据是低位开始

          dq = 1;                  //释放总线

          if(dq == 1)             //开始读写数据

                 value |= 0x80;

          delay_uint(5);       //60us   读一个时间隙最少要保持60us的时间

   }

   return value;         //返回数据

}


/*************读取温度的值 读出来的是小数***************/

uint read_temp()

{

   uint value;

   uchar low;                     //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序

   init_18b20();            //初始化18b20

   write_18b20(0xcc);        //跳过64ROM

   write_18b20(0x44);        //启动一次温度转换命令

   delay_uint(50);               //500us


   init_18b20();            //初始化18b20

   

   write_18b20(0xcc);         //跳过64ROM

   write_18b20(0xbe);        //发出读取暂存器命令

   

   EA = 0;

   low = read_18b20();        //读温度低字节

   value = read_18b20();  //读温度高字节

   EA = 1;

   value <<= 8;            //把温度的高位左移8

   value |= low;            //把读出的温度低位放到value的低八位中

   value *= 0.625;           //转换到温度值 小数

   return value;            //返回读出的温度带小数

}


/*************定时器0初始化程序***************/

void time_init()   

{

   EA   = 1;            //开总中断

   TMOD = 0X01;      //定时器0、定时器1工作方式1

   ET0  = 1;             //开定时器0中断

   TR0  = 1;             //允许定时器0定时

}


/****************独立按键处理函数************************/

void key()

{

   static uchar key_new =0,key_old = 0,key_value = 0;

   if(key_new == 0)               

   {                                           //按键松开的时候做松手检测

          if((P2 & 0x0f) == 0x0f)

                 key_value ++;

          else

                 key_value = 0;

          if(key_value >= 10)

          {

                 write_eepom();

                 key_value = 0;

                 key_new = 1;

                 flag_lj_en = 0;             //关闭连加使能

                 flag_lj_3_en = 0;   //关闭3秒后使能

                 flag_value = 0;             //清零

          }

   }

   else

   {

          if((P2 & 0x0f) != 0x0f)

                 key_value ++;  //按键按下的时候

          else

                 key_value = 0;

          if(key_value >= 7)

          {

                 key_value = 0;

                 key_new = 0;

                 flag_lj_en = 1;       //连加使能

                 zd_break_en = 1;//自动退出设置界使能

                 zd_break_value =0; //自动退出设置界变量清零

          }

   }

   key_can = 20;

   if(key_500ms == 1)

   {

          key_500ms = 0;

          zd_break_en = 1; //自动退出设置界使能

          zd_break_value = 0; //自动退出设置界变量清零

          key_new = 0;

          key_old = 1;

   }

   if((key_new == 0) &&(key_old == 1))

   {

          switch(P2 & 0x0f)

          {

                 case 0x0e: key_can= 4; break;       //得到k1键值

                 case 0x0d: key_can= 3; break;       //得到k2键值

                 case 0x0b: key_can= 2; break;       //得到k3键值

                 case 0x07: key_can= 1; break;       //得到k4键值

          }

   }                  

   key_old = key_new;     

}


/****************按键处理数码管显示函数***************/

void key_with()

{

   if(key_can == 4)

   {

          menu_1 ++;

          if(menu_1 >= 3)

          {

                 menu_1 = 0;

          }

          if(menu_1 == 0)

          {

                 dis_smg[0] =smg_du[temperature % 10];  //取温度的小数显示

                 dis_smg[1] =smg_du[temperature / 10 % 10] & 0x7f; //取温度的个位显示

                 dis_smg[2] =smg_du[temperature / 100 % 10] ;        //取温度的十位显示

                 smg_i = 3;

          }

          if(menu_1 == 1)

          {

                 dis_smg[0] =smg_du[t_high % 10];             //取小数显示

                 dis_smg[1] =smg_du[t_high / 10 % 10] & 0x7f;  //取个位显示

                 dis_smg[2] =smg_du[t_high / 100 % 10] ;          //low十位显示

                 dis_smg[3] = 0x89;      

                 smg_i = 4;

          }

          if(menu_1 == 2)

          {

                 dis_smg[0] =smg_du[t_low % 10];              //low小数显示

                 dis_smg[1] =smg_du[t_low / 10 % 10] & 0x7f;  //取个位显示

                 dis_smg[2] =smg_du[t_low / 100 % 10] ;    //取十位显示

                 dis_smg[3] = 0xc7;      

                 smg_i = 4;

          }

   }

   if(menu_1 == 1)                 //设置高温报警

   {

          if(key_can == 3)

          {

                 if(flag_lj_3_en ==0)

                        t_high ++ ;           //按键按下未松开自动加三次   

                 else

                        t_high += 10; //按键按下未松开自动加三次之后每次自动加10

                 if(t_high >990)

                        t_high = 990;

                 dis_smg[0] =smg_du[t_high % 10];             //取小数显示

                 dis_smg[1] =smg_du[t_high / 10 % 10] & 0x7f;  //取个位显示

                 dis_smg[2] =smg_du[t_high / 100 % 10] ;          //取十位显示

                 dis_smg[3] = 0x89;       //H

          }

          if(key_can == 1)

          {

                 if(flag_lj_3_en ==0)

                        t_high -- ;             //按键按下未松开自动加三次   

                 else

                        t_high -= 10; //按键按下未松开自动减三次之后每次自动减10

                 if(t_high <=t_low)

                        t_high = t_low + 1;

                 dis_smg[0] =smg_du[t_high % 10];             //取小数显示

                 dis_smg[1] =smg_du[t_high / 10 % 10] & 0x7f;  //取个位显示

                 dis_smg[2] =smg_du[t_high / 100 % 10] ;          //取十位显示

                 dis_smg[3] = 0x89;       //H

          }

//        write_eepom();

   }     

   if(menu_1 == 2)                 //设置低温报警

   {

          if(key_can == 3)

          {

                 if(flag_lj_3_en ==0)

                        t_low ++ ;                    

                 else

                        t_low += 10;

                 if(t_low >=t_high)

                        t_low = t_high - 1;

                 dis_smg[0] =smg_du[t_low % 10];              //取小数显示

                 dis_smg[1] =smg_du[t_low / 10 % 10] & 0x7f;  //取个位显示

                 dis_smg[2] =smg_du[t_low / 100 % 10] ;    //取十位显示

                 dis_smg[3] = 0xc7;        //L

          }

          if(key_can == 1)

          {

                 if(flag_lj_3_en ==0)

                        t_low -- ;               

                 else

                        t_low -= 10;

                 if(t_low <= 10)

                        t_low = 10;

                 dis_smg[0] =smg_du[t_low % 10];              //取小数显示

                 dis_smg[1] =smg_du[t_low / 10 % 10] & 0x7f;  //取个位显示

                 dis_smg[2] =smg_du[t_low / 100 % 10] ;    //取十位显示

                 dis_smg[3] = 0xc7;        //L

          }

//        write_eepom();

   }     

}  


/****************报警函数***************/

void clock_h_l()

{

   if((temperature <= t_low)|| (temperature >= t_high))

   {

          flag_clock = 1;      

   }

   else

   {

          flag_clock = 0;      

          beep = 1;

   }                  

}


void main()

{

   temperature = read_temp();        //先读出温度的值

   time_init();                    //初始化定时器

   read_eepom();      

   if(a_a == 0xff)                                  //新的单片机初始单片机内问EEPOM

   {

          t_high = 300;

          t_low  = 100;

          a_a = 1;

          write_eepom();     

   }            

   delay_1ms(650);                        

   temperature = read_temp();                 //先读出温度的值

   dis_smg[0] =smg_du[temperature % 10];  //取温度的小数显示

   dis_smg[1] =smg_du[temperature / 10 % 10] & 0x7f; //取温度的个位显示

   dis_smg[2] =smg_du[temperature / 100 % 10] ;        //取温度的十位显示

   while(1)

   {

          display();                      //显示函数

          key();                                 //按键程序

          if(key_can < 10)

          {

                 key_with();                  //设置报警温度   

          }

          temperature = read_temp(); //先读出温度的值

          if(flag_300ms == 1)             //300ms 处理一次温度程序

          {        

                 clock_h_l();            //报警函数

                 if(flag_clock ==1)

                        beep = ~beep;

                 flag_300ms = 0;   

                 if(menu_1 == 0)

                 {     

                        smg_i = 3;

                        dis_smg[0] = smg_du[temperature % 10];  //取温度的小数显示

                        dis_smg[1] = smg_du[temperature / 10 %10] & 0x7f; //取温度的个位显示

                        dis_smg[2] = smg_du[temperature / 100 %10] ;        //取温度的十位显示

                 }

                 if(zd_break_en ==1)    //自动退出设置界面程序

                 {

                        zd_break_value ++;  //300ms加一次

                        if(zd_break_value > 50)   //15秒后自动退出设置界面

                        {

                               menu_1= 0;

                               zd_break_en= 0;

                               zd_break_value= 0;

                        }           

                 }

          }

   }

}


/*************定时器0中断服务程序***************/

void time0_int() interrupt 1

{

   static uchar value;

   TH0 = 0x3c;

   TL0 = 0xb0;     // 50ms

   value ++;      

   if(value % 6 == 0)

   {

          flag_300ms = 1;       //300ms

          value = 0;

   }

   if(flag_lj_en == 1)    //按下按键使能

   {

          key_time ++;

          if(key_time >= 10) //500ms

          {

                 key_time = 0;

                 key_500ms = 1; //500ms

                 flag_value ++;

                 if(flag_value >3)

                 {

                        flag_value = 10;

                        flag_lj_3_en = 1; //3次后1.5秒连加大些

                 }

                                      

          }

   }

}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:276340 发表于 2018-1-15 19:46 | 只看该作者
点赞!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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