基于51单片机课程设计报告

单片机课程设计

课    题:基于51单片机的数字温度计设计

专    业:    电气工程及其自动化

班    级:      4

学    号:      12151688

 姓    名:     彭明闯

指导教师:      李敏

设计日期:      2014/6/3

成    绩:

重庆大学城市科技学院电气学院

基于51单片机数字温度计设计报告

一、设计目的作用

本设计是一款简单实用的小型数字温度计,所采用的主要元件有传感器DS18B20,单片机AT89C52,,四位共阴极数码管一个,电容电阻若干。DS18B20支持“一线总线”接口,测量温度范围-55°C~+125°C。在-10~+85°C范围内,精度为±0.5°C。18B20的精度较差,为± 2°C 。现场温度直接以“一线总线”的数字方式传输,大大提高了系统的抗干扰性。适合于恶劣环境的现场温度测量,如:环境控制、设备或过程控制、测温类消费电子产品等。

本次数字温度计的设计共分为五部分,主控制器,LED显示部分,传感器部分,复位部分,按键设置部分,时钟电路。主控制器即单片机部分,用于存储程序和控制电路;LED显示部分是指四位共阴极数码管,用来显示温度;传感器部分,即温度传感器,用来采集温度,进行温度转换;复位部分,即复位电路,按键部分用来设置上下限报警温度。测量的总过程是,传感器采集到外部环境的温度,并进行转换后传到单片机,经过单片机处理判断后将温度传递到数码管显示。

二、设计要求

(1).利用DS18B20传感器实时检测温度并显示。

(2).利用数码管实时显示温度。

(3).当温度超过或者低于设定值时蜂鸣器报警,LED闪烁指示。

(4).能够手动设置上限和下限报警温度。

三、设计的具体实现

1、系统概述

方案一: 由于本设计是测温电路,可以使用热敏电阻之类的器件利用其感温效应,在将随被测温度变化的电压或电流采集过来,进行A/D转换后,就可以用单片机进行数据的处理,在显示电路上,就可以将被测温度显示出来,这种设计需要用到A/D转换电路,感温电路比较麻烦。

方案设计框图如下:

 

   

方案二:考虑到用温度传感器,在单片机电路设计中,大多都是使用传感器,所以这是非常容易想到的,所以可以采用一只温度传感器DS18B20,此传感器,可以很容易直接读取被测温度值,进行转换,就可以满足设计要求。

从以上两种方案,很容易看出,采用方案二,电路比较简单,软件设计也比较简单,故采用了方案二。

2、 单元电路设计与分析

1、硬件设计

按照系统设计功能的要求,确定系统由3个模块组成:主控制器、测温电路和显示电路。

数字温度计总体电路结构框图所示:

 

单片机的选择

单片机AT89S52具有低电压供电和体积小等特点,四个端口只需要两个口就能满足电路系统的设计需要,很适合便携手持式产品的设计使用系统可用二节电池供电。由于器件问题,我们使用了通用的手机5V充电器接口。

复位电路模块

单片机系统的复位电路在这里使用的是上电+按钮的复位电路模式,其中电阻R采用的是10KΩ的阻值,电容采用电容值为10uF的电解电容,电路图如下:

复位电路

温度显示模块

四位共阴极数码管,能够显示小数。列扫描用P2.4~P2.7口来实现,列驱动直接51接单片机驱动。电路图如下:

                                                                                                           

温度传感器模块

DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,与传统的热敏电阻等测温元件相比,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。电路图如下:

                                                                                             按键模块

按键是用来设置报警的上下限温。K1是用 来进入上下限调节模式的,当按一下K1进入上限调节模式,再按一下进入下限调节模式。在正常模式下,按一下K2进入查看上限温度模式,显示1s左右自动退出;按一下K3进入查看下限温度模式,显示1s左右自动退出;按一下K4消除按键音,再按一下启动按键音。在调节上下限温度模式下,K2是实现加1功能, K1是实现减1功能,K3是用来设定上下限温度正负的。

     

2、软件设计

主要包括主程序、读出温度子程序、温度转换命令子程序、计算温度子程序和现实数据刷新子程序等。

主程序  主程序的主要功能是负责温度的实时显示、读出并处理DS18B20的测量温度值。温度测量每1S进行一次。主流程图如下:

读出温度子程序 

读出温度子程序的主要功能是读出RAM中的9字节。在读出时须进行CRC校验,校验有错时不进行温度数据的改写。流程图如下:

温度

温度转换命令子程序  温度转换命令子程序主要是发温度转换开始命令。当采用12位分辨率时,转换时间约为750ms。在本程序设计中,采用1s显示程序延时法等待转换的完成。流程图如下:

显示数据刷新子程序  显示数据刷新子程序主要是对显示缓冲器中的显示数据进行刷新操作,当最高数据显示位为0时,将符号显示位移入下一位。

系统的调试及性能分析:

硬件调试,首先检查电感的焊接是否正确,然后可用万用表测试或通电检测。

软件调试可以先编写显示程序并进行硬件的正确性检验,然后分别进行主程序、读出温度子程序、温度转换命令子程序、计算温度子程序和现实数据刷新子程序等的编程及调试

由于DS18B20与单片机采用串行数据传送,因此,对DS18B20进行读/写编程时必须严格地保证读/写时序;否则将无法读取测量结果。本程序采用单片机汇编或C语言编写用 Keil C51编译器编程调试。

软件调试到能显示温度值,并且在有温度变化时显示温度能改变,就基本完成。

性能测试可用制作的温度计和已有的成品温度计同时进行测量比较。由于DS18B20的精度很高,所以误差指标可以限制在0.5℃以内。另外,-55~+125℃的测温范围使得该温度计完全适合一般的应用场合,其低电压供电特性可做成用电池供电的手持温度计。

                                                   

四、总结

本次的课程设计使我们进一步巩固了书本上的知识,做到了学以致用。这是我们第二次自己动手设计的电路,通过系统仿真软件Proteus和编译软件Keil,使我们进一步了解了单片机的设计制作过程,其中最为困难的是软件部分,即编程部分,我们上网找了好多资料,虽然经过自己的修改,但还是有很多功能不能实现,如温度上下限设置。由于Proteus并不是很熟练,在使用的过程中有很多原件的名称不知道,从而花费了大量的时间在网上查找,今后应该在这方面多多努力。最后一步的焊接硬件也遇到了不少麻烦。总结经验的时候我们得出这样的结论,学习应该学以致用,有目的的去学习,如果学了不用等于没学。其次,要学以致用,理论联系实际,这样才会取得事半功倍的效果。

五、附录

附录一:元件清单

附录二:完整电路原理图

附录三:焊接实物图

附录四:源程序

/********************************************************************

* 程序名;  基于51单片机的温度计

* 功  能: 实时测量温度,超过上下限报警,报警温度可手动调整。K1是用来

* 进入上下限调节模式的,当按一下K1进入上限调节模式,再按一下进入下限

* 调节模式。在正常模式下,按一下K2进入查看上限温度模式,显示1s左右自动

* 退出;按一下K3进入查看下限温度模式,显示1s左右自动退出;按一下K4消除

* 按键音,再按一下启动按键音。在调节上下限温度模式下,K2是实现加1功能,

* K1是实现减1功能,K3是用来设定上下限温度正负的。         

* 编程者: 彭明闯

* 编程时间:2014/05/30                

*********************************************************************/

#include<reg52.h>                            

#include<intrins.h>                            //将intrins.h头文件包含到主程序(调用其中的_nop_()空操作函数延时)

#define uint unsigned int                

#define uchar unsigned char             

uchar max=0x00,min=0x00;              //max是上限报警温度,min是下限报警温度

bit   s=0;                                                                //s是调整上下限温度时温度闪烁的标志位,s=0不显示200ms,s=1显示1s左右

bit   s1=0;                                                              //s1标志位用于上下限查看时的显示

void display1(uint z);                //声明display1()函数(display.h头文件中的函数,ds18b20.h要用应先声明)

#include"ds18b20.h"                           

#include"keyscan.h"                            

#include"display.h"                               

/******************************************************/

/*                                                                   主函数                                                                                      /

/*****************************************************/

void main()

{

        beer=1;                                      //关闭蜂鸣器

        led=1;                                        //关闭LED灯

        timer1_init(0);                    //初始化定时器1(未启动定时器1)

        get_temperature(1);         //首次启动DS18B20获取温度(DS18B20上电后自动将EEPROM中的上下限温度复制到TH和TL寄存器)

        while(1)                                        

        {  

               keyscan();                          

               get_temperature(0);    

               display(temp,temp_d*0.625);

               alarm();                              

        }

}  

/********************************************************************

* 程序名;  DS18B20头文件       

* 编程者:彭明闯

* 编程时间:2014/5/30

* 说  明:用到的全局变量是:无符号字符型变量temp(测得的温度整数部分),temp_d

* (测得的温度小数部分),标志位f(测量温度的标志位‘0’表示“正温度”‘1’表

* 示“负温度”),标志位f_max(上限温度的标志位‘0’表示“正温度”、‘1’表

* 示“负温度”),标志位f_min(下限温度的标志位‘0’表示“正温度”、‘1’表

* 示“负温度”),标志位w(报警标志位‘1’启动报警‘0’关闭报警)。                

*********************************************************************/

#ifndef __ds18b20_h__                          //定义头文件

#define __ds18b20_h__

#define uint unsigned int                      

#define uchar unsigned char                  

sbit    DQ= P2^3;                                    //DS18B20接口

sbit    beer=P1^0;                               //用beer表示P1.0

sbit    led=P1^1;                                              //用led表示P1.1

uchar   temp=0;                            //测量温度的整数部分

uchar   temp_d=0;                 //测量温度的小数部分

bit     f=0;                                                      //测量温度的标志位,0’表示“正温度” ‘1’表示“负温度”)

bit     f_max=0;                                      //上限温度的标志位‘0’表示“正温度” ‘1’表示“负温度”)

bit     f_min=0;                                       //下限温度的标志位‘0’表示“正温度”、‘1’表示“负温度”)

bit     w=0;                                                     //报警标志位‘1’启动报警‘0’关闭报警

/******************************************************/

/*                                                            延时子函数                                                                              /

/*****************************************************/

void ds18b20_delayus(uint t)          //延时几μs

{

   while(t--);

}

void ds18b20_delayms(uint t)          //延时1ms左右

{

       uint i,j;

       for(i=t;i>0;i--)

          for(j=120;j>0;j--);

}

/******************************************************/

/*                                                            DS18B20初始化函数                                                             /

/*****************************************************/

void ds18b20_init()                              

{

       uchar c=0; 

       DQ=1;

       DQ=0;                                                              //控制器向DS18B20发低电平脉冲

       ds18b20_delayus(80);                  //延时15-80μs

       DQ=1;                                                                         //控制器拉高总线,

       while(DQ);                                          //等待DS18B20拉低总线,在60-240μs之间

       ds18b20_delayus(150);                   //延时,等待上拉电阻拉高总线

       DQ=1;                                                                  //拉高数据线,准备数据传输;

}

/******************************************************/

/*                                                            DS18B20字节读函数                                                     /

/*****************************************************/

uchar ds18b20_read()                           

{

       uchar i;

       uchar d=0;

       DQ = 1;                                           //准备读;

       for(i=8;i>0;i--)

       {    

           d >>= 1;                        //低位先发;

              DQ = 0;                                                        

              _nop_();

              _nop_();                     

              DQ = 1;                                    //必须写1,否则读出来的将是不预期的数据;

              if(DQ)                                      //在12us处读取数据;

                     d |= 0x80;

              ds18b20_delayus(10);             

              }

       return d;                                   //返回读取的值

}

/******************************************************/

/*                                                            DS18B20字节写函数                                                   /

/*****************************************************/

void ds18b20_write(uchar d)               

{

     uchar  i;

     for(i=8;i>0;i--)

     {       

                DQ=0;

                DQ=d&0x01;

                ds18b20_delayus(5);

                DQ=1;     

                d >>= 1;        

     }

}

/******************************************************/

/*                                                            获取温度函数                                                                /

/*****************************************************/

 void get_temperature(bit flag)            

{

       uchar a=0,b=0,c=0,d=0;

    uint i;   

       ds18b20_init();                            

       ds18b20_write(0xcc);                     //向DS18B20发跳过读ROM命令

       ds18b20_write(0x44);                     //写启动DS18B20进行温度转换命令,转换结果存入内部RAM

       if(flag==1)

       {                                                                                  //首次启动DS18B20进行温度转换需要500ms,若转换时间不够就出错,读出的是85度的错误值。

         display1(1);                                 //用开机动画耗时

       }

       else

       ds18b20_delayms(1);                     

       ds18b20_init();                          

       ds18b20_write(0xcc);                          

       ds18b20_write(0xbe);                           

       a=ds18b20_read();                                 //读内部RAM (LSB)

       b=ds18b20_read();                                 //读内部RAM (MSB)

       if(flag==1)                                                    //局部位变量f=1时读上下线报警温度

       {

           max=ds18b20_read();                 //读内部RAM (TH)

           min=ds18b20_read();                  //读内部RAM (Tl)

             

       }

       if((max&0x80)==0x80)               //若读取的上限温度的最高位(符号位)为‘1’表明是负温度

       {f_max=1;max=(max-0x80);}       //将上限温度符号标志位置‘1’表示负温度,将上限温度装换成无符号数。

        if((min&0x80)==0x80)                  //若读取的下限温度的最高位(符号位)为‘1’表明是负温度

       {f_min=1;min=(min-0x80);}       //将下限温度符号标志位置‘1’表示负温度,将下限温度装换成无符号数。

            

       i=b;

       i>>=4;

       if (i==0)

              {

        f=0;                                    //i为0,正温度,设立正温度标记

        temp=((a>>4)|(b<<4));           //整数部分

              a=(a&0x0f);

              temp_d=a;                                //小数部分

              }

       else

              {

              f=1;                                      //i为1,负温度,设立负温度标记

              a=~a+1;

              b=~b;

              temp=((a>>4)|(b<<4));                                  //整数部分

              a=(a&0x0f);                             //小数部分

              temp_d=a;

          }

}

/******************************************************/

/*                                                            存储极限温度函数                                                        /

/*****************************************************/

void store_t()

 {

       if(f_max==1)                                  //若上限温度为负,将上限温度转换成有符号数(最高位为1是负,为0是正)

       max=max+0x80;

       if(f_min==1)                                   //若下限温度为负,将上限温度转换成有符号数

       min=min+0x80;

       ds18b20_init();                         

       ds18b20_write(0xcc);                     

       ds18b20_write(0x4e);                     //向DS18B20发写字节至暂存器2和3(TH和TL)命令

       ds18b20_write(max);                    //向暂存器TH(上限温度暂存器)写温度

       ds18b20_write(min);                     //向暂存器TL(下限温度暂存器)写温度

       ds18b20_write(0xff);               //向配置寄存器写命令,进行温度值分辨率设置

       ds18b20_init();                         

       ds18b20_write(0xcc);                     

       ds18b20_write(0x48);                     //向DS18B20发将RAM中2、3字节的内容写入EEPROM

 }                                                                                            //DS18B20上电后会自动将EEPROM中的上下限温度拷贝到TH、TL暂存器

/******************************************************/

/*                                                            温度超限报警函数                                                      /

/*****************************************************/

 void alarm()

 {                                                           //若上限值是正值

         if(f_max==0)

         {

            if(f_min==0)                         //若下限值是正值

               {

                      if(f==0)                           //若测量值是正值

                      {

                             if(temp<=min||temp>=max)

                             {w=1;TR1=1;}         //当测量值小于最小值或大于最大值时报警

                             if((temp<max)&&(temp>min))

                             {w=0;}                            //当测量值大于最小值且小于最大值时不报警

                      }

                      if(f==1){w=1;TR1=1;}   //若测量值是负值时报警

               }

            if(f_min==1)                         //若下限值是负值

               {

                     if(f==0)                           //若测量值是正值

                      {

                             if(temp>=max)//当测量值大于最大值时报警

                             {w=1;TR1=1;}

                             if(temp<max )//当测量值小于最大值时不报警

                             {w=0;}

                      }

                      if(f==1)                           //若测量值是负值

                      {

                             if(temp>=min)//当测量值大于最小值时报警

                             {w=1;TR1=1;}

                             if(temp<min)//当测量值小于最小值时不报警

                             {w=0;}

                      }

               }

         }

         if(f_max==1)                              //若下限值是负值

         {

            if(f_min==1)                         //若下限值是负值

               {

                      if(f==1)                           //若测量值是负值

                      {

                             if((temp<=max)||(temp>=min))

                             {w=1;TR1=1;}         //当测量值小于最大值或大于最小值时报警

                             if((temp<min)&&(temp>max))

                             {w=0;}                            //当测量值小于最小值且大于最大值时不报警

                      }

                      if(f==0){w=1;TR1=1;}   //若测量值是正值时报警

               }

         }  

 }

#endif

/**********************************************************************

* 程序名;   ds18b20keyscan函数

* 功  能:  通过键盘设定设定上下限报警温度

* 编程者:  彭明闯

* 编程时间:2014/5/30  

**********************************************************************/

#ifndef __keyscan_H__                        //定义头文件

#define __keyscan_H__

             

sbit key1=P2^2;                             

sbit key2=P2^1;                                  

sbit key3=P2^0;                                    

sbit key4=P3^3;                                    

uchar i=0;                                               //定义全局变量i用于不同功能模式的选择,‘0’正常模式,‘1’上限调节模式,‘2’下限调节模式

uchar a=0;                                           //定义全局变量a用于不同模式下数码管显示的选择

bit     k4=0;                                           //K4按键双功能选择位,k4=0时K4按键选择消按键音的功能,k4=1时K4按键选择正负温度设定功能

bit   v=0;                                              //K2、K3按键双功能选择位,v=0时选择上下限查看功能,v=1时选择上下限温度加减功能

bit   v1=0;                                            //v1=1时定时1250ms时间到自动关闭报警上下限查看功能

bit   v2=0;                                //消按键音功能调整位,为‘0’时开按键音,为‘1’时关按键音

/******************************************************/

/*                                                                   读键盘延时子函数                                                    /

/*****************************************************/

void keyscan_delay(uint z)                    //延时1ms左右

{

  uint i,j;

  for(i=z;i>0;i--)

       for(j=120;j>0;j--);

}

/******************************************************/

/*                                                                   温度调节函数                                                                 /

/*****************************************************/

int temp_change(int count,bit f)     //上下限温度调整

{

    if(key2==0)                                    //判断K2是否按下

       {                                                     

           if(v2==0)beer=0;                     //v2=0开按键音,否则消按键音

              keyscan_delay(10);                  //延时10ms

              if(key2==0)                              //再次判断K2是否按下(实现按按键时消抖)

              {              

                 beer=1;                               //K2按下关按键音

                 if(f==0)                              //若温度为正

                 { 

                    count++;                       //每按一下K2温度上调1

                    if(a==1){if(count>125) count=125;}//当温度值大于125时不上调

                       if(a==2){if(count>125) count=125;}

                 }

                 if(f!=0)                               //若温度为负

                 {                  

                       count++;                        //每按一下K2温度下调1

                       if(a==1){if(count>55) count=55;}//当温度值小于-55时不再下调

                       if(a==2){if(count>55) count=55;}

                 }

              }

              while(key2==0);                       //K2松开按键时消抖

              keyscan_delay(10);

      

       }

       if(key3==0)

       {

           if(v2==0)beer=0;

              keyscan_delay(10);

              if(key3==0)                           //K3按按键时消抖

              {

                  beer=1;

                 count--;                       //每按一下K3温度为正时下调1,为负时上调1

                     if(a==1){if(count<0) count=0;}//当温度值达到0时不再调

                     if(a==2){if(count<0) count=0;}    

              }

              while(key3==0);

              keyscan_delay(10);                  //K3松开按键时消抖

      

       }

       return count;

}

/******************************************************/

/*                                                                   读键盘函数                                                                  /

/*****************************************************/

void keyscan()

{

        

       if(key1==0)

       {

           if(v2==0)beer=0;

              keyscan_delay(10);

              if(key1==0)                              //K1按按键时消抖

              {

                 beer=1;

                 TR1=1;                            //开定时器1,通过s标志位的变化,实现在上下限温度调整时温度显示时闪烁的功能               

                 k4=1;                                  //在上下温度调节功能模式下选择K4的调整上下限温度正负的功能

                 v=1;                                    //在上下温度调节功能模式下选择K2、K3的温度加减功能

                 i++;                                  //K1按一下i加1,i=‘0’进入正常模式,i=‘1’进入调上限模式,i=‘2’进入调下限模式

                 if(i>2)                                 //K1按下三次后退出调节模式

                 {

                     i=0;                             //进入正常模式

                        TR1=0;                        //关定时器1

                        k4=0;                           //在正常模式下选择K4的消按键音功能

                        v=0;                             //在正常模式下选择K2、K3的查看上下限报警温度功能

                        store_t();               //存储调整后的上下限报警温度

                 }               

                 switch(i)                      //显示选择

                 {

                     case 0:a=0;break; //a=0选择显示测得的温度

                        case 1:a=1;break;    //a=1选择显示上限温度

                        case 2:a=2;break;    //a=2选择显示下限温度

                       

                        default:break;

                 }

                

              }

              while(key1==0);                       //K1松按键时消抖

              keyscan_delay(10);

             

       }

       if(a==1&&v==1)                            //a=1选择显示上限温度且v=1时选择上下限温度加功能

       {led=0;max=temp_change(max,f_max);}//显示上限温度

       else if(a==2&&v==1)                     //a=2选择显示下限温度且v=1时选择上下限温度减功能

       {led=1;min=temp_change(min,f_min);}

       else;

       if(k4==1)                                         //k4=1时K4按键选择正负温度设定功能

       {

              if(key4==0)

              {

                  if(v2==0)beer=0;

                     keyscan_delay(5);

                     if(key4==0)

                     {

                        beer=1;

                        if(a==1)

                        {if(max>55) f_max=0;else f_max=~f_max;}//当温度大于55度时,只能设定为正温度

                        if(a==2)

                        {if(min>55) f_max=0;else f_min=~f_min;}//当温度大于55度时,只能设定为正温度                       

                     }

                     while(key4==0);

                     keyscan_delay(10);

              }

       }

      

       if(v==0)                                    //v=0时选择上下限查看功能

       {

              if(key2==0)

              {

                  if(v2==0)beer=0;

                     keyscan_delay(10);

                     if(key2==0)

                     {

                        beer=1;

                        a=1;                             //选择上限显示

                        TR1=1;                        //开定时器1开始定时一分钟左右

                        s1=1;                        //上限显示不闪烁,显示一分钟左右自动退出

                     }

                     while(key2==0);

                     keyscan_delay(10);

                    

              }

              if(key3==0)

              {

                  if(v2==0)beer=0;

                     keyscan_delay(10);

                     if(key3==0)

                     {

                        beer=1;

                        a=2;                             //选择下限显示

                        TR1=1;                        //开定时器1开始定时1s

                        s1=1;                       //下限显示不闪烁,显示1s自动退出                

                     }

                     while(key3==0);

                     keyscan_delay(10);

                    

              }

              if(v1==1)                              //v1=1时定时1s时间到自动关闭报警上下限查看功能

              {a=0;v1=0;TR1=0;}             //a=0显示实测温度,v1清零,关定时器1

              if(k4==0)                              //k4=0时K4按键选择消按键音的功能

              {                                          

                     if(key4==0)

                     {

                            if(v2==0)beer=0;

                            keyscan_delay(10);

                            if(key4==0)

                            {

                               beer=1;

                               v2=~v2;                //为‘0’时开按键音,为‘1’时关按键音                        

                            }

                            while(key4==0);

                            keyscan_delay(10);

                  }          

              }

       }       

}

#endif

/**********************************************************************

* 程序名;   ds18b20数码管动态显示头文件

* 功  能:  通过定时器0延时是数码管动态显示

* 编程者:  彭明闯

* 编程时间:2014/5/30  

**********************************************************************/

#ifndef __ds18b20_display_H__         

#define __ds18b20_display_H__

#define uint unsigned int                     //变量类型宏定义,用uint表示无符号整形(16位)

#define uchar unsigned char                  //变量类型宏定义,用uchar表示无符号字符型(8位)

sbit wei1=P2^4;                                    //可位寻址变量定义,用wei1表示P2.4口

sbit wei2=P2^5;                                    //用wei2表示P2.5口

sbit wei3=P2^6;                                    //用wei3表示P2.6口

sbit wei4=P2^7;                                     //用wei4表示P2.7口

uchar num=0;                                         //定义num为全局无符号字符型变量,赋初值为‘0’

uchar code temperature1[]={ 0x3f,0x06,0x5b,0x4f,0x66,

                           0x6d,0x7d,0x07,0x7f,0x6f};     //定义显示码表0~9

uchar code temperature2[]={ 0xbf,0x86,0xdb,0xcf,0xe6,

                           0xed,0xfd,0x87,0xff,0xef};      //带小数点的0~9.

uchar code temperature3[]={ 0x00,0x80,0x40,0x76,0x38};    //依次是‘不显示’‘.’‘-’‘H’‘L’

/******************************************************/

/*                                                                   延时子函数                                                                       /

/*****************************************************/

void display_delay(uint t)             //延时1ms左右

{

       uint i,j;

       for(i=t;i>0;i--)

          for(j=120;j>0;j--);

}

/******************************************************/

/*                                                                   定时器1初始化函数                                                       /

/*****************************************************/

void timer1_init(bit t)

{

    TMOD=0x10;                                      

    TH0=0x3c;                                    

    TL0=0xb0;                                    

    EA=1;                                           

    ET1=1;                                          

    TR1=t;                                            // 局部变量t为1启动定时器1,为0关闭定时器1

}

/******************************************************/

/*                                                                   定时器1中断函数                                                           /

/*****************************************************/

void timer1() interrupt 3

{

    TH0=0x3c;                                     //重新赋初值,定时50ms

    TL0=0xb0;

       num++;                                            //每进入一次定时器中断num加1(每50ms加1一次)

    if(num<5)

       {s=1;if(w==1){beer=1;led=1;}else{beer=1;led=1;}}                                                

       else                                            //进入4次中断,定时200ms时若报警标志位w为‘1’则启动报警,不为‘1’不启动

                                                                                    //实现间歇性报警功能

       {s=0;if(w==1){beer=0;led=0;}else{beer=1;led=1;}}

       if(num>20)                                      //进入20次中断,定时1s

    {

          num=0;                                      //num归0,重新定开始定时1s

          s1=0;                                         //定时1s时间到时自动关闭报警上下限显示功能

          v1=1;                                         //定时1s时间到时自动关闭报警上下限查看功能

    }

      

}

/******************************************************/

/*                                                                   调整报警上下限选择函数                                 /

/*****************************************************/

void  selsct_1(uchar f,uchar k)          //消除百位的0显示,及正负温度的显示选择

{

      if(f==0)                                                                  //若为正温度,百位为0则不显示百位,不为0则显示

         {

                if(k/100==0)  P0=temperature3[0];

                else          P0=temperature1[k/100];

         }

         if(f==1)                                                                          //若为负温度,若十位为0,百位不显示,否则百位显示‘-’

         {

             if(k%100/10==0)   P0=temperature3[0];

                else              P0=temperature3[2];

         }

}

void  selsct_2(bit f,uchar k)                 //消除十位的0显示,及正负温度的显示选择

{

      if(f==0)                                                        //若为正温度,百位十位均为0则不显示十位,否则显示十位

         {

                if((k/100==0)&&(k%100/10==0)) 

                    P0=temperature3[0];

                else          P0=temperature1[k%100/10];

         }

         if(f==1)                                                                          //若为负温度,若十位为0,十位不显示,否则十位显示‘-’

         {

             if(k%100/10==0)   P0=temperature3[2];

                else               P0=temperature1[k%100/10];

         }       

}

/******************************************************/

/*                                                                   主函数显示                                                                       /

/*****************************************************/

void display(uchar t,uchar t_d)          //用于实测温度、上限温度的显示

{

   uchar i;

   for(i=0;i<4;i++)                  //依次从左至右选通数码管显示,实现动态显示

   {              

       switch(i)

          {

             case 0:                             //选通第一个数码管

                wei2=1;                            //关第二个数码管

                wei3=1;                            //关第三个数码管

                wei4=1;                          //关第四个数码管

             wei1=0;                           //开第一个数码管              

                if(a==0){selsct_1(f,t);} //若a=0则在第一个数码管上显示测量温度的百位或‘-’

                if(a==1)

                {                 

                    P0=temperature3[3];  //若a=1则在第一个数码管上显示‘H’            

                }

                if(a==2)

                {                  

                    P0=temperature3[4];  //若a=2则在第一个数码管上显示‘L’

                }                              

                break;

             case 1:                                            //选通第二个数码管

                wei1=1;            

                wei3=1;

                wei4=1;            

             wei2=0;           

                if(a==0){selsct_2(f,t);} //若a=0则在第二个数码管上显示测量温度的十位或‘-’

                if(a==1)                                           //若a=1则在第二个数码管上显示上限报警温度的百位或‘-’

                { 

                   if(s==0) selsct_1(f_max,max);//若s=0则显示第二个数码管,否则不显示

                   else P0=temperature3[0];               //通过s标志位的变化实现调节上下限报警温度时数码管的闪烁

                   if(s1==1) selsct_1(f_max,max);//若s1=1则显示第二个数码管(s1标志位用于上下限查看时的显示)

                }

                if(a==2)                                                         //若a=2则在第二个数码管上显示下限报警温度的百位或‘-’

                { 

                   if(s==0) selsct_1(f_min,min);

                   else P0=temperature3[0];

                   if(s1==1) selsct_1(f_min,min);

                }                                                       

                break;

             case 2:                                                          //选通第三个数码管

                wei1=1;

                wei2=1;            

                wei4=1;            

             wei3=0;           

                if(a==0){P0=temperature2[t%10];}//若a=0则在第三个数码管上显示测量温度的个位

                if(a==1)                                                                       //若a=1则在第三个数码管上显示上限报警温度的十位或‘-’

                {

                    if(s==0) selsct_2(f_max,max);//若s=0则显示第三个数码管,否则不显示

                       else P0=temperature3[0];

                       if(s1==1) selsct_2(f_max,max);//若s1=1则显示第三个数码管

                }

                if(a==2)                                                                       //若a=2则在第三个数码管上显示下限报警温度的十位或‘-’

                {

                    if(s==0) selsct_2(f_min,min);

                       else P0=temperature3[0];

                       if(s1==1) selsct_2(f_min,min);

                }                                                               

                break;

             case 3:                            //选通第四个数码管

                wei1=1;          

                wei2=1;            

                wei3=1;

                wei4=0;            

                if(a==0){P0=temperature1[t_d];}//若a=0则在第四个数码管上显示测量温度的小数位

                if(a==1)                                                                        //若a=1则在第四个数码管上显示上限报警温度的个位

                {

                   if(s==0) P0=temperature1[max%10];//若s=0则显示第四个数码管,否则不显示

                      else P0=temperature3[0];

                      if(s1==1) P0=temperature1[max%10];//若s1=1则显示第四个数码管

                }

                if(a==2)                                                                               //若a=2则在第四个数码管上显示下限报警温度的个位

                {

                   if(s==0) P0=temperature1[min%10];

                      else P0=temperature3[0];

                      if(s1==1) P0=temperature1[min%10];

                }                                                                                       

                break;        

          }

        display_delay(10);                   //每个数码管显示3ms左右

       }

      

}

/******************************************************/

/*                                                                   开机显示函数                                                                   /

/*****************************************************/

void display1(uint z)                  //用于开机动画的显示

{

   uchar i,j;

   bit f=0;

   for(i=0;i<z;i++)                           //‘z’是显示遍数的设定

   {        

          for(j=0;j<4;j++)            //依次从左至右显示‘-’

          {

              switch(j)

                 {

                        case 0:

                               wei2=1;

                               wei3=1;

                               wei4=1;          

                            wei1=0;  break;

                                     P0=temperature3[2];//第一个数码管显示

                        case 1:

                               wei1=1;          

                               wei3=1;

                               wei4=1;          

                            wei2=0;break;

                                     P0=temperature3[2];//第二个数码管显示

                        case 2:

                               wei1=1;

                               wei2=1;          

                               wei4=1;          

                            wei3=0;break;

                                     P0=temperature3[2];//第三个数码管显示

                        case 3:

                               wei1=1;        

                               wei2=1;          

                               wei3=1;

                               wei4=0;break;

                                     P0=temperature3[2];//第四个数码管显示

                 }

                display_delay(400);         //每个数码管显示200ms左右

          }

            

       }

}

#endif

六、参考文献

(1).郭天祥.51单片机c语言教程.电子工业出版社.2009.12

(2).李群芳.单片微型计算机与接口技术.电子工业出版社.2012.12

相关推荐