小型温度测控系统-单片机爱好者-搜狐博客

来源:百度文库 编辑:神马文学网 时间:2024/04/28 15:36:59

小型温度测控系统

前言

此小型测控系统的主要功能是对外环境温度的实时测量,并按照预先设定好的温度,对外环境温度进行调节,使其保持在预先设定的温度。制作过程中,主要是实现单片机模块和显示模块的功能。通过该系统的制作,使制作者具备电路简单设计与制作,程序编写与调试,系统调试与完善等系统开发的基本技能和知识。同时培养制作者的团队合作精神。

   本次培训的任务:              

1.    设计一款温度测量和控制的小系统,测量范围为:-5~45℃

2.    要求显示部分可以显示一位小数及负号。

3.    片选地址更改。

目录

摘要………………………………………………………………………4

课题背景…………………………………………………………………4

系统整体框架……………………………………………………………4

电路及元件选择…………………………………………………………5

系统主要模块的具体实现………………………………………………6

系统模块的调试程序 …………………………………………………12

心得与体会 ……………………………………………………………19

 

 

 

 

 

 

 

 

 

 

摘要:   本系统主要由LM35温度传感器、AT89S52单片机、变送器、AD转换、

DA转换、稳压电源、键盘输入及数码管显示模块组成。

温度传感器的作用是采集温度,并进行判断和显示。由于此次设计所使

用的是温度传感器为LM35,其检测到的信号是模拟电压信号,需要进行 A/D转换变成二进制数字信号,以便单片机处理。

单片机主要是读取温度传感器的温度检测的电压值,并把该信号转化成

温度值用数码管显示出来。由于AT89系列单片机与MCS一51系列单片机兼容,所以,本系统中的单片机选用AT89S52。

变送器、D/A转换和A/D转换模块对信号进行转换;键盘输入模块辅助

参数的设定,数码管显示模块同步显示系统的状态,共同完成系统的人机交互。

关键字:单片机  电压信号  温度传感器  数码管显示  键盘输入

课题背景

在人类的生活环境中,温度扮演着极其重要的角色。无论你生活在哪里,从事什么工作,无时无刻不在与温度打着交道。今天,我们的生活环境和工作环境有越来越多称之为单片机的小电脑在为我们服务。单片机在工业控制、尖端武器、通信设备、信息处理、家用电器等各测控领域的应用中独占鳌头。时下,家用电器和办公设备的智能化、遥控化模糊控制化已成为世界潮流,而这些高性能无一不是靠单片机来实现的。采用单片机来对温度进行测量和控制,不仅具有控制方便、组态简单和灵活性大等优点,而且可以大幅度提高被控温度的技术指标,从而能够大大提高产品的质量和数量。单片机以其功能强、体积小、可靠性高、造价低和开发周期短等优点,成为自动化和各个测控领域中必不可少且广泛应用的器件,尤其在日常生活中也发挥越来越大的作用。因此,单片机对温度的测控问题是一个工农业生产中经常会遇到的问题。


电路及元件选择

1.电源电路

   • 集成线性稳压电路

     纹波、噪声小、效率低、实现电路相对简单、成本低

• 集成开关稳压电路

     纹波、噪声大、效率高、实现电路相对复杂,成本较高

交流供电电压低,输出功率较小。从实现电路简单,低成本的角度考虑应选择集成线性稳压电路的实现方案。

2.温度传感器

• 热电偶灵敏度低,温度与输出为非线性关系,信号调理电路复杂,适合宽温范围测温。

• 铂电阻温度与输出非理想线性关系,需作电抗到电压的转换,电路复杂,适合宽温范围测温。

• DS1820 采用一线串行数字控制,操作过程复杂,初学者不易掌握。

• LM35具有很高的工作精度和较宽的线性工作范围,该器件输出电压与摄氏温度线性成比例。无需外部校准或微调,可以提供±1/4℃的常用的室温精度。为首选测温传感器。

综上,选择LM35。

    3.单片机

MCS-51系列单片机有众多性能优异的兼容产品、成熟的开发环境、世界上最大的单片机客户群、高性价比、畅通的供货渠道,是初学者的首选机型。

          8031是MCS-51系列单片机早期产品之一,其最小系统需要在外部扩展程序存储器,成本高、性能差,现已退出市场。

          8051也是MCS-51系列单片机早期产品之一,内建一次性可编程只读存储器 ( PROM ) ,只需要很少的外围元件即可组成最小系统。现已有内建 Flash存储器的兼容产品,8051已经被使用上更为方便的AT89C51 AT89S52等单片机产品所代替。

           综上,选择AT89S52。

     4.地址译码电路

·全地址译码

全部地址参与译码,产生的控制信号对应唯一地址。

        ·部分地址译码

部分地址参与译码,产生的控制信号对应某一地址区域,而不是唯一地址。

·直接选择

直接使用地址线作为读/写访问控制信号线。该方案的片选信号与地址之间不是线性关系,使用该方案需要熟练掌握片选信号与地址之间的关系计算。

        综合分析,选择部分地址译码、带有总线驱动电路。

     5.D/A、A/D转换

          DAC0832是8 位乘算型电流输出的典型产品,具有MCU兼容接口,使用方便,价格低,能满足设计要求。

           ADC0804是8 位逐次比较(逐次逼近)型典型产品,具有MCU 兼容接口,使用方便;分辩率和转换速度都能够满足设计要求,且价格低廉。

     6.显示控制电路

           动态显示电路方案:电路简单,成本低,控制程序复杂,适用于显示位数较多的场合。

静态显示电路方案:使用的元件多,成本相对较高。每位独立控制,程序设计比较简单,适用于显示位数较少的场合。采用此方案。

7.键盘电路

           直读键盘电路方案:按键较多时,成本高,控制程序较简单,适用于按键较少的场合。

矩阵键盘电路方案:按键较多时,成本低,控制程序较直读电路复杂,适用于显示位数较多的场合。采用此方案。

系统主要模块的具体实现

一、电源模块

      

        首先,用一个变压器将220V的交流电变成9V和14V的交流电。然后使其通过整流桥将交流电变成直流电。再经过LM7805、LM7812、LM7912这三个芯片使其最终变成+5V、+12V和-12V的直流电。

      注意:连接完毕后,打开调试台电源远离电源板1-2分钟,观察电路板有无异味或异常响动,如果一切正常可以开始进一步的测试;如果整流桥短路就会烧掉保险丝。电路连接不正常可能会引起电容爆裂等现象。这次培训就有一位同学的电容爆裂,有多位同学的保险丝烧掉。应特别小心!

二、单片机模块

     AT89S52器件图

 

 

 

    AT89S52管脚说明

VCC:供电电压。
    GND:接地。
    P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P1口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
    P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为第八位地址接收。
    P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
    P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(TLL)这是由于上拉的缘故。

      P3的特有复用功能

 

引脚

复用功能

P3.0

RXD(串行口输入)

P3.1

TXD(串行口输出)

P3.2

(外部中断0)

P3.3

(外部中断1)

P3.4

T0(定时器0外部输入)

P3.5

T1(定时器1外部输出)

P3.6

(外部数据储存器写信号)

P3.7

(外部数据储存器读信号)

表2-9

RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。/PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的 信号将不出现。 /VPP:当 保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时, 将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。XTAL2:来自反向振荡器的输出。

     原理图

 

单片机电路的组成

1.单片机最小系统

单片机最小系统由一个STC89C51系列单片机,一个晶振和若干电容组成。(如右图)

2.数据/地址分离电路设计

由于本系统采用的是数据地址总线共线,所以使用了一个74LS373锁存器来实现数据和地址的分离,单片机通过ALE口产生的时序脉冲信号来控制74LS373锁存器的使能端LE口,从而将地址信号在一段时间内分离出来。本电路中低四位即能决定地址。其电路如下(图中P0口为数据地址总线):

 

3.地址译码电路设计

一次译码采用138译码器,通过控制A B C输入可得到C口上的片选信号。(图示如下)

4.驱动电路

单片机所接负载超出其负载能力时需要设计总线驱动电路,本系统采用在数据总线上接一块74LS245来实现电流的放大。(电路图如下)

 

三、显示模块

 

1.数码管显示电路

本系统采用的是共阴数码管,阳极接到一块74LS273锁存器上,并与地址总线相连。四块锁存器的使能端CLK与二次译码电路相连,实现不同蕊片的选通。

2.二次译码电路

本系统仍然采用138译码器,输入信号为一次译码产生的各地址信号。实现对不同数码管的选通。

系统模块的调试程序

  C

#include

#include

#define    C1      XBYTE[0x1000]

#define    C2      XBYTE[0x3000]

#define    C3      XBYTE[0x5000]

#define    C4      XBYTE[0x7000]

void main(void)

{    while(1) 

        {C1=0;C2=0;C3=0;C4=0;}

}。

  A口:

    #include

#include

void main(void)

{    while(1) 

            { 

              XBYTE[0x1055]=0; 

              XBYTE[0x10aa]=0;

              }

}。

显示电路模块:

#include

#include

#define    DP1      XBYTE[0x1000]

#define    DP2      XBYTE[0x1001]

#define    DP3      XBYTE[0x1002]

#define    DP4      XBYTE[0x1003]

#define    TIMER    0xff00

unsigned char table[]= {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};

void delay(void);

//void display(unsigned char x,y);

void main(void)

      {  unsigned  char i=0,num=0;

          DP1=DP2=DP3=DP4=!i;

          while(1)

          {     for(num=0;num<10;++num)          //  一

            {  DP1=DP2=DP3=DP4=table[num];    //  同

              delay( );}                          //

         }                                   //   显

        }                                          // 示

      /*     {  for(num=0;num<10;++num)       //逐个显示

                { i++;

                   if(i<=4)     display(i,num);

                   else   { i=1; display(i,num);}

                   delay( );

                }    

            }

     }

void display(unsigned char x,y)

      {   if (x==1) 

            {  DP1=table[y]; }

         else if(x==2)

            {DP2=table[y];}

         else if(x==3)

             {DP3=table[y];}

         else  

             {DP4=table[y];}

      } */                                  //逐个显示    

void delay(void)

      {  unsigned int i;

         for(i=0;i

      }。

D/A转换:

#include

#include

#include

#define ADC XBYTE[0x3000]

#define DP1 XBYTE[0x1001]

#define DP2 XBYTE[0x1002]

#define DP0 XBYTE[0x1000]

#define DP3 XBYTE[0x1003]

#define TIMER 0xffff

unsigned char table[]= {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};

void delay(void);                      //延时函数

void display(unsigned char x,y);       //?

void main(void)

     { unsigned char x=0,y=0,z=0,num=0;

       DP1=DP2=!x;

      DP0=DP3=0;

       while(1)

         {

          ADC=x;                              

          delay( );                          //延时函数

              x=ADC;y=x%10;  num=1;  display(num,y);

          z=x/10;  num=2;  display(num,z);

         }

      }

void display(unsigned char x,y)                      {

      if (x==1) DP1=table[y];

      else       DP2=table[y];

      }

void delay(void)                            //延时函数

     { unsigned int i;

       for(i=0;i

     }

A/D转换:

#include

#include

#include

#define    ADC      XBYTE[0x2000]

//#define    DP1      XBYTE[0x0000]

//#define    DP2      XBYTE[0x0001]

//#define    DP3      XBYTE[0x0002]

//#define    DP4      XBYTE[0x0003]

#define    DP1      XBYTE[0x1003]

#define    DP2      XBYTE[0x1002]

#define    DP3      XBYTE[0x1001]

#define    DP4      XBYTE[0x1000]

#define    TIMER    0x8000

unsigned char table[  ]={0x3F,0x06,0x5B,0x4F,0x66,

                 0x6D,0x7D,0x07,0x7F,0x6F};

void delay(void);

void display(unsigned char x,y);

void main(void)

     { unsigned char x=0,y=0,z=0,w=0,num=0;

        DP1=0x40;

      //   delay( );

       while(1)

         {

          ADC=x;

          delay( );

          x=ADC;

          w=x/100;

          DP2=table[w];

         // delay( );

          y=x/10-w*10;

          DP3=table[y];

         // delay( );

          z=x%10;

          DP4=table[z];

         // delay( );

         }

      }

/*void display(unsigned char x,y)

     {

      if (x=1) DP1=table[y];

      else       DP2=table[y];

      }    

 */

void delay(void)

     {

     unsigned int i;

     for(i=0;i

     }

测温总程序

/*********************************header files********************************/

#include

#include

#include

/*********************************macroinstruction********************************/

#define    ADC      XBYTE[0x2000]

#define    DAC      XBYTE[0x3000]

#define    DP1      XBYTE[0x1000]

#define    DP2      XBYTE[0x1001]

#define    DP3      XBYTE[0x1002]

#define    DP4      XBYTE[0x1003]

#define    KEY_line1     XBYTE[0x1004]

#define    KEY_line2     XBYTE[0x1005]

#define    KEY_line3     XBYTE[0x1006]

#define    KEY_line4     XBYTE[0x1007]

#define    TIMER    0x8000

#define    TIMER1   0x0050

/**************************Digitron TABLE***********************/

Unsigned char table1[ ]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,

0x87,0xFF,0xEF};   //OPTO

unsigned char table[  ]={0x3F,0x06,0x5B,0x4F,0x66, 0x6D,

0x7D,0x07,0x7F,0x6F};

unsigned char option=0;

void display_AND_option(unsigned char x,y);

void keybord(void);

void delay(void);

void key_delay(void);

void ADC_Module(void);

void main(void)

{

DP1=DP4=0x00;

      while(1)

        {

           option=0;

           keybord();

           if(option==1)

           ADC_Module();

        }

}

void delay(void)

{

    unsigned int i;

    for(i=0;i

}

void key_delay(void)

{

      unsigned int i;

    for(i=0;i

}

void keybord(void)

{  

   unsigned char  l_val,t=0;

   while(1){

       t=0;  

       l_val=KEY_line1;

         key_delay();

         if(l_val!=0x00){

             key_delay();

           if(l_val!=0x00)

             switch(l_val){

                case 0xf7:display_AND_option(1,1); break;

                case 0xfb:display_AND_option(1,2);break; 

            case 0xfd:display_AND_option(1,3); break;

                case 0xfe:display_AND_option(1,4);}

             key_delay();

            }

        l_val=KEY_line2;

         key_delay();

         if(l_val!=0x00){

             key_delay();

           if(l_val!=0x00)

             switch(l_val){

                case 0xf7:display_AND_option(2,1); break;

                case 0xfb:display_AND_option(2,2);break; 

            case 0xfd:display_AND_option(2,3); break;

                case 0xfe:display_AND_option(2,4);}

             key_delay();

            }       

        l_val=KEY_line3;

         key_delay();

         if(l_val!=0x00){

             key_delay();

           if(l_val!=0x00)

             switch(l_val){

                case 0xf7:display_AND_option(3,1); break;

                case 0xfb:display_AND_option(3,2);break; 

            case 0xfd:display_AND_option(3,3); break;

                case 0xfe:display_AND_option(3,4);}

             key_delay();

            }

         l_val=KEY_line4;

         key_delay();

         if(l_val!=0x00){

             key_delay();

           if(l_val!=0x00)

             switch(l_val){

                case 0xf7:display_AND_option(4,1); break;

                case 0xfb:display_AND_option(4,2);break; 

            case 0xfd:display_AND_option(4,3); break;

                case 0xfe:display_AND_option(4,4);}

             key_delay();

            }

        if(option!=t)

           break;

//      else

          

        }

}

void ADC_Module(void)

{

        unsigned char x=0,y=0,z=0,w=0,m=0,num=0,n=0;

        unsigned int i,j;

        DP1=DP2=DP3=DP4=0x76;

        delay( );

        delay( );

        for(i=0;i

           {

                for(j=0;j

               {

                 ADC=x;

                  delay( );

                  x=ADC;

                 m=x*3.9;

                 if(m<0){

                 DP1=0x40;

                 }

                 else DP1=0x00;

                  y=m/100;

                 DP2=table[y];

                  z=m/10-y*10;

                 DP3=table1[z];

                 n=m%10;

                 DP4=table[n];

                 delay( );

               }

           if(i==(TIMER-1))DP1=DP2=DP3=DP4=0x00;

           }

}

void display_AND_option(unsigned char x,y)

     unsigned char t1=0,t2=0;

     option=4*(x-1)+y;

     t1=option%10;DP3=table[t1];

     t2=option/10;DP2=table[t2];

}

心得与体会

    很早就听说我们协会今年寒假要搞培训,由于去年我没能参加寒假培训我很后悔,所以我今年就一直等着培训的消息。培训的通知刚出来我就报了名,同时还介绍了班上的同学参加。我要好好把握这次机会,提高自己电子设计与制作上的能力。在刚过了年的初八我就从家里出发了。

培训的课程对于我们来说,还是很有难度的。在前三天的时间里,老师给我们讲了课。我感觉到自己知识的匮乏,老师的讲课我有很多都听不懂,很多知识和名词都不是很清楚起含义。于是我就通过查资料,看书和问的途径,尽可能的弄懂这些内容。虽然有些知识我还是不太懂,但现在我已经知道个大概了。

培训的重头戏有两个:一个是各个模块的硬件制作;一个是程序的调试。在硬件的制作中,我们遇到了很多的问题。比如:各集成芯片的引脚功能和分布不清楚,二极管,三极管的极性不是特别熟悉。我和其他同学,分工合作,查资料,每个人查找一部分的集成芯片的功能和引脚图。查到资料并看懂了之后,我们就知道了如何去完成电路的焊接。还有每个模块都采用万能板焊接,使得整个的布线也有些不合理,使得我的各个模块连接在一起之后看起来很复杂,到处都是线。这样不利于查错,所以当我有的地方错了之后我要用很多时间去查错。当我把单片机接好后,通电源时结果单片机发热了,我赶紧取下来一看,原来是太激动了,把单片机安反了。在连接温度传感器LM35时,由于没看对LM35的特性,将其接反烧掉一个。在程序的调试过程中,我的A1、A2所出来的波形跟课件上的也有些不同,多出了一条缝。结果看其他同学的也是这样,才知道不是我焊接的问题,而是其他地方出了问题。在调试过程中,我对原理有了更清楚的理解。通过老师的讲解,同学间的交流和自己的学习,对单片机等集成模块有了更深的理解,知道了其功能和使用方法。在调试的过程中发现了更多问题。首先是调试单片机板。我们把程序中的错误进行了修改,尤其是地址,并且确定无误后,烧入单片机。在模数的调试过程中,我一直出不了结果我花了整整两天去检查没弄出来,我重新焊了一个,结果还是不行,最后才发现我的74LS245与74LS138两个芯片一起坏了。当换了两个芯片后一下就好了。

这次的培训,我还学会了示波器,知道怎样调波形了。同时我也学习了Keil μvison、AVR fighter等软件和硬件工具的使用,对单片机有了基本的运用能力,在实践方面也积累了不少经验,在电子设计方面,有了一定的基础,这次培训使我的兴趣有了拓展,我们有了获得新知的强烈渴望。

分享到搜狐微博