找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1681|回复: 2
打印 上一主题 下一主题
收起左侧

求助,基于单片机的2个DS18B20测温LCD1602显示按键控制报警

[复制链接]
跳转到指定楼层
楼主
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P0^0;//ds18b20    与单片机连接口
sbit DQ2=P0^1;//ds18b20    与单片机连接口
//sbit DS=P2^0;
  sbit RS=P1^5;
  sbit RW=P1^6;
  sbit EN=P1^7;
  sbit KEY1=P2^0;
  sbit KEY2=P2^1;
  sbit KEY3=P2^2;
  sbit BEEP=P2^3;
  sbit Switch=P2^6;
  uchar code str[]={"Temperature 1:"};
  uchar code str1[]={"TH 1:           "};
  uchar code str2[]={"TL 1:           "};
  uchar code str3[]={"Temperature 2:"};
  uchar code str4[]={"TH 2:           "};
  uchar code str5[]={"TL 2:           "};
  uchar data disdata[5];
  uchar mode=0;
  char  mode2=0;
  char H_temp=35;
  char L_temp=1;
  char H_temp2=40;  
  char L_temp2=20;
  uint tvalue;//温度值
  uchar tflag;//温度正负标志
/*****************************lcd1602程序******************************/
void delay1ms(uint ms)//延时1毫秒(不够精确的)
{
    uchar i;
    uchar j;
    for(i=0;i<ms;i++)
    for(j=0;j<100;j++);
}
void wr_com(uchar com)//写指令//
{
    delay1ms(1);
    RS=0;
    RW=0;
    EN=0;
    P3=com;
    delay1ms(1);
    EN=1;
    delay1ms(1);
    EN=0;
}

void wr_dat(uchar dat)//写数据//
{
    delay1ms(1);
    RS=1;
    RW=0;
    EN=0;
    P3=dat;
    delay1ms(1);
    EN=1;
    delay1ms(1);
    EN=0;
}

void lcd_init()//初始化设置//
{
    delay1ms(15);
    wr_com(0x38);   //数据总线为8位,显示2行,5*7点阵/每字符
    delay1ms(5);
    wr_com(0x08);   //显示功能关,无光标,光标不闪烁
    delay1ms(5);
    wr_com(0x01);   //清屏
    delay1ms(5);
    wr_com(0x06);   //写入新数据后光标右移,写入新数据显示屏不移动
    delay1ms(5);
    wr_com(0x0c);   //显示功能开,无光标,光标不闪烁
    delay1ms(5);
}

void display(uchar*p)//显示
{
    while(*p!='\0')
      {
          wr_dat(*p);
          p++;
          delay1ms(1);
       }
}

void init_play(uchar st)//初始化显示
{

    wr_com(0x80);
    switch(st)
    {
     case 0:display(str);break;
     case 1:display(str1);break;
     case 2:display(str2);break;
     case 3:display(str3);break;
     case 4:display(str4);break;
     case 5:display(str5);break;
     }
}

/***********************ds1820程序******************************/
void delay_18B20(uint i)//延时1微秒
{
   while(i--);
}
void ds1820rst(bit flag)/*ds1820复位*/
{
    uchar x=0;
    if(flag==0)
    {
    DQ=1;     //DQ复位
    delay_18B20(4);     //延时
    DQ=0;     //DQ拉低
    delay_18B20(100);   //精确延时大于480us
    DQ=1;     //DQ拉高
    delay_18B20(40);
    }
    if(flag==1)
    {
    DQ2=1;     //DQ复位
    delay_18B20(4);     //延时
    DQ2=0;     //DQ拉低
    delay_18B20(100);   //精确延时大于480us
    DQ2=1;     //DQ拉高
    delay_18B20(40);
    }
}
/*******************************18B20读数据******************************/
uchar ds1820rd(bit flag)/*读数据*/
{
    uchar i=0;
    uchar dat=0;
    if(flag==00)
    {
      for(i=8;i>0;i--)
     {
         DQ=0;    //给脉冲信号
         dat>>=1;
         DQ=1;    //给脉冲信号
         if(DQ)
         dat|=0x80;
         delay_18B20(10);
      }
     }
     if(flag==1)
     {
      for(i=8;i>0;i--)
      {
         DQ2=0;    //给脉冲信号
         dat>>=1;
         DQ2=1;    //给脉冲信号
         if(DQ2)
         dat|=0x80;
         delay_18B20(10);
       }
      }
           return(dat);
}
/********************************18b20写数据***************************/

void ds1820wr(uchar wdata,bit flag)/*写数据*/
{
     uchar i=0;
     if(flag==0)
     {
      for(i=8;i>0;i--)
     {
         DQ=0;  
         DQ=wdata&0x01;
         delay_18B20(10);
         DQ=1;
         wdata>>=1;
      }
     }
         if(flag==1)
      {
       for(i=8;i>0;i--)
      {
         DQ2=0;  
         DQ2=wdata&0x01;
         delay_18B20(10);
         DQ2=1;
         wdata>>=1;
       }
      }
}
/*********************************读温度并转换**************************/

uint read_temp(bit flag)/*读取温度值并转换*/
{
    uchar a,b;
    ds1820rst(flag);
    ds1820wr(0xcc,flag);//*跳过读序列号,跳过读ROM (ccH)*/
    ds1820wr(0x44,flag);//*启动温度转换(44H)*/
    ds1820rst(flag);
    ds1820wr(0xcc,flag);//*跳过读序列号*/
    ds1820wr(0xbe,flag);//*读取温度*/
    a=ds1820rd(flag);
    b=ds1820rd(flag);
    tvalue=b;
    tvalue<<=8;
    tvalue=tvalue|a;
   if(tvalue<0x0fff)   //如果为正,最高五位皆为0,只有后十一位可能为1,肯定会小于0x0fff;若为负,最高5位皆为1,必定大于0x0fff
      tflag=0;
   else                //即使测得温度为负,tvalue也为正值,但符号位为1.
     {
        tvalue=~tvalue+1;
        tflag=1;
      }
        tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数;此处所乘本该为0.0625
        return(tvalue);
  }
/****************************显示温度**********************************/

void ds1820disp()//温度值在LCD显示
{
    uchar flagdat;
    disdata[0]=tvalue/1000+0x30;
    disdata[1]=tvalue%1000/100+0x30;//十位数
    disdata[2]=tvalue%100/10+0x30;//个位数
    disdata[3]=tvalue%10+0x30;//小数位
    if(tflag==0)
        flagdat=0x20;    /*正温度不显示符号,0x20对应为空白,可以从1602字符代码表中查找相关字符所对应的数值*/
      else
        flagdat=0x2d;    //负温度显示负号:-
      if(disdata[0]==0x30)
      {
        disdata[0]=0x20;//如果百位为0,不显示
        if(disdata[1]==0x30)
        {
        disdata[0]=0x20;//如果百位为0,十位为0也不显示
       }
      }
          wr_com(0xc0);    //设置下一个要存入数据的CGRAM的地址,即40H单元(40H+80H=C0H),即第二行第一个字节(每行可以显示16个字符,可以显示两行,即1602
          wr_dat(flagdat);//显示符号位
          wr_com(0xc1);    //下一个数据显示在第二行第二个字节
          wr_dat(disdata[0]);//显示百位
          wr_com(0xc2);    //下一个数据显示在第二行第三个字节
          wr_dat(disdata[1]);//显示十位
          wr_com(0xc3);    //下一个数据显示在第二行第四个字节
          wr_dat(disdata[2]);//显示个位
          wr_com(0xc4);    //下一个数据显示在第二行第五个字节
          wr_dat(0x2e);//显示小数点
          wr_com(0xc5);    //下一个数据显示在第二行第六个字节
          wr_dat(disdata[3]);//显示小数位
          wr_com(0xc6);   
          wr_dat(0xdf);
          wr_com(0xc7);   
          wr_dat(0x43);
    }
/****************************************扫描按键*********************************/
uchar key_scan()
{
    uchar key_back;
     key_back=0;
       if(!KEY1|!KEY2|!KEY3)
        {
            delay1ms(5);
            if(!KEY1|!KEY2|!KEY3)
            {
             if(!KEY1)
                 key_back=1;
             else if(!KEY2)
                 key_back=2;
             else if(!KEY3)
                 key_back=3;
             while(!KEY1|!KEY2|!KEY3);//等待按键释放
             }
         }
         return key_back;
}     
/********************************************函数功能:按键处理***************************/

void key_action(uchar key_back)
{
   if(Switch==0)
{
   if(key_back==1)  
     {mode++;
      if(mode>2)
      mode=0;
      }
      else if(key_back==2)
      {if(mode==1)
         { H_temp++;
            if(H_temp>125)
            H_temp=125;
          }
          else if(mode==2)
          {L_temp++;
              if(L_temp>125)
           L_temp=125;
           }
        }
       else if(key_back==3)
       {if(mode==1)
          {H_temp--;
           if(H_temp<-50)
           H_temp=-50;
           }
           else if(mode==2)
           {L_temp--;
             if(L_temp<-50)
                  L_temp=-50;
            }
          }
      }
      if(Switch==1)
      {
       if(key_back==1)
      { mode2++;
         if(mode2>2)
      mode2=0;
      }
      else if(key_back==2)
      {if(mode2==1)
         { H_temp2++;
          if(H_temp2>125)
            H_temp2=125;
          }
          else if(mode2==2)
          {L_temp++;
              if(L_temp2>125)
           L_temp2=125;
           }
        }
       else if(key_back==3)
       {if(mode2==1)
          {H_temp2--;
           if(H_temp2<-50)
           H_temp2=-50;
           }
           else if(mode2==2)
           {L_temp2--;
             if(L_temp2<-50)
                  L_temp2=-50;
        }
       }
   }
}

/*************************************显示数据处理***************************************/
void dispaly_transaction()
{
    if(Switch==0)/*如果拨动开关关闭,则调整显示传感器1相关数据*/
     {
       if(mode==0)//模式0,正常 显示传感器测得温度
        {
          init_play(0);
          read_temp(0);//读取温度
          ds1820disp();//显示
         }
         if(mode==1)     //模式1,显示高温限值TH1
         {
           init_play(1);
           tvalue=H_temp*10;
           if(H_temp<0)
               tflag=1;
           else
               tflag=0;
           ds1820disp();//显示
          }
          if(mode==2)    //模式2,显示低温限值TH1
          {
            init_play(2);
            tvalue=L_temp*10;
            if(L_temp<0)
                tflag=1;
            else
                tflag=0;
            ds1820disp();//显示
           }
          }
          else          /*拨动开关开,则显示温度传感器2相关数据*/
          {
           if(mode==0)   //模式0,正常显示传感器测得温度
           {
            init_play(3);
            read_temp(1);//读取温度
            ds1820disp();//显示
            }
            if(mode2==1)//模式1,显示高温限值TH1
            {
             init_play(4);
             tvalue=H_temp2*10;
             if(H_temp<0)
                tflag=1;
             else
                tflag=0;
             ds1820disp();//显示
             }
             if(mode2==2)//模式2,显示低温限值TH1
             {
             init_play(5);
             tvalue=L_temp2*10;
             if(L_temp<0)
                 tflag=1;
             else
                  tflag=0;
            ds1820disp();//显示
            }
         }
}
/**************************************蜂鸣器程序*****************************************/

void beep(void)   //500Hz频率声音 T=2ms  方波信号
{
     int i;
     for(i=0;i<100;i++)
       {
         BEEP=0;
         delay1ms(4);
         BEEP=1;
         delay1ms(4);
        }
}
/**************************************函数功能:检查报警**************************************/
void check_alarm(void)
{
              //判断传感器1是否报警
    read_temp(0);//读取温度
    if(tflag==0)
    {
      if(((tvalue/10.0)>=H_temp)||((tvalue/10.0)<=L_temp))
       {
          delay1ms(10);
          read_temp(0);
          if(tflag==0)
            {
              if(((tvalue/10.0)>=H_temp)||((tvalue/10.0)<=L_temp))
                    beep();
             }
         }
      }
      if(tflag==1)
      {
      tvalue=-tvalue;
      if(((tvalue/10.0)>=H_temp)||((tvalue/10.0)<=L_temp))
        {
          delay1ms(10);
          read_temp(0);
          if(tflag==1)
         {
           tvalue=-tvalue;
           if(((tvalue/10.0)>=H_temp)||((tvalue/10.0)<=L_temp))
                beep();
          }
       }
     }
              //判断传感器2是否报警
    read_temp(1);//读取温度
    if(tflag==0)
    {
      if(((tvalue/10.0)>=H_temp2)||((tvalue/10.0)<=L_temp2))
       {
          delay1ms(10);
          read_temp(1);
          if(tflag==0)
            {
              if(((tvalue/10.0)>=H_temp2)||((tvalue/10.0)<=L_temp2))
                 {  
                  beep();
                  }
              }
         }
     }
     if(tflag==1)
     {
      tvalue=-tvalue;
      if(((tvalue/10.0)>=H_temp2)||((tvalue/10.0)<=L_temp2))
        {
          delay1ms(10);
          read_temp(1);
          if(tflag==1)
         {
           tvalue=-tvalue;
           if(((tvalue/10.0)>=H_temp2)||((tvalue/10.0)<=L_temp2))
             {
                  beep();
          }
         }
       }
     }
}

/*****************************************主程序**********************************************/
void main()
  {
     uchar Key_Back;
     BEEP=0;
     lcd_init();
     while(1)
       {
          Key_Back=key_scan();

          if(Key_Back)
          key_action(Key_Back);

          display_transcation();
          check_alarm();
        }
    }
这是程序,帮忙修改一下

仿真图.PNG (40.79 KB, 下载次数: 28)

仿真图

仿真图
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:494382 发表于 2019-4-24 16:55 | 只看该作者
如果是两个DS18B20只占用一个IO口 怎么写程序呢 在1602上显示两个温度
回复

使用道具 举报

板凳
ID:518089 发表于 2019-5-4 21:41 | 只看该作者
楼主解决了吗,我正在做这个,想请教一下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表