找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7301|回复: 21
收起左侧

51单片机DS18B20温度计制作 带仿真和源码

  [复制链接]
ID:295548 发表于 2018-5-31 21:48 | 显示全部楼层 |阅读模式
1、温度可通过调整DS18B20“+”“-”进行调整。
2、当温度超出范围,会有声光报警
3、因为在proteus中找不到三极管8550,所以拿了NPN管MSP8098代替,其原理是相同的,但程序稍做修改,位选本来用低电平,现在高电平位选。
4、如何装载程序?双击单片机—program file—找到相应的hex文件。
1523791717856.jpg
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png 0.png

单片机源程序如下:
  1. #include<reg52.h>     //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
  2. #include<math.h>
  3. #include<INTRINS.H>

  4. #define uchar unsigned char
  5. #define uint   unsigned int

  6. /******************************************************************/
  7. /*                    定义端口                                    */
  8. /******************************************************************/
  9. sbit buzzer=P1^0;//蜂鸣器端口
  10. sbit led1=P1^1;  //led指示灯,当前温度高于设置的最高温度时点亮
  11. sbit led2=P1^2;  //led指示灯,当前温度低于设置的最低温度时点亮
  12. sbit DQ=P1^4;         //ds18b20 端口

  13. sbit key1=P3^4;  //按键
  14. sbit key2=P3^5;
  15. sbit key3=P3^6;
  16. sbit key4=P3^7;

  17. /******************************************************************/
  18. /*                    全局变量                                    */
  19. /******************************************************************/
  20. uint temp;//当前温度值
  21. uchar TempH=0,TempL=0;
  22. int temp_max,temp_min;//设定温度的最大值和最小值
  23. uchar flag_get,count,num;
  24. uchar tab[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //0~~9段码
  25. uchar  str[4];//四位数码管显示字符
  26. uchar display_mod;//数码管显示模式
  27. /******************************************************************/
  28. /*                   函数声明                                     */
  29. /******************************************************************/
  30. unsigned int ReadTemperature(void);//读取温度函数
  31. void Init_DS18B20(void);//18b20初始化函数
  32. unsigned char ReadOneChar(void);//18B20读一个字节
  33. void WriteOneChar(unsigned char dat);//18B20写一个字节
  34. void delay(unsigned int i);//短延时
  35. void delay_ms(uint z);//长延时
  36. void alarm();//报警
  37. void keyscan();//键盘扫描
  38. /******************************************************************/
  39. /*                    主函数                                      */
  40. /******************************************************************/
  41. main()
  42. {
  43.         uchar buzzer_delay=0;//蜂鸣器延时计数
  44.         uchar buzzer_work=0;//蜂鸣器开始工作
  45.         display_mod=0;//显示当前温度
  46.         temp_min=10;//设置最低温  
  47.         temp_max=40;//设置最高温
  48.         TMOD|=0x01;//定时器设置
  49.         TH0=0xef;  //定时器初值
  50.         TL0=0xf0;
  51.         IE=0x82;//EA=1,ET0=1
  52.         TR0=1;  //开定时器
  53.         P2=0xff;  
  54.         count=0;
  55.         buzzer=0;
  56.         while(1)
  57.         {
  58.                   keyscan();//独立按键扫描
  59.                        
  60.                 if(flag_get==1)
  61.                 {   buzzer_delay++;
  62.                         flag_get=0;// 获取温度标志清零
  63.                         temp=ReadTemperature();//读温度值
  64.                 }                       

  65.                 if(display_mod==0)
  66.                 {
  67.                         if(temp&0x8000)
  68.                      {
  69.                              str[0]=0xbf;//负号标志
  70.                              temp=~temp; //取反加1
  71.                                  temp +=1;
  72.                          }
  73.                         else
  74.                         {
  75.                                 str[0]=0xff;
  76.                         }
  77.                         TempH=temp>>4;
  78.                           TempL=temp&0x0F;
  79.                           TempL=TempL*6/10;//小数近似处理
  80.                        
  81.                         str[1]=tab[(TempH%100)/10]; //十位温度
  82.                            str[2]=tab[(TempH%100)%10]&0x7f; //个位温度,带小数点
  83.                            str[3]=tab[TempL];                       
  84.                 }
  85.                 else if(display_mod==1)//显示最低温
  86.                 {
  87.                         str[0]=0xc7;//显示L
  88.                         str[1]=tab[temp_min/100]; //温度百位
  89.                            str[2]=tab[(temp_min%100)/10]; //温度十位
  90.                            str[3]=tab[temp_min%10];//温度个位
  91.                 }
  92.                 else if(display_mod==2)//显示最高温
  93.                 {
  94.                         str[0]=0x89;//显示H
  95.                         str[1]=tab[temp_max/100]; //温度百位
  96.                            str[2]=tab[(temp_max%100)/10]; //温度十位
  97.                            str[3]=tab[temp_max%10];//温度个位       
  98.                 }
  99.                 if(buzzer_delay>5)//为了防止温度获取前就会出现报警
  100.                 {
  101.                         buzzer_work=1;
  102.                 }
  103.                 if(buzzer_work==1)
  104.                         alarm();

  105.           }
  106. }


  107. /******************************************************************/
  108. /*                  定时器中断                                    */
  109. /******************************************************************/
  110. void tim(void) interrupt 1 using 1//中断,用于数码管扫描和温度检测间隔
  111. {
  112.         TH0=0xea;//定时器重装值
  113.         TL0=0xf0;
  114.         num++;
  115.         if (num==100)
  116.     {
  117.                 num=0;
  118.                   flag_get=1;//获取温度标志位有效
  119.         }
  120.         count++;
  121.         if(count==1)
  122.            {
  123.                 //P2=0Xfe;
  124.                 P2=0x01;
  125.             P0=str[0];
  126.         }//数码管扫描
  127.         if(count==2)
  128.    {
  129.                 if(str[1]==tab[0])
  130.                         str[1]=0xff;//显示为空
  131.                    //P2=0Xfd;
  132.                 P2=0x02;
  133.             P0=str[1];
  134.         }
  135.         if(count==3)
  136.    {
  137.                 //P2=0Xfb;
  138.                 P2=0x04;
  139.              P0=str[2];
  140.    }
  141.         if(count==4)
  142.    {
  143.                 //P2=0Xf7;
  144.                 P2=0x08;
  145.              P0=str[3];
  146.                 count=0;
  147.    }
  148. }
  149. /******************************************************************/
  150. /*                    长延时函数                                  */
  151. /******************************************************************/
  152. void delay_ms(uint z) //长延时函数
  153. {
  154.         uint x,y;
  155.         for(x=z;x>0;x--)
  156.                 for(y=110;y>0;y--);
  157. }
  158. /******************************************************************/
  159. /*                    短延时函数                                  */
  160. /******************************************************************/
  161. void delay(unsigned int i)//短延时函数
  162. {
  163.         while(i--);
  164. }

  165. /******************************************************************/
  166. /*                    初始化                                      */
  167. /******************************************************************/
  168. void Init_DS18B20(void)
  169. {
  170.         /*unsigned char x=0;
  171.         DQ = 1;    //DQ复位
  172.         delay(8);  //稍做延时
  173.         DQ = 0;    //单片机将DQ拉低
  174.         delay(80); //精确延时 大于 480us
  175.         DQ = 1;    //拉高总线
  176.         delay(10);
  177.         x=DQ;      //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  178.         delay(5);*/
  179.         unsigned char x=0;
  180.         DQ = 1;    //DQ复位
  181.         delay(8);  //稍做延时
  182.         DQ = 0;    //单片机将DQ拉低
  183.         delay(80); //精确延时 大于 480us
  184.         DQ = 1;    //拉高总线
  185.         delay(14);
  186.         x=DQ;      //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  187.         delay(20);
  188. }

  189. /******************************************************************/
  190. /*                    读一个字节                                  */
  191. /******************************************************************/
  192. unsigned char ReadOneChar(void)
  193. {
  194.         unsigned char i=0;
  195.         unsigned char dat = 0;
  196.         for (i=8;i>0;i--)
  197.         {
  198.                   DQ = 0; // 给脉冲信号
  199.                   dat>>=1;
  200.                   DQ = 1; // 给脉冲信号
  201.                   if(DQ)
  202.                            dat|=0x80;
  203.                   delay(5);
  204.         }
  205.         return(dat);
  206. }

  207. /******************************************************************/
  208. /*                 写一个字节                                     */
  209. /******************************************************************/
  210. void WriteOneChar(unsigned char dat)
  211. {
  212.         unsigned char i=0;
  213.         for (i=8; i>0; i--)
  214.         {
  215.           DQ = 0;
  216.           DQ = dat&0x01;
  217.           delay(5);
  218.           DQ = 1;
  219.           dat>>=1;
  220.         }
  221.         delay(5);
  222. }

  223. /******************************************************************/
  224. /*                   读取温度                                     */
  225. /******************************************************************/
  226. unsigned int ReadTemperature(void)
  227. {       
  228.         unsigned char a=0;
  229.         unsigned int b=0;
  230.         unsigned int t=0;
  231.         Init_DS18B20();
  232.         WriteOneChar(0xCC); // 跳过读序号列号的操作
  233.         WriteOneChar(0x44); // 启动温度转换
  234.         delay(200);
  235.         Init_DS18B20();
  236.         WriteOneChar(0xCC); //跳过读序号列号的操作
  237.         WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
  238.         a=ReadOneChar();   //低位
  239.         b=ReadOneChar();   //高位
  240.         b<<=8;
  241.         t=a+b;
  242.         return(t);
  243. }

  244. /******************************************************************/
  245. /*              独立键盘扫描函数并显示设定的温度                  */
  246. /******************************************************************/
  247. void keyscan()  
  248. {       
  249.         static uchar keynum;//用于切换界面时按键计数
  250.         P3=0xff;//拉高P3口,以读取P3口的值
  251.         if(key4==0)//设置键
  252.         {
  253.                 delay_ms(5);//延时消抖
  254.                 if(key4==0)
  255.                 {
  256.                         keynum++;
  257.                         keynum%=2;//在0、1间变化
  258.                         if(keynum==1)
  259.                         {
  260.                                 display_mod=1;
  261.                         }
  262.                         else
  263.                         {
  264.                                 display_mod=2;
  265.                         }
  266.                 }
  267.                 while(!key4);//松手检测
  268.         }
  269.         if(key3==0)//确定键
  270.         {
  271.                 delay_ms(5);
  272.                 if(key3==0)
  273.                 {
  274.                         keynum=0;
  275.                         display_mod=0;
  276.                 }
  277.                 while(!key3);
  278.         }
  279.         if(key2==0)//加键
  280.         {
  281.                 delay_ms(5);//延时消抖
  282.                 if(key2==0)
  283.                 {
  284.                         if(display_mod==2)
  285.                         {
  286.                                 temp_max++;
  287.                                 if(temp_max>=99)
  288.                                         temp_max=99;
  289.                         }
  290.                         if(display_mod==1)
  291.                         {
  292.                                 temp_min++;
  293.                                 if(temp_min>=temp_max)
  294.                                         temp_min=temp_max;
  295.                         }
  296.                        
  297.                 }
  298.                 while(!key2);//松手检测
  299.         }
  300.         if(key1==0)//减键
  301.         {
  302.                 delay_ms(5);
  303.                 if(key1==0)
  304.                 {
  305.                         if(display_mod==2)
  306.                         {
  307.                                 temp_max--;
  308.                                 if(temp_max<=temp_min)
  309.                                         temp_max=temp_min;
  310.                         }
  311.                         if(display_mod==1)
  312.                         {
  313.                                 temp_min--;
  314.                                 if(temp_min<=0)
  315.                                         temp_min=0;
  316.                         }
  317.                 }
  318.                 while(!key1);//松手检测
  319.         }

  320. }

  321. /******************************************************************/
  322. /*                  蜂鸣器报警程序                                */
  323. /******************************************************************/
  324. void alarm()
  325. {
  326.         if(display_mod==0)//在显示当前温度时报警才会动作
  327.         {
  328.         if(TempH<(temp_min))
  329.         {
  330.                 led1=0;
  331.                 led2=1;
  332.                 buzzer=~buzzer;
  333.         }
  334.         else if(TempH>=(temp_max))
  335.         {
  336.                 led1=1;
  337.                 led2=0;
  338.                 buzzer=~buzzer;
  339.         }
  340.         else
  341.         {
  342.                 led1=1;
  343.                 led2=1;
  344.                 buzzer=0;
  345.         }
  346.         }
  347. }

复制代码

所有资料51hei提供下载:
3 protues仿真.zip (71.5 KB, 下载次数: 308)

评分

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

查看全部评分

回复

使用道具 举报

ID:348549 发表于 2018-6-10 15:34 来自手机 | 显示全部楼层
我用msps6534三极管,这个设计该怎么该
回复

使用道具 举报

ID:356418 发表于 2018-6-23 01:00 | 显示全部楼层
看好,不错,学习了
回复

使用道具 举报

ID:358464 发表于 2018-9-21 12:46 | 显示全部楼层
参考一下,感谢!
回复

使用道具 举报

ID:356963 发表于 2018-9-22 00:06 来自手机 | 显示全部楼层
注释好详细呀,感谢分享
回复

使用道具 举报

ID:367428 发表于 2018-9-24 09:41 | 显示全部楼层
求教如何写这个代码

new image - 1wnty.jpg
回复

使用道具 举报

ID:255559 发表于 2018-9-25 17:18 | 显示全部楼层
我按照原理图焊了板子,数码管显示乱码,我用的共阳数码管
回复

使用道具 举报

ID:402375 发表于 2018-9-25 20:30 | 显示全部楼层
学习了 谢谢楼主
回复

使用道具 举报

ID:402394 发表于 2018-9-25 21:13 | 显示全部楼层
顶一下
回复

使用道具 举报

ID:401656 发表于 2018-9-26 16:26 | 显示全部楼层
这是用的阳极数码管还是阴极的?
回复

使用道具 举报

ID:313459 发表于 2018-9-26 20:30 来自手机 | 显示全部楼层
正在学这个很有帮助
回复

使用道具 举报

ID:120930 发表于 2018-10-24 13:18 | 显示全部楼层
下载了  解压后 没有wendu.dsn文件
回复

使用道具 举报

ID:443131 发表于 2018-12-13 11:49 | 显示全部楼层
数码管不显示负号怎么办
回复

使用道具 举报

ID:463623 发表于 2019-1-7 17:09 | 显示全部楼层
新手村村长 发表于 2018-12-13 11:49
数码管不显示负号怎么办

能发我一份吗谢谢,1179364571@qq.com
回复

使用道具 举报

ID:617770 发表于 2019-9-28 23:11 | 显示全部楼层
这个设计真的秀
回复

使用道具 举报

ID:617770 发表于 2019-9-28 23:11 | 显示全部楼层
学到了
回复

使用道具 举报

ID:623610 发表于 2019-10-14 08:38 来自手机 | 显示全部楼层
学习了 谢谢楼主
回复

使用道具 举报

ID:555539 发表于 2019-10-26 14:21 | 显示全部楼层
学习学习
回复

使用道具 举报

ID:845576 发表于 2020-12-7 12:38 | 显示全部楼层

这个要自己慢慢研究
回复

使用道具 举报

ID:845549 发表于 2020-12-8 15:12 | 显示全部楼层
请问百位和负号不显示该怎么解决呢
回复

使用道具 举报

ID:848824 发表于 2021-1-9 09:38 来自手机 | 显示全部楼层
这个做个保温箱挺好
回复

使用道具 举报

ID:848824 发表于 2021-1-12 08:07 来自手机 | 显示全部楼层
怎么改低电平输出啊!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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