专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

基于单片机的ds18b20温度测量系统

作者:佚名   来源:本站原创   点击数:  更新时间:2010年05月20日   【字体:
用Keil写的。温度传感器用DS18B20,单片机AT89C51.

 

/*温度范围-55.0度~+99.9度,用四个七段LED显示出来*/

#include 
#include 
#include   //要用到取绝对值函数

sbit DQ=P3^7;//DS18B20的数据线和单片机的P3.7口相接,且定义DQ为变量名

sbit led3_g=P2^4;//单片机的P2.4口定义为LED1的g段,表示温度的正负
sbit led0_off=P3^3;//led0熄灭信号接到P3.3口
sbit led1_off=P3^4;//led0熄灭信号接到P3.4口
sbit led2_off=P3^5;//led0熄灭信号接到P3.5口

float low_limitedTmp,high_limitedTmp;

                                    //设置的报警最低温度和最高温度,因为要在几个函数中用,故为全局变量
int Final_tmpvalue;  //存放最终得到的十进制有符号并放大10倍的温度值

unsigned char key_value;//存放键值
unsigned char sys_state;//存放系统状态,共有3态
                                            //正常测温状态sys_state=0、调最低温度状态sys_state=1、

                                             //调最高温度状态sys_state=2
unsigned char led_pst;//存放正在设置的led位置值
                                           //led_pst=0表示正在设置最右边的LED,加1依次往左表示

 


/*****************延时函数**************
*************功能:延时Nx15us***********/
void  delay_multi_15us(unsigned int N)
{
      do{
        _nop_();//1
        _nop_();//2
        _nop_();//3
        _nop_();//4
        _nop_();//5
        _nop_();//6
        _nop_();//7
        _nop_();//8
        _nop_();//9
        _nop_();//10
        _nop_();//11
        _nop_();//12
        _nop_();//13
        N--;//计满15us后N减1
      }while(N);
}


/*********************初始化函数******************************
***********功能:初始化DS18B20,以便能进行后续读写操作********/
bit  Init_DS18B20(void)//返回为位的函数,以便检测是否成功启动
{
   DQ=0;//先拉低延时一段时间
   delay_multi_15us(50);//延时750us,协议要求480us~980us,满足要求
   DQ=1;//再拉高延时
   delay_multi_15us(6);//延时等待返回低电平
   return(DQ);
   delay_multi_15us(26);//再延时一段时间
}


/****************** 写一字节数据函数*********************
************功能:向DS18B20写一个字节的数据内容**********/
void  WritetoDS_onebyte(char command)
{
   unsigned char i; //8位数据记位,为了节约资源定义为8位
   bit temp;
   for(i=0;i<8;i++)
   {
     temp=command&0x01;//将最低位提取出来
     command>>1;//将其右移一位
     if(temp)//如果写入的是1,则按1的操作:先置DQ=0,延时15us,再置DQ=1,延时45us
     {
    DQ=0;
    delay_multi_15us(1);//延时15us
    DQ=1;
    delay_multi_15us(3);//延时45us
     }
  else //如果写入的是0,则按0的操作:先置DQ=0,延时60us,再置DQ=1
  {
    DQ=0;
    delay_multi_15us(4);//延时60us
    DQ=1;
  }
   }
}


/****************** 读一字节数据函数*********************
************功能:从DS18B20读一个字节的数据内容**********/
unsigned char  ReadfromDS_onebyte()//char类型函数,最后要返回一个字节数据
{
   unsigned char i,dat;
   dat=0;//初始化存放读取内容的变量
   for(i=0;i<8;i++)
   {
      DQ=0;    //先拉低约4us,符合至少1us的要求
   _nop_();
   _nop_();
   _nop_();
   _nop_();
   DQ=1;  //再拉高延时
   delay_multi_15us(1);//延时15us
   _nop_();//为了保证大于15us再延时几us
   _nop_();
   _nop_();
   if(DQ) //如果读出为1,按1读:
   {
      dat=dat|0x80;//存进最高位,待会右移
   }
   else
   {
      dat=dat|0x00;//存进最高位,待会右移
   }
   dat=dat>>1;
   delay_multi_15us(4);//延时60us
   }
   return(dat);
}        


/************************发送温度转换命令函数 ****************************
**************功能:发送温度转换命令到DS18B20,启动温度转换功能************/
void   SendCommand_TmpConvert(void)
{
   while(Init_DS18B20());//初始化DS18B20,等待返回低电平信号
   WritetoDS_onebyte(0xcc);//写入跳过序列号命令字 Skip Rom
   WritetoDS_onebyte(0x44);//写入温度转换命令字 Convert T,启动温度转换功能
}


/************************发送读取温度命令函数 ****************************
**************功能:发送温度读取命令到DS18B20,读取DS18B20中的温度值************/
void   SendCommand_TmpRead(void)
{
   while(Init_DS18B20());//初始化DS18B20,等待返回低电平信号
   WritetoDS_onebyte(0xcc);//写入跳过序列号命令字 Skip Rom
   WritetoDS_onebyte(0xbe);//写入温度读取命令字 ,以便后续读取温度值
}


/******************************温度值获取和计算函数***********************
***************功能:获得温度值并进行计算,得到最终十进制温度值***********/
int  Get_TmpValue(void)//返回温度最终十进制值
{
   unsigned  int Temp_tmpvalue;//存放中间温度变量
   float temp;//存放中间的浮点数,因为分辨率为0.0625,故先算出来的应该为浮点数
   unsigned char low,high;//存放读取出来的温度低、高字节

   SendCommand_TmpRead();//送读取温度命令
   low=ReadfromDS_onebyte();//读取两个字节的数据,先送入低字节
   high=ReadfromDS_onebyte();//再送入高字节

   Temp_tmpvalue=high;//数据处理,将两个字节合并
   Temp_tmpvalue<<=8;
   Temp_tmpvalue|=low;
   Final_tmpvalue=Temp_tmpvalue;//直接将无符号数变为有符号数
                                //因为计算机中对于负数是利用补码来表示的
                    //若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的Final_tmpvalue

   temp=Final_tmpvalue*0.0625; //使用DS18B20的默认分辨率12位, 精确度为0.0625度, 

                                                         //即读回数据的最低位代表0.0625度
   Final_tmpvalue=temp*10+(Final_tmpvalue>0?0.5:-0.5); //将它放大10倍, 

                                                        //使显示时可显示小数点后1位, 并对小数点后第二进行4舍5入
                                                       //如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度
                                                       //如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度
                                                       //大于0加0.5, 小于0减0.5
   return(Final_tmpvalue);//最终返回放大10倍的十进制有符号温度值
}


/**************************温度LED显示函数*****************************
*******************功能:将温度值显示在LED数码管上*********************/
void  Display_TmpValue(int tmp)//参数将引用函数Get_TmpValue(),

                                                        //或者直接引用全局变量Final_tmpvalue
                               //或者显示设置的最高或者最低温度high_limitedTmp*10、low_limitedTmp*10
{
   unsigned char dat[3]={0,0,0};//定义分别存温度的十、个、小数三位值
   unsigned char temp;
   unsigned int v;

   LED1_g=tmp>0?0:1;//确定负号显示与否:温度为正不点亮LED1_g,

                                          //为负则置P2.4=1,即点亮LED1_g,显示为一个“-”号

   v=abs(tmp); //取温度的绝对值
   dat[0]=v%100; //计算十位数值
   dat[1]=(v-(dat[0]*100))%10; //计算个位数值
   dat[2]=v-(dat[0]*100)-(dat[1]*10);//计算小数位数值

   temp=dat[0];//将十位和个位合并送到P0口显示
   temp<<=4;
   temp|=dat[1];
   P0=temp;//已包含reg51.h头文件,可以直接用P口
   P2&=0x10;//先将P2口低4位清0,高4位不改变
   P2|=dat[2];//将小数位送到P2口低4位显示:不改变高4位,把低4位送入P2口低4位
}


/************************************报警函数**************************************
**************功能:当温度超过设置的最高值或者低于最低值时系统报警*****************/
void  Alarm_tmp(int tmp)   //参数将引用函数Get_TmpValue()

                                                //得出的温度值全局变量Final_tmpvalue
{
   sbit  BUZZER=P2^5; //定义蜂鸣器口为P2.5口
   sbit  LED_R=P2^6; //定义红灯为P2.6口
   sbit  LED_G=P2^7; //定义绿灯为P2.7口
   float temp;
   temp=tmp/10.0; //因为tmp为放大10倍的温度值,要再缩小10倍
   if((temp>=high_limitedTmp)||(temp<=low_limitedTmp))  //高于设置最高温或者低于最低温
   {
       BUZZER=1;  //蜂鸣器响
    LED_R=1;   //红灯亮
    LED_G=0;   //绿灯灭
   }
   else      //正常
   {
    BUZZER=0;  //蜂鸣器停
    LED_R=0;   //红灯灭
    LED_G=1;   //绿灯亮
   }
}


/**********************************键盘扫描函数************************************
***************功能:当有键盘中断时,进入键盘查询键值,得出按下的键值**************/
void Int0_key_Calculate()  interrupt 0  //中断程序,用外部中断0
{
    unsigned char row,col;//分别存放键盘为0的行和列号
 int temp;
 sbit P1_4=P1^4;
 sbit P1_5=P1^5;
 sbit P1_6=P1^6;
 sbit P1_7=P1^7;

 EA=0;//关cpu中断,在完成一个键的过程中不能有中断产生
 delay_multi_15us(800);//进入中断,说明有键按下,先延时12ms去抖

 if((P1|0x10)!=1)//有键按下,进入查询程序
 {
     switch(P1)//根据P1口来查哪一行为低电平,P1=1111xxxx,其中xxxx中只有一个为0
  {
    case 0x0FE:row=0;break;  //如果P1=1111 1110,则置row=0
    case 0x0FD:row=1;break;  //如果P1=1111 1101,则置row=1
    case 0x0FB:row=2;break;
    case 0x0F7:row=3;break;
    default:break;
  }
  P1_5=1;//先置P0.4口为0,P0.5~P0.7为1
  P1_6=1;
  P1_7=1;
  if((P1|0x10)!=1) //如果P0.0~P0.3中有0,则列号为P0.4,置col=0标志
     col=0;
  else  //否则继续查P0.5
  {
     P1_4=1;//置P0.5口为0
     P1_5=0;
     P1_6=1;
     P1_7=1;
     if((P1|0x10)!=1) //如果P0.0~P0.3中有0,则列号为P0.5,置col=1标志
        col=1;
     else  //否则继续查P0.6
    {
       P1_4=1;//再置P0.6口为0
       P1_5=1;
       P1_6=0;
       P1_7=1;
       if((P1|0x10)!=1) //如果P0.0~P0.3中有0,则列号为P0.6,置col=2标志
          col=2;
    else  //否则继续查P0.7
      {
         P1_4=1;//再置P0.5口为0
         P1_5=1;
         P1_6=1;
         P1_7=0;
         if((P1|0x10)!=1) //如果P0.0~P0.3中有0,则列号为P0.7,置col=3标志
             col=3;
      }
    }
  }
  temp=row;//将row和col合并,以便查键值
  temp<<=8;
  temp|=col;
  switch(temp)//键值查询赋值
  {
     case 0x0000:key_value=1;break;//第0行第0列,键值为1
     case 0x0001:key_value=2;break;//第0行第1列,键值为2
     case 0x0002:key_value=3;break;
     case 0x0003:key_value=4;break;
     case 0x0100:key_value=5;break;//第1行第0列,键值为5
     case 0x0101:key_value=6;break;//第1行第1列,键值为6
     case 0x0102:key_value=7;break;
     case 0x0103:key_value=8;break;
     case 0x0200:key_value=9;break;
     case 0x0201:key_value=0;break;
     case 0x0202:key_value='L';break;//表示要设置最低温度
     case 0x0203:key_value='H';break;//表示要设置最高温度
     case 0x0300:key_value='l';break;//表示按下向左键
     case 0x0301:key_value'r';break;//表示按下向右键
     case 0x0302:key_value='F';break;//表示改变正负号的标志flag
     case 0x0303:key_value='E';break;//表示按下了确认键
     default:key_value=FALSE;break;//无按键按下
  }
 }
  else
      key_value=FALSE; //无键按下,将键值置为FALSE
       
  if(key_value!=FALSE)
      Tmp_Setting();//每一次有键按下进行一次状态查询和温度设置
  
  EA=1;//开cpu中断,准备下次中断
  P1=0x01;//将键盘扫描口低4位写入全1,高四位写入全0,以查下次中断
}


/***************************************单LED跳动显示函数***************************************
***功能:根据LED的位置参数led_pos跳动此位置的单个LED,其他的静止显示************/
void Single_LED_twinkle(void)
{
   unsigned char i;
   
      switch(led_pst)
   {
     case 0:for(i=0;i<2;i++) //正在设置小数位led0,闪2次
         {
         led0_off=0;//将led0熄灭
      delay_multi_15us(20000);//延时300ms,大于人视觉暂留时间
      led0_off=1;//将led0点亮
      delay_multi_15us(20000);//延时300ms,大于人视觉暂留时间
      }  
      break;
  case 1:for(i=0;i<2;i++) //正在设置个位led1,闪2次
         {
         led1_off=0;//将led1熄灭
      delay_multi_15us(20000);//延时300ms,大于人视觉暂留时间
      led1_off=1;//将led1点亮
      delay_multi_15us(20000);//延时300ms,大于人视觉暂留时间
      }
      break;
  case 2:for(i=0;i<2;i++) //正在设置十位led2,闪2次
         {
         led2_off=0;//将led2熄灭
      delay_multi_15us(20000);//延时300ms,大于人视觉暂留时间
      led2_off=1;//将led2点亮
      delay_multi_15us(20000);//延时300ms,大于人视觉暂留时间
      }
      break;
  case 3:for(i=0;i<2;i++) //正在设置符号位led3,闪2次
         {
         led3_g=0;//将led0熄灭
      delay_multi_15us(20000);//延时300ms,大于人视觉暂留时间
      led3_g=1;//将led0熄灭
      delay_multi_15us(20000);//延时300ms,大于人视觉暂留时间
      }
      break;
   }
}


/******************全4个LED跳动显示函数*************************************
*功能:在进入最低极限温度或者最高极限温度设置的初始时将4个LED全部跳动闪烁几下***/
void All_LED_twinkle(int lmt_tmp)//参数将引用low_limitedTmp或者high_limitedTmp
{
   unsigned char i;
   Display_TmpValue(lmt_tmp*10);//先显示上次设置的极限温度

   for(i=0;i<3;i++)//跳动3次
   {
   delay_multi_15us(40000);//延时延时600ms
   led0_off=0;//将led0熄灭
   led1_off=0;//将led1熄灭
   led2_off=0;//将led2熄灭
   led3_g=0;//将led0熄灭
   delay_multi_15us(40000);//延时延时600ms
   led0_off=1;//将led0点亮
   led1_off=1;//将led1点亮
   led2_off=1;//将led2点亮
   led3_g=1;//将led0点亮
   }
}

 

/******************************************温度设置函数*****************************************
************功能:根据键盘扫描值设置报警的最低温度和最高温度*************************/
void Tmp_Setting(void)
{
 unsigned char lmt_low_tmp[3];//lmt_low_tmp[0]、lmt_low_tmp[1]、

                                                     //lmt_low_tmp[2]、lmt_low_tmp[3]分别表示
                                 //调节中的小数位数字、个位数字、十位数字、正负号(正用0,负用1表示)
 unsigned char lmt_high_tmp[3];//lmt_high_tmp[0]、lmt_high_tmp[1]、

                                                      //lmt_high_tmp[2]、lmt_high_tmp[3]分别表示
                                //调节中的小数位数字、个位数字、十位数字、正负号(正用0,负用1表示)
 unsigned int tmp[2];//存放low_limitedTmp、 high_limitedTmp的绝对值放大10倍的值
   tmp[0]=abs(low_limitedTmp*10);
 tmp[1]=abs(high_limitedTmp*10);
 unsigned int tmp;

   if(sys_state==0)//查状态为状态0:正常测温状态
 {
    switch(key_value)//查此时按下的键值
    {
      case 1:
   case 2:
   case 3:
   case 4:
   case 5:
   case 6:
   case 7:
   case 8:
   case 9:
   case 0:
   case 'l':
   case 'r':
   case 'F':
   case 'E':break; //在sys_state=0正常测温下,按以上键均无效

   case 'L':sys_state=1;//按“VL”,则转换为设置温度下限状态
            led_pst=0;//默认为最右边的led0设置
            
      lmt_low_tmp[3]=(low_limitedTmp>0?0:1);//提取分离极限最低温度的每一位数值
      lmt_low_tmp[2]=tmp[0]%100;
      lmt_low_tmp[1]=(tmp[0]-lmt_tmp[2]*100)%10;
      lmt_low_tmp[0]=tmp[0]-lmt_tmp[2]*100-lmt_tmp[1]*10;
   
      All_LED_twinkle(low_limitedTmp);//全部闪烁3次
      Single_LED_twinkle(led_pst);//再默认为最右边的led闪烁设置

      break;

   case 'H':sys_state=2;//按“VH”,则转换为设置温度下限状态
            led_pst=0; //默认为最右边的led0设置

            lmt_high_tmp[3]=(high_limitedTmp>0?0:1);//提取分离极限最高温度的每一位数值
      lmt_high_tmp[2]=tmp[1]%100;
      lmt_high_tmp[1]=(tmp[1]-lmt_tmp[2]*100)%10;
      lmt_high_tmp[0]=tmp[1]-lmt_tmp[2]*100-lmt_tmp[1]*10;

      All_LED_twinkle(low_limitedTmp);//全部闪烁3次
      Single_LED_twinkle(led_pst);//再默认为最右边的led闪烁设置

      break;
    }
 }


 if(sys_state==1)//查状态为状态1:设置最低极限温度状态
 {
    switch(key_value)//查此时按下的键值
    {
      case 1:switch(led_pst)
          {
      case 0:lmt_low_tmp[0]=1;//小数位为1
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 1:lmt_low_tmp[1]=1;//个位为1
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 2:lmt_low_tmp[2]=1;//十位为1
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 3:Single_LED_twinkle(led_pst);//相应led闪烁
             break;//无效
    }break; 

   case 2:switch(led_pst)
          {
      case 0:lmt_low_tmp[0]=2;//小数位为2
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 1:lmt_low_tmp[1]=2;//个位为2
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 2:lmt_low_tmp[2]=2;//十位为2
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 3:Single_LED_twinkle(led_pst);//相应led闪烁
             break;//无效
    }break; 
 
   case 3:switch(led_pst)
          {
      case 0:lmt_low_tmp[0]=3;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_low_tmp[1]=3;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_low_tmp[2]=3;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 
   case 4:switch(led_pst)
          {
      case 0:lmt_low_tmp[0]=4;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_low_tmp[1]=4;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_low_tmp[2]=4;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
  
   case 5:switch(led_pst)
          {
      case 0:lmt_low_tmp[0]=5;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_low_tmp[1]=5;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_low_tmp[2]=5;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 
   case 6:switch(led_pst)
          {
      case 0:lmt_low_tmp[0]=6;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_low_tmp[1]=6;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_low_tmp[2]=6;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 

   case 7:switch(led_pst)
          {
      case 0:lmt_low_tmp[0]=7;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_low_tmp[1]=7;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_low_tmp[2]=7;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 
   case 8:switch(led_pst)
          {
      case 0:lmt_low_tmp[0]=8;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_low_tmp[1]=8;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_low_tmp[2]=8;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 
   case 9:switch(led_pst)
          {
      case 0:lmt_low_tmp[0]=9;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_low_tmp[1]=9;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_low_tmp[2]=9;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 
   case 0:switch(led_pst)
          {
      case 0:lmt_low_tmp[0]=0;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_low_tmp[1]=0;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_low_tmp[2]=0;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 

   case 'l':switch(led_pst)
           {
      case 0:led_pst=1;//按一次向左键led向左移一次,改变设置的位数
             Single_LED_twinkle(led_pst);//换闪烁的led
             break;
      case 1:led_pst=2;
             Single_LED_twinkle(led_pst);
             break;
      case 2:led_pst=3;
             Single_LED_twinkle(led_pst);
             break;
      case 3:led_pst=0;//到最左边的led再按向左回到最右边的led0
             Single_LED_twinkle(led_pst);
             break;
     }break; 
 
   case 'r':switch(led_pst)
           {
      case 0:led_pst=3;//按一次向右键led向右移一次,改变设置的位数
             Single_LED_twinkle(led_pst);//换闪烁的led
             break;
      case 1:led_pst=0;
             Single_LED_twinkle(led_pst);
             break;
      case 2:led_pst=1;
             Single_LED_twinkle(led_pst);
             break;
      case 3:led_pst=2;//到最左边的led再按向左回到最右边的led0
             Single_LED_twinkle(led_pst);
             break;
     }break;

   case 'F':switch(led_pst)
           {
      case 0:Single_LED_twinkle(led_pst);//设置符号正负的键,对小数位、个位、十位不起作用
             break;
      case 1:Single_LED_twinkle(led_pst);
             break;
      case 2:Single_LED_twinkle(led_pst);
             break;
      case 3:if(lmt_low_tmp[3]==0) lmt_low_tmp[3]=1;

                                                                        //对符号位取反,如果以前是正,则按下后变为负
             else  lmt_low_tmp[3]=0;

             Single_LED_twinkle(led_pst);
             break;
     }break;

   case 'E':sys_state=0;//系统设置温度完成,回到正常测温时候
            if(lmt_low_tmp[3]==0)//最低温度是正温度时
      { 
        low_limitedTmp=(lmt_low_tmp[2]*100+lmt_low_tmp[1]*10+lmt_low_tmp[0])/10.0;

                                                                                                  //计算并确认设置后的最低温度
      }
      else   //最低温度是负温度时
      {
        low_limitedTmp=-(lmt_low_tmp[2]*100+lmt_low_tmp[1]*10+lmt_low_tmp[0])/10.0;
      }
      break;

   case 'L':Single_LED_twinkle(led_pst);//正在设置报警低温,不起作用,相应led闪烁
      break;

   case 'H':sys_state=2;//按“VH”,则转换为设置温度上限状态
            led_pst=0;

      lmt_high_tmp[3]=(high_limitedTmp>0?0:1);//提取分离极限最高温度的每一位数值
      lmt_high_tmp[2]=tmp[1]%100;
      lmt_high_tmp[1]=(tmp[1]-lmt_tmp[2]*100)%10;
      lmt_high_tmp[0]=tmp[1]-lmt_tmp[2]*100-lmt_tmp[1]*10;

      All_LED_twinkle(high_limitedTmp);//全部闪烁3次
      Single_LED_twinkle(led_pst);//再默认为最右边的led闪烁设置

      break;
    }
 }

 if(sys_state==2)//查状态为状态2:设置最高极限温度状态
 {
    switch(key_value)//查此时按下的键值
    {
      case 1:switch(led_pst)
          {
      case 0:lmt_high_tmp[0]=1;//小数位为1
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 1:lmt_high_tmp[1]=1;//个位为1
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 2:lmt_high_tmp[2]=1;//十位为1
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 3:Single_LED_twinkle(led_pst);//相应led闪烁
             break;//无效
    }break; 

   case 2:switch(led_pst)
          {
      case 0:lmt_high_tmp[0]=2;//小数位为2
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 1:lmt_high_tmp[1]=2;//个位为2
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 2:lmt_high_tmp[2]=2;//十位为2
             Single_LED_twinkle(led_pst);//相应led闪烁
             break;
      case 3:Single_LED_twinkle(led_pst);//相应led闪烁
             break;//无效
    }break; 
 
   case 3:switch(led_pst)
          {
      case 0:lmt_high_tmp[0]=3;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_high_tmp[1]=3;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_high_tmp[2]=3;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 
   case 4:switch(led_pst)
          {
      case 0:lmt_high_tmp[0]=4;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_high_tmp[1]=4;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_high_tmp[2]=4;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
  
   case 5:switch(led_pst)
          {
      case 0:lmt_high_tmp[0]=5;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_high_tmp[1]=5;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_high_tmp[2]=5;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 
   case 6:switch(led_pst)
          {
      case 0:lmt_high_tmp[0]=6;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_high_tmp[1]=6;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_high_tmp[2]=6;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 

   case 7:switch(led_pst)
          {
      case 0:lmt_high_tmp[0]=7;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_high_tmp[1]=7;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_high_tmp[2]=7;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 
   case 8:switch(led_pst)
          {
      case 0:lmt_high_tmp[0]=8;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_high_tmp[1]=8;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_high_tmp[2]=8;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 
   case 9:switch(led_pst)
          {
      case 0:lmt_high_tmp[0]=9;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_high_tmp[1]=9;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_high_tmp[2]=9;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 
   case 0:switch(led_pst)
          {
      case 0:lmt_high_tmp[0]=0;
             Single_LED_twinkle(led_pst);
             break;
      case 1:lmt_high_tmp[1]=0;
             Single_LED_twinkle(led_pst);
             break;
      case 2:lmt_high_tmp[2]=0;
             Single_LED_twinkle(led_pst);
             break;
      case 3:Single_LED_twinkle(led_pst);
             break;
    }break; 
 

   case 'l':switch(led_pst)
           {
      case 0:led_pst=1;//按一次向左键led向左移一次,改变设置的位数
             Single_LED_twinkle(led_pst);//换闪烁的led
             break;
      case 1:led_pst=2;
             Single_LED_twinkle(led_pst);
             break;
      case 2:led_pst=3;
             Single_LED_twinkle(led_pst);
             break;
      case 3:led_pst=0;//到最左边的led再按向左回到最右边的led0
             Single_LED_twinkle(led_pst);
             break;
     }break; 
 
   case 'r':switch(led_pst)
           {
      case 0:led_pst=3;//按一次向右键led向右移一次,改变设置的位数
             Single_LED_twinkle(led_pst);//换闪烁的led
             break;
      case 1:led_pst=0;
             Single_LED_twinkle(led_pst);
             break;
      case 2:led_pst=1;
             Single_LED_twinkle(led_pst);
             break;
      case 3:led_pst=2;//到最左边的led再按向左回到最右边的led0
             Single_LED_twinkle(led_pst);
             break;
     }break;

   case 'F':switch(led_pst)
           {
      case 0:Single_LED_twinkle(led_pst);//设置符号正负的键,对小数位、个位、十位不起作用
             break;
      case 1:Single_LED_twinkle(led_pst);
             break;
      case 2:Single_LED_twinkle(led_pst);
             break;
      case 3:if(lmt_high_tmp[3]==0) 
                lmt_high_tmp[3]=1;//对符号位取反,如果以前是正,则按下后变为负
             else  
          lmt_high_tmp[3]=0;

             Single_LED_twinkle(led_pst);
             break;
     }break;

   case 'E':sys_state=0;//系统设置温度完成,回到正常测温时候
            if(lmt_high_tmp[3]==0)//最低温度是正温度时
      { 
        high_limitedTmp=(lmt_high_tmp[2]*100+lmt_high_tmp[1]*10+lmt_high_tmp[0])/10.0;

                                                                                      //计算并确认设置后的最低温度
      }
      else   //最低温度是负温度时
      {
        high_limitedTmp=-(lmt_high_tmp[2]*100+lmt_high_tmp[1]*10+lmt_high_tmp[0])/10.0;
      }
      break;

   case 'L':sys_state=1;//按“VL”,则转换为设置温度下限状态
            led_pst=0;

      lmt_low_tmp[3]=(low_limitedTmp>0?0:1);//提取分离极限最低温度的每一位数值
      lmt_low_tmp[2]=tmp[0]%100;
      lmt_low_tmp[1]=(tmp[0]-lmt_tmp[2]*100)%10;
      lmt_low_tmp[0]=tmp[0]-lmt_tmp[2]*100-lmt_tmp[1]*10;

      All_LED_twinkle(low_limitedTmp);//全部闪烁3次
      Single_LED_twinkle(led_pst);//再默认为最右边的led闪烁设置

      break;

   case 'H':Single_LED_twinkle(led_pst);//正在设置报警高温,不起作用,相应led闪烁
      break;
    }
 }
}


/***********************************主程序***************************************/
void main()
{
   EA=1;//开cpu中断和INT0中断
   EX0=1;

   P1=0x01;//将键盘扫描口低4位写入全1,高四位写入全0

   sys_state=0;//初始化系统状态为测温状态0

   led0_off=1;//把led全部点亮
   led1_off=1;
   led2_off=1;

   low_limitedTmp=-40.0;//设置初始报警温度下限
   high_limitedTmp=50.0;//设置初始报警温度下限
   Final_tmpvalue=100;//设置初始10倍放大温度以便灭报警器和红灯
   Alarm_tmp(Final_tmpvalue);//初始化报警设备

   
   while(1)   //实时显示温度值
   {
       SendCommand_TmpConvert();//启动温度转换
    Display_TmpValue(Get_TmpValue());//显示温度值
    Alarm_tmp(Final_tmpvalue);//调用报警函数
   
   }
}


完整程序下载:http://www.51hei.com/ziliao/file/ds18.rar

关闭窗口

相关文章