职场文秘网

首页 > 心得体会 > 经验交流 / 正文

基于51单片机数字温度计设计课程设计

2020-12-29 21:51:36

 

 课

 题:

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

 业:

 电子信息工程 班

 级:

  班 学

 号:

 姓

 名:

  指导教师:

 设计日期:

 成

 绩:

  XX大学XX学院电气学院

  基于51单片机数字温度计设计 一、设计目的

 1、掌握单片机电路的设计原理、组装与调试方法。

 2、掌握LED数码显示电路的设计和使用方法。

 3、掌握DS18B20温度传感器的工作原理及使用方法。

 二、设计要求

 1、本次单片机课程设计要求以51系列单片机为核心,以开发板为平台。

  2、设计一个数字式温度计,要求使用DS18B20温度传感器测量温度。

  3、经单片机处理后,要求用4位一体共阴LED数码管来设计显示电路,以显示测量的温度值。

  4、另外还要求在设计中加入报警系统,如果我们所设计的系统用来监控某一设备,当设备的温度超过或低于我们所设定的温度值时,系统会产生报警。

  5、要求在设计中加入上下限警报温度设置电路。

 三、 设计的具体实现 1数字温度计设计的方案

 在做数字温度计的单片机电路中,对信号的采集电路大多都是使用传感器,这是非常容易实现的,所以可以采用一只温度传感器DS18B20,此传感器,可以很容易直接读取被测温度值,进行转换,就可以满足设计要求。采集之后,通过使用51系列的单片机,可以对数据进行相应的处理,再由LED显示电路对其数据进行显示。

 2系统设计框图 温度计电路设计总体设计方框图如下图所示,控制器采用单片机AT89C51,温度传感器采用DS18B20,用4位一体共阴LED数码管以串口传送数据实现温度显示。此外,还添加了报警系统,对温度实施监控。

 3主控器AT89C51芯片

 对于单片机的选择,可以考虑使用8031与8051系列,由于8031没有内部RAM,系统又需要大量内存存储数据,因而不适用。AT89C51 以低价位单片机可为提供许多高性价比的应用场合,可灵活应用于各种控制领域,对于简单的测温系统已经足够。单片机AT89C51具有低电压供电和体积小等特点,四个端口只需要两个口就能满足电路系统的设计需要该器件是INTEL公司生产的MCS一5l系列单片机中的基础产品,采用了可靠的CMOS工艺制造技术,具有高性能的8位单片机,属于标准的MCS—51的CMOS产品。

 AT8951的管脚如下图所示:

  AT89C51芯片管脚图 4时钟电路

 80C51时钟有两种方式产生,即内部方式和外部方式。80C51中有一个构成内部震荡器的高增益反向放大器,引脚XTAL1和XTAL2分别是该放大器的输入端和输出端。本次采用内部震荡电路,瓷片电容采用22PF,晶振为12MHZ。

  晶体震荡电路图

 5 复位电路

  单片机系统的复位电路在这里采用的是上电+按钮复位电路形式,其中电阻R采用10KΩ的阻值 ,电容采用10μF的电容值。

  复位电路 6 温度传感电路 DALLAS 最新单线数字温度传感器DS18B20是一种新型的“一线器件”,其体积更小、更适用于多种场合、且适用电压更宽、更经济。DALLAS 半导体公司的数字化温度传感器DS18B20是世界上第一片支持“一线总线”接口的温度传感器。温度测量范围为-55~+125 摄氏度,可编程为9位~12 位转换精度,测温分辨率可达0.0625摄氏度,分辨率设定参数以及用户设定的报警温度存储在EEPROM 中,掉电后依然保存。被测温度用符号扩展的16位数字量方式串行输出。

 DS18B20内部结构主要由四部分组成:64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。DS18B20的管脚排列、各种封装形式,DQ 为数据输入/输出引脚。开漏单总线接口引脚。当被用着在寄生电源下,也可以向器件提供电源;GND为地信号;VDD为可选择的VDD引脚。当工作于寄生电源时,此引脚必须接地,如下图所示。

 DS18B20管脚图 7 显示电路 对于数字温度的显示,我们采用4位一体共阴LED数码管。足够显示0~100中各位数,并且还能显示一位小数部分。

 4位LED数码显示管 8 温度报警电路

 对于数字温度计的设计,除了温度的数字显示功能外还加入了报警系统,当测量的温度超过或低于我们所设定的温度值时,系统会产生报警并亮红灯报警。

  其电路图如下所示。

 蜂鸣器红灯报警系统电路图

 源程序:

 /******************************************************************** * 程序名;

 基于51单片机的温度计 * 功

 能:

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

 *********************************************************************/ #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);

 #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数码管动态显示头文件 * 功

 能:

  通过定时器0延时是数码管动态显示

 **********************************************************************/ #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 /******************************************************************** * 程序名;

 DS18B20头文件

 * 说

 明:用到的全局变量是:无符号字符型变量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)

 {

 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)

 //若上限温度为负,将上限温度转换成有符号数 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 /********************************************************************

  * 程序名;

 基于51单片机的温度计

  * 功

 能:

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

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

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

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

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

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

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

  #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();

 }

  } /********************************************************************** * 程序名;

  ds18b20keyscan函数 * 功

 能:

  通过键盘设定设定上下限报警温度

 **********************************************************************/ #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智能测温,而其相关知识我们很模糊甚至可以说一无所知,不过后来,我们通过查找一些相关的资料书以及寻求辅导老师的帮助,又经过我们的主动思考,理清思路,终于将程序修改正确。在仿真时,由于我们有了之前的数模电课设仿真经验,所以此时我们课设进行的很顺利,并没有受到什么大的阻碍。

 通过此次单片机课程设计,我们明白了很多,理论指导实践,但是理论也需要实践给予证明,不能盲目的相信书本,凡事都要通过自己的思考推敲,否则自己不会取的大的进步。而且在平时的学习生活中应该多和周围的同学相互学习,交流经验,遇到不会的东西时,切忌焦躁,首先要经过自己的独立思考,有了一定想法后,可以去查找相关的资料书刊或者找同学讨论,如果实在解释不了,再去找辅导老师,在这个遇到问题解决问题的过程中,不断加强自我的动脑能力,进而去指导动手能力,也只有这样,在思路清晰,条理顺畅的时候,再去进行软件编写和硬件操作工作,才有可能起到事半功倍的效果。

 五、 附录

 系统硬件原理电路图

 数字温度计设计器材表

 单片机STC89C52 1 DS18B20 1 晶振12M 1 三极管8850 1 电容30PF 2 电解电容10UF/25V 1 小蜂鸣器 1 LED ø5红 1 电阻10k,3k,2k,1k,510,330 各5 4位一体共阴数码管 1 AC/DC(5V/1A)电源

 1 IC插座40 1 9X15cm万用板 1 六、 参考文献 1、李群芳编.《单片微型计算机及接口技术》[M].电子工业出版社.

 2、楼然苗编.《51系列单片机设计实例》[M].北京航空航天大学出版社. 3、黄勤编.《计算机硬件技术基础实验教程》[M].重庆大学出版社.

 

Tags: 温度计   单片机   课程设计  

搜索
网站分类
标签列表