⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trime+key.c

📁 AT89S52控制的18B20数字温度传感器
💻 C
字号:
/*=============================================
                 温度控制器

           广州工程职业技术学院
              传感器课程设计

指导老师:    冯伟
    作者:    GIT-3408-YOUJJYY (方畅,曹文荣,梁锐权)
    时间:    2007-4-25

温度传感器用单总线DS18B20
CPU为AT89S52,三个按键(UP,DOWN,SET)
温度调节上限为125度,下限为-55度(本程序只能用于单只18B20)

================================================*/
#include <at89x52.h>
#include <intrins.h>
#include <LED_Display.h>

/*--------用于按键可位寻址的状态寄存器-----------*/
static unsigned char bdata StateREG;      
sbit DS1820ON=StateREG^0;			       //DS18B20是否存在
sbit SetTF=StateREG^1;					   //是否是在温度设置状态
sbit KeySETDown=StateREG^2;			       //"1"为已按过SET键,"0"为没按过SET按
sbit PowTF=StateREG^3;                     //电源标识("0"为开电源,"1"为关电源)
sbit KeyTF=StateREG^4;                     //"0"为按键允许,"1"为不允许
sbit KeySETDowning=StateREG^5;             //SET是否正在按下
sbit LEDTF=StateREG^6;					   //开机LOG标志位

static unsigned char bdata TLV _at_ 0x0029; //温度变量高低位
static unsigned char bdata THV _at_ 0x0028;
static signed char TMV;                     //转换后的温度值
static unsigned char KeyV,TempKeyV;         //键值
static signed char TMRomV _at_ 0x0027;      //高温度限制
static signed char TMSetV _at_ 0x0026;      //温度设定值
static unsigned char KSDNum;                //SET键连按时的采集次数
static unsigned char IntNum,IntNum2,IntNum3;//中断发生次数(IntNum用于SET长按检测,IntNum2用于设定状态时LED闪烁,IntNum用于连按其他键)
static unsigned int IntNum4,IntNum5;
static signed char Sign;                    //负号标识
static unsigned char LED_One,LED_Two,LED_Three;
/*------------------------------------------
              数值转换
-------------------------------------------*/
void V2ToV(void)
{
 TLV>>=4;
 THV<<=4;   //读出的高低位数值移位
 TMV=TLV|THV; //合并高低位放入TM为实际温度值
 Sign=0;
  if(SetTF||!Key_SET)Sign=TMSetV>>7; //取符号
  else Sign=TMV>>7;
  if(Sign)
  {
   if(SetTF||!Key_SET)
    {
	 LED_One=(~(TMSetV-1))/100;    //SET状态下显示设定值
	 LED_Two=((~(TMSetV-1))-LED_One*100)/10;
	 LED_Three=(~(TMSetV-1))-LED_One*100-LED_Two*10;
	 }
	else
	 {
	  LED_One=(~(TMV-1))/100;     //转换百位数值
	  LED_Two=((~(TMV-1))-LED_One*100)/10;  
	  LED_Three=(~(TMV-1))-LED_One*100-LED_Two*10;
	  }
	}
   else
    {
	 if(SetTF||!Key_SET)
	  {
	   LED_One=TMSetV/100;    //SET状态下显示设定值
	   LED_Two=(TMSetV-LED_One*100)/10;
	   LED_Three=TMSetV-LED_One*100-LED_Two*10;
	   }
	 else
	  {
	   LED_One=TMV/100;     //转换百位数值
	   LED_Two=(TMV-LED_One*100)/10;  
	   LED_Three=TMV-LED_One*100-LED_Two*10;
	   }
	  }
//======转换LED字段=======
 if(LED_One)LED_Two=BCD_ASCII[LED_Two+1];   //超过百时十位的处理
 else
  {
   if(LED_Two==0)LED_Two=BCD_ASCII[0];
   else LED_Two=BCD_ASCII[LED_Two+1];
   }
 if(Sign)LED_One=0xf7;
 else
  {
   if(LED_One==0)LED_One=BCD_ASCII[0];
   else LED_One=BCD_ASCII[LED_One+1];
   }
 LED_Three=BCD_ASCII[LED_Three+1];
 }
 /*-------------------------------------
        初始化DS1820
 -------------------------------------*/
 void InitDS1820(void)
 {
  TMPort=1;
  _nop_();
  TMPort=0;
  Delay_6n5_8us(77);           //延时 DS1820复位时间要500US的抵电平
  TMPort=1;
  Delay_6n5_8us(16);	 //延时112US 等待DS1820的回应
  if(!TMPort){DS1820ON=1;ON_DS1820=1;}             //检测是否有DS1820
  else {DS1820ON=0;ON_DS1820=0;}
  Delay_6n5_8us(55);
  TMPort=1;
  }
/*----------写数据-----------*/
void Write_Data(uchar T_DATA)
 {
   uchar i,DATA_T;
   DATA_T=T_DATA;
   for(i=0;i<=7;i++)
   {
    TMPort=0;
    Delay_6n5_8us(1);			   //延时14微秒
    if(DATA_T&0x01)TMPort=1;
	else TMPort=0;
	DATA_T>>=1;
    Delay_6n5_8us(7);	           //延时54微秒
	TMPort=1;
	_nop_();
	}
	TMPort=1;
  }
/*-------------------------------
       写入温度限制值
发出4EH写ROM指令后连发两个字节
--------------------------------*/
void WriteDS1820(void)
{
 uchar TM_H,TM_L;
  TM_H>>=4;
  TM_L<<=4;
  Write_Data(TM_H);
  Write_Data(TM_L);
}
/*---------读数据------------*/
uchar ReadTM(void)
{
 uchar i,TM_DATA;
 for(i=0;i<=7;i++)
 {
  TM_DATA>>=1;
  TMPort=1;
  _nop_();_nop_();
  TMPort=0;
  _nop_();_nop_();_nop_();
  TMPort=1;
  Delay_6n5_8us(1);
  if(TMPort)TM_DATA|=0x80;
  Delay_6n5_8us(6);
  }
  return (TM_DATA);
 }
/*----------------------------------
         读出温度值
将温度高位和低位,高温度限制位从DS1820中读出
    低位存入29H(TEMPER_L),
    高位存入28H(TEMPER_H),
    高温度限制位存入27H(TMRomV) 
---------------------------------*/
void ReadDS1820(void)
{
 TLV=ReadTM();
 THV=ReadTM();
 TMRomV=ReadTM();
 }
/*===============主程序================*/
void main(void)
{
 StateREG=0;             //初始化变量
 SetTF=1;				 //在设置温度状态
 PowTF=1;                //关电源
 THV=0;					 //温度数据存储(高地址:0x0028,低地址:0x0029) TLV=0;
 TMV=0;					 //转换后的温度值
 KeyV=0;
 KSDNum=0;				 //SET键连按时的采集次数
 IntNum=0;				 //用于SET长按检测
 IntNum2=0;				 //用于设定状态时LED闪烁
 IntNum3=0;
 LED_One=0;
 LED_Two=0;
 Beep=1;
 LEDTF=0;
 InitDS1820();//初始化
 Write_Data(0xcc);//跳过ROM
 Write_Data(0xb8);//E2RAM中的温度上限值调入RAM
 InitDS1820();
 Write_Data(0xcc);//跳过ROM
 Write_Data(0xbe);//读出温度指令
 ReadDS1820();//读出温度值和上限值
 TMSetV=TMRomV;//拷贝保存在DS1820ROM里的上限值到TMSet
 EA=1;		   //允许CPU中断
 ET0=1;		   //定时器0中断开
 TMOD=0x01;	   //设定时器0为模式1,16位模式
 TH0=0XB1;
 TL0=0XDF;     //设定时值为20MS
 TR0=1;        //开定时
 while(1);
 }
 /*----------------------------------
 定时器0中断处理中键扫描和显示

 ------------------------------------*/
 void KeyAndDis_Time0(void) interrupt 1 using 2
 {
  TH0=0XB1;
  TL0=0XDF;                    //设定时值为20MS
  LEDPort=0xff;				   //关闭LED
/*-----对按下的键值附值------*/
  if(!Key_UP)KeyV=1;		   //检测Key_UP是否按下
  if(!Key_DOWN)KeyV=2;		   //检测Key_DOWN是否按下
  if(!Key_SET)KeyV=3;		   //检测Key_SET是否按下
  KeySETDowning=0;  //清除
/*-------检测是否有键按下------*/
  if(KeyV!=0)				   //KeyV不等于零表示有键按下
   {
	Delay_1ms(10);             //延时防抖  按下10MS再测
	if(!Key_UP)TempKeyV=1;	  
	if(!Key_DOWN)TempKeyV=2;
	if(!Key_SET)TempKeyV=3;
	if(KeyV==TempKeyV)        //两次值相等为确定接下了键
	 {
/*---判断是否是Key_SET按下---*/
	  if(KeyV==3)         //按下SET键,如在SET状态就退出,否则进入
	   {
		 KeySETDowning=1;   //表明SET正在按下
		 PowTF=0;         //电源标识开
		 if(!KeyTF)		  //KeyTF为1不允许执行下程序
		 if(SetTF)
		 {
		  SetTF=0;      //是否是在温度设置状态标识位标识退出设定
		  InitDS1820();
		  Write_Data(0xcc);  //跳过ROM
		  Write_Data(0x4e);  //写温度上限指令
		  WriteDS1820();     //写温度上限到DS1820ROM
		  InitDS1820(); 
		  Write_Data(0xcc);	//跳过ROM匹配
		  Write_Data(0x48);  //温度上限值COPY回E2PRAM
		   }
		  else SetTF=1;	      //为下一次没按SET时,按其他键作准备
		  if(!KeySETDown){KeySETDown=1;OPen=1;}	   //是否已按过SET键标识
		  else KSDNum+=1;  //前一秒内有按SET则开始计数
		  }
/*---Key_UP和Key_DOWN的检测---*/
	  if(SetTF)  //在SET状态下
		  {
		   if((KeyV==1)&&(!KeyTF))TMSetV+=1,OPen=0;    //上调温度
		   if((KeyV==2)&&(!KeyTF))TMSetV-=1,OPen=0;   //下调温度
		   if(TMSetV<=-55)TMSetV=-55;
		   if(TMSetV>=125)TMSetV=125;
		   }
	  if((!KeyTF)&&(IntNum3==0))KeyTF=1;     //判断键盘是否处于可用时
	  }
/*---按键长按的处理---*/
     if(KeySETDown)IntNum+=1;    //在2秒内按下了SET则计中断发生次数用于长按SET时计时用
     if(IntNum>60)
      {
       IntNum=0;
	   KeySETDown=0;
/*--按长SET的处理--*/
	   if(KSDNum>=60)   //如一直长按了SET 3秒左右
	    {
	     RelayOutPort=1;  //关闭控制对象
	     PowTF=1;		  //电源标识关
		 LED_Display(0,21,2,"--__OFF__-2007_6_23__--");
		 LEDPort=0xbf;   //显示"--"         
	     LEDOneC=0;
		 LEDTwoC=0;
	     LEDThreeC=0;
		 LED_C=0;
	     Delay_100ms(40);	//延时4S
	     LEDOneC=1;	   //关显示
	     LEDTwoC=1;
	     LEDThreeC=1;
  	     IntNum=0;
	     IntNum2=0;
	     IntNum3=0;
		 IntNum4=0;
		 Beep=1;
		 OPen=1;
		 LEDTF=0;
	     }
	  KSDNum=0;
	  }
	}
   KeyV=0;	   //清空变量准备下次键扫描
   TempKeyV=0;
   OPen=1;
/*----开电源程序----*/ 
   if(!PowTF)
    {
	 if(LEDTF==0)
	 {
	  LED_Display(0,26,2,"--__OPEN__--_3408_YOUJJYY_--");
	  if(DS1820ON==0)LED_Display(0,14,2,"--__NO-SENSOR__--");
	  LEDTF=1;
	  }
	 InitDS1820();
	 if(DS1820ON==0)IntNum5+=1;
	 if((DS1820ON==0)&&(IntNum5>400))
	 {LED_Display(0,14,2,"--__NO-SENSOR__--");IntNum5=0;IntNum4+=500;}
	 Write_Data(0xcc);
	 Write_Data(0x44);
	 Delay_6n5_8us(152);	  //延时1000uS 等转换完成
	 InitDS1820();
	 Write_Data(0xcc);
	 Write_Data(0xbe);  //读出温度指令
	 ReadDS1820();  //读出温度值
	 V2ToV();       //转换显示值
	 if(TMV>TMSetV)RelayOutPort=0,Beep=0,IntNum4+=1;  //根据采集的温度值控制对象
	 else if(DS1820ON==1) RelayOutPort=1,Beep=1,IntNum4=0;
	 if(IntNum4>=2000)KSDNum=60,IntNum=60,KeySETDown=1,KeyV=4;
	 if(SetTF)IntNum2+=1,OPen=1;       //用于闪烁计数
	 if(IntNum2>50)IntNum2=0,OPen=0;
/*---连按Key_UP或Key_DOWN键时的采集次数--*/
	 if(KeyTF)IntNum3+=1;       //用于防止按键连按
	 if(IntNum3>15)	            //检测按键是否超过
	  {
	   IntNum3=0;
	   KeyTF=0;
	   }
	 if((SetTF)&&(IntNum2<20))goto InitEnd;  //使LED闪烁
	 LEDPort=LED_One;
	 LEDOneC=0;
	 Delay_1ms(1);
	 LEDOneC=1;         //显示百位数
	 LEDPort=LED_Two;
	 LEDTwoC=0;
	 Delay_1ms(1);
	 LEDTwoC=1;         //显示十位数
	 LEDPort=LED_Three;
	 LEDThreeC=0;
	 Delay_1ms(1);
	 LEDThreeC=1;       //显示个位数
	 }
	InitEnd:	
	        if(!PowTF){LEDPort=0x34;
	        LED_C=0;
	        Delay_1ms(1);
	        LED_C=1;}
 }
	   


 
 
 
 
              







⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -