找回密码
 立即注册

QQ登录

只需一步,快速开始

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

用DS18B20采集温度和用单片机T0端口作时钟,并在LCD1602上显示

[复制链接]
跳转到指定楼层
楼主
自己做的,有不足的地方请指出,一起学习进步!
这个设计由单片机最小系统、温度传感模块 (DS18B20)、显示模块(LCD1602)、按键模块和声光报警模块组成。
功能:①显示 时—分—秒和实时温度;②可以通过按键调整显示时间,还可以调整声光报警(7秒后自动关闭)的时间,并且还可以手动关闭声光报警

电路图和系统各框图:



单片机程序:
  1. #include <reg51.h>
  2. #include <intrins.h>                           //包含_nop_空函数指令的头文件
  3. #include <stdio.h>
  4. #define uchar unsigned char
  5. #define uint unsigned int
  6. #define out P0
  7. uchar date[20];                           //存放温度值
  8. sbit RS=P3^5;                          // 寄存器选择(1——数据寄存器;0——命令/状态寄存器)
  9. sbit RW=P3^6;                          // 读/写操作选择(1——读;0——写)
  10. sbit E=P3^4;                          // 使能信号

  11. sbit voise=P2^3;            //蜂鸣器链接口
  12. sbit beeled=P1^7;                //LED灯接口

  13. sbit CON  = P3^0;
  14. sbit UP   = P3^1;
  15. sbit DOWN = P3^2;
  16. sbit START= P3^3;

  17. sbit ds = P2^2;                         //温度传感器的输入/输出引脚

  18. void keyScan();         //按键调时间
  19. void keyclockdown();        //按下按键关闭闹钟

  20. void init();                    //定时器T0的初始化
  21. void TIME();                        //实现时间变化

  22. void lcd_initial();     //lcd1602初始化
  23. void check_busy();      //检查忙碌标志位
  24. void write_command(uchar com);   //写命令
  25. void wtite_data(uchar  dat);         //写数据
  26. void string(uchar ad,uchar *s);         //显示字符串
  27. uchar dis[ ]={0x30,0x38,0x2d,0x35,0x39,0x2d,0x35,0x37,'\0'};                //dis[]={0,8,-,5,9,-,5,7}

  28. void delayMs(uint a);
  29. void delay(uint);

  30. void bee();                         //蜂鸣器
  31. uchar flag;

  32. uchar num;
  33. uchar over=0;
  34. void aoto();                         //7s后自动关闭闹铃

  35. uchar a=0x30,b=0x38,c=0x30,d=0x30,e=0x30,f=0x30;

  36. void dsInit();                                             //DS18B20复位,初始化函数
  37. void dsWait();
  38. bit readBit();                                             //读一位数据函数
  39. unsigned char readByte();                         //读一个字节数据函数
  40. void writeByte(unsigned char dat);             //向DS18B20写一个字节数据函数
  41. void sendChangeCmd();                                         //DS18B20开始获取温度并转换
  42. void sendReadCmd();                                                 //读取寄存器中存储的温度数据
  43. int getTmpValue();                                                 //得到温度

  44. //*************************************************************
  45. void main()
  46. {
  47.         float temp=0.0;
  48.         lcd_initial ();                                          //液晶显示初始化
  49.         init();                                                           //定时器的初始化
  50.         while(1)
  51.         {
  52.                         bee();
  53.                         keyScan();                                  //按键调时间
  54.                         keyclockdown();                          //按下按键关闭闹钟
  55.                         aoto();
  56.                         delay(200);
  57.                         string(0x80,"TIME:");
  58.                         delay(200);
  59.                         string(0xcb,"^C");
  60.                         string(0x86,dis);
  61.                         delay(200);
  62.                         temp=getTmpValue()/100.0;
  63.                         sendChangeCmd();
  64.                         sprintf(date,"TEMP: %0.2f",temp);
  65.                         string(0xc0,date);
  66.                         delay(200);
  67.         }


  68. }
  69. //**************************************************************
  70. //延迟函数
  71. void delayMs(uint a)
  72. {
  73.     uint i, j;
  74.     for(i = a; i > 0; i--)
  75.         for(j = 100; j > 0; j--);
  76. }

  77. void delay (uint j)                         //延迟
  78. {
  79.         uchar i=10;
  80.         for(;j>0;j--)
  81.         {
  82.                 while(--i);
  83.                 i=10;
  84.                 while(--i);
  85.                 i=10;
  86.         
  87.         }
  88. }

  89. //********************************************************
  90. void init()                                          //定时器的初始化
  91. {
  92.         TMOD=0x01;                                  //定时器T0的方式1
  93.         TH0=(65536-50000)/256;          //50ms
  94.         TL0=(65536-50000)%256;
  95.         EA=1;                                          //总中断允许
  96.         ET0=1;                                          //启动定时器T0中断
  97.         TR0=1;                                          //启动定时器T0
  98. }

  99. void timer0() interrupt 1           //T0中断程序
  100. {
  101.         TH0=(65536-50000)/256;          //50ms
  102.         TL0=(65536-50000)%256;
  103.         num++ ;
  104.         TIME();                                          //实现时间变化
  105. }

  106. //***********************************************************
  107. void lcd_initial ()                        //液晶显示初始化
  108. {
  109.         write_command(0x38);        //写入命令0x38;8位2行显示,5×7点阵字符
  110.         _nop_();
  111.         write_command(0x0c);            //写入命令0x0c;整体显示,光标关闭,无闪烁
  112.          _nop_();
  113.         write_command(0x06);                //写入命令0x05;光标右移
  114.         _nop_();
  115.         write_command(0x01);                //写入命令0x01;清屏
  116.         delay(1);
  117. }

  118. void check_busy ()                //检查忙标志
  119. {                                                
  120.         uchar dt;                        //dt变量单元 ,忙状态标志 0:不忙,0x80:忙
  121.         do
  122.         {
  123.                 dt=0xff;                  // 先往数据端口赋高电平,便于读数据
  124.                 E=0;
  125.                 RS=0;
  126.                 RW=1;          //读
  127.                 E=1;           // 数据端口读写使能
  128.                 dt=out;           // 读数据端口的值
  129.         }while(dt&0x80);         // 如果忙位BF为1,就一直读端口数据,直到为0才退出忙判断。
  130.                                                   // BF:忙标志位,为数据端口的BIT7位。所以为0x80。
  131.         E=0;
  132. }

  133. void write_command (uchar com)           //写命令
  134. {
  135.         check_busy();
  136.         E=0;                                                   //RS=E=0;才可以写入命令
  137.         RS=0;
  138.         RW=0;
  139.         out=com;
  140.         E=1;
  141.         _nop_();        //空操作1个机械周期
  142.         E=0;
  143.         delay(1);
  144. }

  145. void write_data (uchar dat)                //写数据
  146. {
  147.         check_busy();                                //检测忙标志位BF=1则等待,BF=0则可对LCD写入
  148.         E=0;                                                //写数据时,E为正脉冲,所以E置0
  149.         RS=1;                                                //RS=1,RW=1时,才可以写入数据
  150.         RW=0;
  151.         out=dat;                                        //将数据dat从P0口输出,即写入LCD
  152.         E=1;                                            //E产生正跳变
  153.         _nop_();                                        //空操作1个机械周期
  154.         E=0;                                                //E由高电平变低电平,写操作结束
  155.         delay(1);
  156. }

  157. void string(uchar ad,uchar *s)
  158. {
  159.         write_command(ad);
  160.         while(*s>0)
  161.         {
  162.                 write_data(*s++);           //输出字符传,指针加1
  163.                 delay(1);
  164.         }
  165. }

  166. //*****************************************************
  167. void TIME()                                     //实现时分秒变化
  168. {
  169.         if(num==20)
  170.                 {
  171.                         num=0;
  172.                         over++;
  173.                         dis[7]++;
  174.                         if(dis[7]>0x39)                  //秒
  175.                         {
  176.                                 dis[7]=0x30;
  177.                                 dis[6]++;
  178.                          }
  179.                         if(dis[6]==0x36)         
  180.                         {
  181.                                 dis[6]=0x30;
  182.                                 dis[4]++;
  183.                         }
  184.                         if(dis[4]>0x39)                   //分
  185.                         {
  186.                                 dis[4]=0x30;
  187.                                 dis[3]++;
  188.                                 }
  189.                         if(dis[3]==0x36)
  190.                         {
  191.                                 dis[3]=0x30;
  192.                                 dis[1]++;
  193.                          }
  194.                         if(dis[1]>0x39)                //时
  195.                         {
  196.                                 dis[1]=0x30;
  197.                                 dis[0]++;
  198.                          }
  199.                         if(dis[0]==0x32)
  200.                         {
  201.                                 if(dis[1]>0x33)
  202.                                 {
  203.                                         dis[0]=0x30;
  204.                                         dis[1]=0x30;
  205.                                 }        
  206.                         }
  207.         }
  208. }

  209. //*******************************************************
  210. //扫描键盘程序
  211. void keyScan()
  212. {
  213.         static uchar key;
  214.         if(!CON){ while(!CON);key++;}
  215.         if(key)
  216.         {
  217.                 TR0=0;          //时间先停下,再调整
  218.                 P1=~(key%7);    //指示灯
  219.                 switch(key%7)
  220.                 {
  221.                         case 6:        if(!UP)                                                                  //秒的个位
  222.                                         {
  223.                                                 while(!UP);        
  224.                                                 dis[7]++;
  225.                                                 if(dis[7]>0x39) dis[7]=0x30;
  226.                                         }
  227.                                         if(!DOWN)
  228.                                         {
  229.                                                 while(!DOWN);
  230.                                                 dis[7]--;
  231.                                                 if(dis[7]<0x30) dis[7]=0x39;
  232.                                         }  
  233.                                         break;           
  234.                         case 5:        if(!UP)                                                                           //秒的十位
  235.                                         {
  236.                                                 while(!UP);        
  237.                                                 dis[6]++;
  238.                                                 if(dis[6]>0x35) dis[6]=0x30;
  239.                                         }
  240.                                         if(!DOWN)
  241.                                         {
  242.                                                 while(!DOWN);
  243.                                                 dis[6]--;
  244.                                                 if(dis[6]<0x30) dis[6]=0x35;
  245.                                         }           
  246.                                         break;
  247.                         case 4:        if(!UP)                                                                           //分的个位
  248.                                         {
  249.                                                 while(!UP);        
  250.                                                 dis[4]++;
  251.                                                 if(dis[4]>0x39) dis[4]=0x30;
  252.                                         }
  253.                                         if(!DOWN)
  254.                                         {
  255.                                                 while(!DOWN);
  256.                                                 dis[4]--;
  257.                                                 if(dis[4]<0x30) dis[4]=0x39;
  258.                                         }           
  259.                                         break;
  260.                         case 3:        if(!UP)                                                                                //分的十位
  261.                                         {
  262.                                                 while(!UP);        
  263.                                                 dis[3]++;
  264.                                                 if(dis[3]>0x35) dis[3]=0x30;
  265.                                         }
  266.                                         if(!DOWN)
  267.                                         {
  268.                                                 while(!DOWN);
  269.                                                 dis[3]--;
  270.                                                 if(dis[3]<0x30) dis[3]=0x35;
  271.                                                 }           
  272.                                                 break;        
  273.                         case 2:        if(!UP)                                                                          // 时的个位
  274.                                         {
  275.                                                 while(!UP);        
  276.                                                 dis[1]++;
  277.                                                 if(dis[0]==0x30||dis[0]==0x31)
  278.                                                 {
  279.                                                         if(dis[1]>0x39) dis[1]=0x30;
  280.                                                 }
  281.                                                 if(dis[0]==0x32)
  282.                                                 {
  283.                                                         if(dis[1]>0x33)         dis[1]=0x30;
  284.                                                 }
  285.                                         }
  286.                                         if(!DOWN)
  287.                                         {
  288.                                                 while(!DOWN);
  289.                                                 dis[1]--;
  290.                                                 if(dis[0]==0x30||dis[0]==0x31)
  291.                                                 {
  292.                                                         if(dis[1]<0x30) dis[1]=0x39;
  293.                                                 }
  294.                                                 if(dis[0]==0x32)
  295.                                                 {
  296.                                                         if(dis[1]<0x30)         dis[1]=0x33;
  297.                                                 }

  298.                                         }           
  299.                                                 break;
  300.                         case 1:        if(!UP)                                                                        //时的十位
  301.                                                 {
  302.                                                         while(!UP);        
  303.                                                         dis[0]++;
  304.                                                         if(dis[0]>0x32) dis[0]=0x30;
  305.                                                 }
  306.                                                 if(!DOWN)
  307.                                                 {
  308.                                                         while(!DOWN);
  309.                                                         dis[0]--;
  310.                                                         if(dis[0]<0x30) dis[0]=0x32;
  311.                                                 }           
  312.                                                 break;        
  313.                 }               
  314.         }
  315.         if(!START)
  316.         {
  317.                 while(!START);
  318.                 TR0=1;
  319.                 key=0;
  320.                 P0=0xff;
  321.         }
  322. }

  323. //*******************************************************************************蜂鸣器
  324. void bee()
  325. {
  326.         keyclockdown();
  327.         if(dis[0]==a&&dis[1]==0x38&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)          //8点
  328.         {
  329.                 flag=1;
  330.         }
  331.         if(dis[0]==a&&dis[1]==0x39&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)          //9点
  332.         {
  333.                 flag=1;
  334.         }
  335.         if(dis[0]==0x31&&dis[1]==0x30&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)          //10点
  336.         {
  337.                 flag=1;
  338.         }
  339.         if(dis[0]==0x31&&dis[1]==0x31&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)          // 11点
  340.         {
  341.                 flag=1;
  342.         }
  343.         if(dis[0]==0x31&&dis[1]==0x32&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)           // 12点
  344.         {
  345.                 flag=1;
  346.         }
  347.         if(dis[0]==0x31&&dis[1]==0x33&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)                //13点
  348.         {
  349.                 flag=1;
  350.         }
  351.         if(dis[0]==0x31&&dis[1]==0x34&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)                 //14点
  352.         {
  353.                 flag=1;
  354.         }
  355.         if(dis[0]==0x31&&dis[1]==0x35&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)                 //15点
  356.         {
  357.                 flag=1;
  358.         }if(dis[0]==0x31&&dis[1]==0x36&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)                //16点
  359.         {
  360.                 flag=1;
  361.         }if(dis[0]==0x31&&dis[1]==0x37&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)                 //17点
  362.         {
  363.                 flag=1;
  364.         }
  365.         if(dis[0]==0x31&&dis[1]==0x38&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)                 //18点
  366.         {
  367.                 flag=1;
  368.         }
  369.         if(dis[0]==0x31&&dis[1]==0x39&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)                 //19点
  370.         {
  371.                 flag=1;
  372.         }
  373.         if(dis[0]==0x32&&dis[1]==0x30&&dis[3]==c&&dis[4]==d&&dis[6]==e&&dis[7]==f)                  //20点
  374.         {
  375.                 flag=1;
  376.         }

  377.         if(flag==1)
  378.                 {voise=0;beeled=0;}
  379.         else
  380.                 {voise=1;beeled=1; }
  381. }

  382. //*************************按下按键关闭闹钟
  383. void keyclockdown()
  384. {
  385.         if(!START) {flag=0;beeled=1;}
  386. }

  387. //*********************************************

  388. void aoto()                                   //7s后自动关闭闹铃
  389. {
  390.         if(flag==1)
  391.         {
  392.                 if(over==10) {flag=0;over=0;}

  393.         }
  394. }

  395. /******************温度部分**********************/
  396. void dsInit()                //DS18B20复位,初始化函数
  397. {
  398.    
  399.     unsigned int i;  
  400.     ds = 0;
  401.     i = 100;  
  402.      while(i>0) i--;
  403.     ds = 1;   
  404.     i = 4;
  405.      while(i>0) i--;
  406. }

  407. void dsWait()                //
  408. {
  409.       unsigned int i;
  410.       while(ds);  
  411.       while(~ds);
  412.       i = 4;
  413.       while(i > 0) i--;
  414. }


  415. bit readBit()                //读一位数据函数
  416. {
  417.     unsigned int i;
  418.     bit b;
  419.     ds = 0;
  420.     i++;   
  421.     ds = 1;
  422.    i++; i++;  
  423.     b = ds;
  424.     i = 8;
  425.     while(i>0) i--;
  426.     return b;
  427. }

  428. unsigned char readByte()                //读一个字节数据函数
  429. {
  430.     unsigned int i;
  431.     unsigned char j, dat;
  432.    dat = 0;
  433.     for(i=0; i<8; i++)
  434.     {
  435.         j = readBit();
  436.       
  437.         dat = (j << 7) | (dat >> 1);                //读出的数据最低位在最前面,这样刚好一个字节在dat里
  438.     }
  439.     return dat;
  440. }


  441. void writeByte(unsigned char dat)                //向DS18B20写一个字节数据函数
  442. {
  443.     unsigned int i;
  444.     unsigned char j;
  445.     bit b;
  446.     for(j = 0; j < 8; j++)
  447.     {
  448.         b = dat & 0x01;
  449.         dat >>= 1;
  450.    
  451.         if(b)                             //写1
  452.         {
  453.            ds = 0;i++; i++;  
  454.             ds = 1;   
  455.             i = 8; while(i>0) i--;  
  456.         }
  457.         else  
  458.         {
  459.             ds = 0;                  //写0
  460.           i = 8; while(i>0) i--;  
  461.             ds = 1;
  462.            i++; i++;
  463.         }
  464.    }
  465. }


  466. void sendChangeCmd()                //DS18B20开始获取温度并转换
  467. {
  468.     dsInit();   
  469.     dsWait();   
  470.     delayMs(1);   
  471.     writeByte(0xcc);                //写跳过读ROM指令
  472.     writeByte(0x44);                //写温度转换指令
  473. }

  474. void sendReadCmd()                        //读取寄存器中存储的温度数据
  475. {
  476.     dsInit();
  477.     dsWait();
  478.     delayMs(1);
  479.     writeByte(0xcc);
  480.     writeByte(0xbe);
  481. }


  482. int getTmpValue()                                 //得到温度
  483. {
  484.     unsigned int tmpvalue;
  485.     int value;
  486.     float t;
  487.     unsigned char low, high;
  488.     sendReadCmd();
  489.    
  490.     low = readByte();                //读低8位
  491.     high = readByte();                //读高8位
  492.    
  493.     tmpvalue = high;
  494.     tmpvalue <<= 8;                        //两个字节组合为1个字节
  495.     tmpvalue |= low;

  496.     value = tmpvalue;
  497.     t = value * 0.0625;                 //温度在寄存器中为12位,分辨率为0.0625度
  498.     value = t * 100 + (value > 0 ? 0.5 : -0.5); //乘以100表示小数点后面只取1位,加0.5是四舍五入,大于0加0.5, 小于0减0.5。
  499.     return value;                        //value是整型
  500. }

  501. //*****************************************************
复制代码

全部资料51hei下载地址:
ds18b20 lcd1602 声光报警_仿真电路.zip (21.9 KB, 下载次数: 21)
ds18b20 lcd1602 声光报警_程序.zip (101.46 KB, 下载次数: 24)
系统框图.zip (62.43 KB, 下载次数: 9)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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