找回密码
 立即注册

QQ登录

只需一步,快速开始

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

智能数字温度计

  [复制链接]
跳转到指定楼层
楼主
ID:103224 发表于 2016-1-15 10:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include<reg52.h>
#include <intrins.h>
#include<math.h>
#define uint unsigned int
#define uchar unsigned char
#define LCD P0

sbit redLED=P2^7;//位定义报警显示灯
sbit xuanze=P3^3;//位定义选择按键
sbit up=P3^4;//位定义极限加
sbit down=P3^5;//位定义极限减

int th=20,tl=5,thh=0,tll=0;//初始上限值和下限值
uchar i,num=0;//定义变量
/*******************************************************
            延时函数
*******************************************************/
void delay(uint z)
{
  uint x,y;
    for (x=z;x>0;x--)
     for(y=110;y>0;y--);

}

/*************************************************
             LCD部分
***************************************************/
sbit rs=P2^0;
sbit rw=P2^1;
sbit E=P2^2;
uchar tmp5[]="temp:";
uchar tmp6[]="^C";
uchar code tab1[]="TH:";
uchar code tab2[]="TL:";
write_com(uchar com)//LCD写地址函数
{
  rs=0;
  rw=0;
  E=1;
  LCD=com;
  delay(5);
  E=0;
  return 0;  
}
write_data(uchar dat)//LCD写数据函数
{
  rs=1;
  rw=0;
  E=1;
  LCD=dat;
  delay(5);  
  E=0;
  return 0;
}
init_lcd()//LCD初始化函数
{

  write_com(0x38);//16*2显示,5*7点阵,8位数据
  write_com(0x0c);//设置为显示开,关光标,不闪烁
  write_com(0x06);//写操作后,AC自动加1
  write_com(0x01); //LCD清屏



   write_com(0x80+0x01);//LCD第一行第二个位置起显示"TH:"
   for(i=0;i<3;i++)
   {  
    write_data(tab1[i]);
       
   }

   write_com(0x80+9);//LCD第一行第10个位置起显示"TL:"
   for(i=0;i<3;i++)
   {
    write_data(tab2[i]);
   }

   write_com(0x80+0X40+0x00);//LCD第二行开始出显示"Temp:"
   for(i=0;i<5;i++)
   {

     write_data(tmp5[i]);
   }

write_com(0x80+0X40+10);//显示温度的单位
   for(i=0;i<2;i++)
   {

     write_data(tmp6[i]);
   }

//以下是温度的上限和下限初始化显示部分
                 write_com(0x80+0x00+4);
           write_data('+');
                 write_data(th/10+0x30);
              write_data(th%10+0x30);
               write_com(0x80+0x00+12);
                 write_data('+');
                   write_data(tl/10+0x30);
                     write_data(tl%10+0x30);
                                         return 0;
}
/*********************************************************
               DS18B20部分
**********************************************************/
uchar timecount;//定义中断次数
uchar test0,test1,test;//温度值变量
uchar a1,a2,a3;//温度整数部分的十位,个位和小数部分的十分位
uchar readdate[2];//定义数组,用来暂存读取的温度值
sbit DQ=P3^0;//DS18B20数据口
bit sflag;//定义温度的正负标志位
void delay1(uint i)//短延时函数
{
while(i--);
}
void reset()//DS18B20的复位函数
{
uchar x=0;
DQ=1;//使总线为高电平
delay1(8);//延时
DQ=0;//使总线为低电平
delay1(80);//延时,大于480us
DQ=1;//使总线为高电平
delay1(14);//延时,等待DS18B20回应低电平
x=DQ;//将DS18B20的回应读到变量x,用于判断复位是否成功
delay1(20);//延时一段时间结束
}


void writecmd(uchar cmd)//DS18B20的写字节函数
{
uchar i=0;//定义位循环变量
for(i=8;i>0;i--)//循环8次
{
  DQ=0;//总线拉低
  DQ=cmd&0x01;//将发送字节的最低位送到总线
  delay1(5);//延时(30us),等待DS18B20取走总线数据
  DQ=1;//总线拉高
  cmd>>=1;//将待发送的字节右移后,继续发送
}
}

uchar readdat()//DS18B20的读字节函数
{
uchar i=0;//定义位循环变量
uchar temp=0;//定义暂存变量
for(i=8;i>0;i--)//循环8次
{
   DQ=0;//总线为低电平
   temp>>=1;//暂存变量右移
   DQ=1;//总线拉高,执行如下的读操作
   if(DQ)//如果DS18B20输出高电平
   temp|=0x80;//将暂存变量的最高位置1
   delay1(4);//延时一段时间
}
return temp;//程序结束后,将暂存变量返回调用程序
}

/***************************************************
         按键设置上线温度和下限温度值函数

****************************************************/
void key()
{
if(xuanze==0)//如果选择键按下
{delay(10);//延时消抖
if(xuanze==0)//如果按键还处于按下状态
{   num++;//次数加1
  while(!xuanze);//等待按键抬起


        if(num==1)//如果按下选择键的次数为1
         {
          TR0=0;//关闭中断
          write_com(0x80+0x00+5);//光标移到第一行第七个位置
      write_com(0x0f);//设置为显示开,开光标,闪烁
     }
    if(num==2)//如果按下选择键的次数为2
         {
         write_com(0x80+0x00+13);//光标移到第一行第十五个位置
         }
    if(num==3)//如果按下选择键的次数为3
        {
         num=0;//次数清零
         write_com(0x0c);//设置为显示开,关光标,不闪烁
         TR0=1;//开中断
        }
  }  
}
if(num!=0)//在选择键按下时
{
  if(up==0)//如果极限加按键按下
{
  delay(10);//延时消抖
  if(up==0)//如果极限加按键仍处于按下状态
  {
    while(!up);//等待按键抬起

   if(num==1)//如果选择键按了一次
   {
      th++;//上线值加1
            if(th>=0)//如果上线值为正
                {thh=0;//计数清零
                 write_com(0x80+0x00+4);
                  write_data('+');//显示正号
               write_com(0x80+0x00+5);
                    write_data(th/10+0x30);//显示上限温度值的十位
                 write_data(th%10+0x30);//显示上限温度值的个位
              }

                        if(th<0)
                         {
                           thh--;
                            write_com(0x80+0x00+4);
                                 write_data('-');//显示正号
                              write_com(0x80+0x00+5);
                                   write_data(thh/10+0x30);//显示上限温度值的十位
                                write_data(thh%10+0x30);//显示上限温度值的个位
                                 }
     }

if(num==2)//如果选择键按了两次
  {
        tl++;//下限温度值加1
        if(tl>=0)//如果下限温度值为正
        {
      tll=0;//计数清零
           write_com(0x80+0x00+12); // 显示正号
            write_data('+');//
             write_com(0x80+0x00+13);
              write_data(tl/10+0x30);//显示下限温度值的十位
               write_data(tl%10+0x30);//显示下限温度值的个位
            }
               
                if(tl<0)
                {
                   tll--;
                    write_com(0x80+0x00+12);
                         write_data('-');//显示正号
                      write_com(0x80+0x00+13);
                           write_data(tll/10+0x30);//显示上限温度值的十位
                        write_data(tll%10+0x30);//显示上限温度值的个位
                   }
      }
   }
  }


if(down==0)//如果极限减按键按下
{
  delay(10);//延时消抖
  if(down==0)//如果按键仍处于按下状态
{while(!down);//等待按键抬起
  if(num==1)//如果选择键按了一次
  {
          th--;//上限温度值减1
           if(th>=0)//如果上限温度值为正
                {
                 write_com(0x80+0x00+4);  //显示正号
                write_data('+');
                write_com(0x80+0x00+5);
                write_data(th/10+0x30);//显示上限温度值的十位
                write_data(th%10+0x30);//显示上限温度值的个位
                }
                if(th<0)//如果上限温度值为负
                {thh++;//计数变量加1
                 write_com(0x80+0x00+4);  
                write_data('-');//显示负号
               
                write_com(0x80+0x00+5);
                write_data(thh/10+0x30);//显示上限温度值的十位
                write_data(thh%10+0x30);//显示上限温度值的个位

         }

                }
        }
                       
        if(num==2)//如果选择键按了两次
        {
        tl--;//下限温度值减1
             if(tl>=0)//如果下限温度值为正
                {
                 write_com(0x80+0x00+12);  
                 write_data('+');//显示正号

                 write_com(0x80+0x00+13);
             write_data(tl/10+0x30);//显示下限温度值的十位
         write_data(tl%10+0x30);//显示下限温度值的个位
                }
                if(tl<0)//如果下限温度值为负
                {tll++;//计数变量加1
                 write_com(0x80+0x00+12);  
                write_data('-');//显示负号
                write_com(0x80+0x00+13);   
                write_data(tll/10+0x30);//显示下限温度值的十位
                 write_data(tll%10+0x30);//显示下限温度值的个位
                }
     }

   }
}
}
/******************************************************
                报警函数
********************************************************/
sbit ddd=P1^0;
void baojing()
{
   if((sflag==0&(test>=th|test<=tl))|(sflag==1&-test<=tl))//如果测得的温度值>=上限温度值(TH)或<=下限温度值(TL)
    {
     redLED=~redLED;//发光二极管闪烁
     delay(300);//延时
      }
else
{
  redLED=1;//否则发光二极管灭
}

}
/********************************************************
               主函数

********************************************************/
void main()
{
  init_lcd();//初始化LCD

  TMOD=0X01;//定时器0,方式1
  TH0=0X3C;//50ms溢出一次
  TL0=0XB0;
  TR0=1;//启动定时器0
  ET0=1;//开定时器0
  EA=1;//开总中断

  while(1)
   {
    key();//调用按键函数


    baojing();//调用报警函数

    }       
}

/************************************************************
          中断函数
**************************************************************/
void timer0()   interrupt 1//定时器0中断,中断标号为1
{  
uint result;//
TH0=0X3C;
TL0=0XB0;
timecount++;//每中断一次,timecount加1

if(timecount==20)//中断定时达到1S,50ms*20=1s
{timecount=0;//timecount清零
  reset();//复位DS18B20
  writecmd(0xcc);//向DS18B20发送跳过ROM搜索命令
  writecmd(0x44);//启动一次温度转换
  reset();//复位DS18B20
  writecmd(0xcc);//向DS18B20发送跳过ROM搜索命令
  writecmd(0xbe);//发送读温度的命令?
  readdate[0]=readdat();//读温度的低8位
  readdate[1]=readdat();//读温度的高8位

  sflag=0;//置负号标志为0
  if(( readdate[1]&0xf8)!=0x00)//如果是负温度值,执行如下取补码语句
{ sflag=1;
   readdate[1]=~ readdate[1];//高位取反码
   readdate[0]=~readdate[0];//低位取反码
   result=readdate[0]+1;//反码加1
   readdate[0]=result;//将取补的高温度值,送回数组
   if(result>255)//如果低8位有进位,则高8位加1
  {readdate[1]++;//
  }
}
test0=readdate[0];//低8位值赋予test0
test1=readdate[1];//高8位值赋予test1
test=((readdate[1]*256)+readdate[0])/16;//取出整数部分温度值
test0=(test0|0x0f)/16;//取出小数部分温度值

reset();//复位DS18B20
writecmd(0xcc);//向DS18B20发送跳过ROM搜索命令
writecmd(0x44);//启动下次温度测量
//以下是温度值处理部分
write_com(0x80+0X40+0x05);

   if(sflag==1)
       write_data('-');//如果测得的温度为负值,显示负号
   else
        write_data('+');//如果测得的温度为正值,显示正号

       a1=(test/10)|0x30;//温度整数部分的十位
       a2=(test%10)|0x30;//温度整数部分的个位

   write_com(0x80+0X40+0x06);
   write_data(a1);//显示温度整数部分的十位
   write_data(a2);//显示温度整数部分的个位
   write_data('.');//显示小数点
   a3=(test0/10)|0x30;//温度小数部分的十分位
   write_data(a3);  //  显示温度小数部分的十分位
}
ddd=sflag;
}


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

使用道具 举报

沙发
ID:103332 发表于 2016-1-15 14:00 | 只看该作者
很不错、、、、、、、、、
回复

使用道具 举报

板凳
ID:103520 发表于 2016-1-27 17:44 | 只看该作者
感谢楼主
回复

使用道具 举报

地板
ID:47652 发表于 2016-4-21 10:19 | 只看该作者
下载看看,谢谢分享
回复

使用道具 举报

5#
ID:152224 发表于 2016-12-8 22:22 | 只看该作者
非常好,下次还会来的
回复

使用道具 举报

6#
ID:209492 发表于 2017-6-10 09:13 | 只看该作者
有没proteus的仿真图啊?
回复

使用道具 举报

7#
ID:89286 发表于 2017-6-10 09:29 | 只看该作者
thanks for sharing
回复

使用道具 举报

8#
ID:96218 发表于 2017-10-29 22:11 | 只看该作者
没有电路图,有点费劲
回复

使用道具 举报

9#
ID:243091 发表于 2017-10-30 17:41 | 只看该作者
还有为了刷东西评论的?
回复

使用道具 举报

10#
ID:124729 发表于 2017-10-30 17:48 | 只看该作者
学习学习
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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