找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4309|回复: 6
收起左侧

单片机DS18B20温度监控系统程序+Proteus仿真

  [复制链接]
ID:535889 发表于 2020-4-22 19:34 | 显示全部楼层 |阅读模式

仿真

仿真


单片机源程序如下:
  1. #include <reg51.h>                         //包含头文件
  2. #define uint unsigned int
  3. #define uchar unsigned char //宏定义
  4. sbit SET=P3^1;                            //定义设置键
  5. sbit DEC=P3^2;                            //定义减少键
  6. sbit ADD=P3^3;                            //定义增加键
  7. sbit BEEP=P3^6;                            //定义蜂鸣器
  8. sbit ALAM=P1^4;                                //定义加热继电器
  9. sbit ALAM1=P1^2;                        //定义制冷继电器
  10. sbit DQ=P3^7;                             //定义DS18B20总线I/O       
  11. bit shanshuo_st;                            //闪烁间隔标志
  12. bit beep_st;                                     //蜂鸣器间隔标志
  13. sbit DIAN = P0^5;                        //小数点
  14. uchar x=0;                                      //计数器
  15. signed char m;                                     //温度值全局变量
  16. uchar n;                                              //温度值全局变量
  17. uchar set_st=0;                             //设置状态标志
  18. signed char shangxian=30;                  //上限报警温度,默认值为30
  19. signed char xiaxian=20;                   //下限报警温度,默认值为20
  20. uchar code  LEDData[]={0x5F,0x44,0x9D,0xD5,0xC6,0xD3,0xDB,0x47,0xDF,0xD7,0xCF,0xDA,0x9B,0xDC,0x9B,0x8B}; //数码管显示码表
  21. //====================================DS18B20=================================
  22. /*****18b20延时子程序*****/
  23. void Delay_DS18B20(int num)
  24. {
  25.   while(num--) ;
  26. }
  27. /*****初始化DS18B20*****/
  28. void Init_DS18B20(void)
  29. {
  30.   unsigned char x=0;
  31.   DQ = 1;         //DQ复位
  32.   Delay_DS18B20(8);    //稍做延时
  33.   DQ = 0;         //单片机将DQ拉低
  34.   Delay_DS18B20(80);   //精确延时,大于480us
  35.   DQ = 1;         //拉高总线
  36.   Delay_DS18B20(14);
  37.   x = DQ;           //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
  38.   Delay_DS18B20(20);
  39. }
  40. /*****读一个字节*****/
  41. unsigned char ReadOneChar(void)
  42. {
  43.   unsigned char i=0;
  44.   unsigned char dat = 0;
  45.   for (i=8;i>0;i--)        //循环8次,读出一个字节
  46.   {
  47.     DQ = 0;     // 给脉冲信号
  48.     dat>>=1;        //数据右移一位
  49.     DQ = 1;     // 给脉冲信号
  50.     if(DQ)                //如果该位为1
  51.     dat|=0x80;        //将数据 | 0x80后,存入dat
  52.     Delay_DS18B20(4);  //延时
  53.   }
  54.   return(dat);        //返回一字节数据
  55. }
  56. /*****写一个字节*****/
  57. void WriteOneChar(unsigned char dat)
  58. {
  59.   unsigned char i=0;
  60.   for (i=8; i>0; i--)         //循环8次,写入一个字节
  61.   {
  62.     DQ = 0;                                 //拉低
  63.     DQ = dat&0x01;                 //将dat数据&0x01后,送入IO口
  64.     Delay_DS18B20(5);         //保持一会
  65.     DQ = 1;                                 //io口拉高
  66.     dat>>=1;                         //dat右移一位
  67.   }
  68. }
  69. /*****读取温度*****/
  70. unsigned int ReadTemperature(void)
  71. {
  72.   unsigned char a=0;
  73.   unsigned char b=0;
  74.   unsigned int t=0;
  75.   float tt=0;
  76.   Init_DS18B20();
  77.   WriteOneChar(0xCC);  //跳过读序号列号的操作
  78.   WriteOneChar(0x44);  //启动温度转换
  79.   Init_DS18B20();
  80.   WriteOneChar(0xCC);  //跳过读序号列号的操作
  81.   WriteOneChar(0xBE);  //读取温度寄存器
  82.   a=ReadOneChar();     //读低8位
  83.   b=ReadOneChar();    //读高8位
  84.   t=b;                                  //将高8位数据存入t
  85.   t<<=8;                          //t左移8位
  86.   t=t|a;                          //将t|a得到一个16位的温度数据
  87.   tt=t*0.0625;                  //一个最低位代表0.0625°C,所以要*0.0625得到实际温度,因为有小数运算,所以定义的tt是float浮点型变量
  88.   t= tt*10+0.5;     //放大10倍输出并四舍五入(将温度放大10倍可以得到小数部分)
  89.   return(t);                //返回得到的温度值
  90. }
  91. //=====================================================================================
  92. /*****延时子程序*****/
  93. void Delay(uint num)
  94. {
  95. while( --num );
  96. }
  97. /*****初始化定时器0*****/
  98. void InitTimer(void)
  99. {
  100.         TMOD=0x1;          //工作方式1
  101.         TH0=0x3c;
  102.         TL0=0xb0;     //50ms(晶振12M)
  103. }
  104. /*****读取温度*****/
  105. void check_wendu(void)
  106. {
  107.         uint a,b,c;
  108.         c=ReadTemperature()-5;                          //获取温度值并减去DS18B20的温漂误差
  109.         a=c/100;                                                     //计算得到十位数字
  110.         b=c/10-a*10;                                            //计算得到个位数字
  111.         m=c/10;                                                      //计算得到整数位
  112.         n=c-a*100-b*10;                                    //计算得到小数位
  113.         if(m<0){m=0;n=0;}                                   //设置温度显示上限
  114.         if(m>99){m=99;n=9;}                                   //设置温度显示上限   
  115. }
  116. /*****显示开机初始化等待画面*****/
  117. void Disp_init(void)   
  118. {
  119.         P0 = ~0x80;      //显示----
  120.         P2 = 0x7F;                 //依次打开各位
  121.         Delay(200);                 //延时
  122.         P2 = 0xDF;
  123.         Delay(200);   
  124.         P2 = 0xF7;
  125.         Delay(200);
  126.         P2 = 0xFD;
  127.         Delay(200);
  128.         P2 = 0xFF;         //关闭显示
  129. }
  130. /*****显示温度子程序*****/
  131. void Disp_Temperature(void)     //显示温度
  132. {
  133.         P0 = ~0x98;      //显示C
  134.         P2 = 0x7F;                 //打开位
  135.         Delay(400);                 //延时
  136.         P2 = 0xff;         //关闭显示
  137.         P0=~LEDData[n];    //显示个位
  138.         P2 = 0xDF;
  139.         Delay(400);
  140.         P2 = 0xff;         //关闭显示
  141.         P0 =~LEDData[m%10];    //显示十位
  142.         DIAN = 0;         //显示小数点
  143.         P2 = 0xF7;
  144.         Delay(400);
  145.         P2 = 0xff;         //关闭显示
  146.         P0 =~LEDData[m/10];    //显示百位
  147.         P2 = 0xFD;
  148.         Delay(400);
  149.         P2 = 0xff;         //关闭显示
  150. }
  151. /*****显示报警温度子程序*****/
  152. void Disp_alarm(uchar baojing)
  153. {
  154.         P0 =~0x98;      //显示C
  155.         P2 = 0x7F;                //选中位
  156.         Delay(200);
  157.         P2 = 0xff;         //关闭显示
  158.         P0 =~LEDData[baojing%10]; //显示十位
  159.         P2 = 0xDF;
  160.         Delay(200);
  161.         P2 = 0xff;         //关闭显示
  162.         P0 =~LEDData[baojing/10]; //显示百位
  163.         P2 = 0xF7;
  164.         Delay(200);
  165.         P2 = 0xff;         //关闭显示
  166.         if(set_st==1)P0 =~0xCE;                 //设置上限时显示H
  167.         else if(set_st==2)P0 =~0x1A;  //设置下限时显示L
  168.         P2 = 0xFD;
  169.         Delay(200);
  170.         P2 = 0xff;         //关闭显示
  171. }
  172. /*****报警子程序*****/
  173. void Alarm()
  174. {
  175.         if(x>=10){beep_st=~beep_st;x=0;} //控制闪烁(x随定时器每50ms加1,10次时500ms,这里闪烁就是500ms亮500ms灭)
  176.         if(m>=shangxian)  //温度大于上限时
  177.         {
  178.                 ALAM=0;                  //降温继电器吸合
  179.                 ALAM1=1;
  180.                 if(beep_st==1)//控制蜂鸣器闪烁变量为1时
  181.                 BEEP=0;                  //蜂鸣器响
  182.                 else                  //控制蜂鸣器闪烁变量为0时
  183.                 BEEP=1;                  //蜂鸣器停止
  184.         }
  185.         else if(m<xiaxian)//温度小于下限时
  186.         {
  187.                 ALAM1=0;          //升温继电器吸合
  188.                 ALAM=1;
  189.                 if(beep_st==1)//控制蜂鸣器闪烁
  190.                 BEEP=0;
  191.                 else
  192.                 BEEP=1;
  193.         }
  194.         else                          //温度在上下限范围内时
  195.         {
  196.                 BEEP=1;                  //关闭蜂鸣器
  197.                 ALAM=1;                  //关闭加热和降温继电器
  198.                 ALAM1=1;
  199.         }
  200. }
  201. /*****主函数*****/
  202. void main(void)
  203. {
  204.         uint z;
  205.         InitTimer();    //初始化定时器
  206.         EA=1;      //全局中断开关
  207.         TR0=1;                 //打开定时器定时开关
  208.         ET0=1;      //开启定时器0
  209.         IT0=1;      //外部中断下降沿有效  
  210.         IT1=1;
  211.         check_wendu();
  212.         check_wendu();          //读取两次温度,防止开机读取到85°C,使继电器误操作
  213.         for(z=0;z<300;z++)        //开机画面
  214.         {
  215.                 Disp_init();        
  216.         }
  217.         while(1)                   //while循环
  218.         {
  219.                 if(SET==0)           //判断设置键是否按下
  220.                 {
  221.                         Delay(2000);         //延时去抖
  222.                         do{}while(SET==0);         //执行空语句,判断按键是否松开,松开向下执行,否则重新执行空语句
  223.                         set_st++;x=0;shanshuo_st=1;        //设置键松开后将设置变量加1,闪烁标志位置1
  224.                         if(set_st>2)set_st=0;        //当设置完成时,退出设置
  225.                 }
  226.                 if(set_st==0) //正常工作时
  227.                 {
  228.                         EX0=0;    //关闭外部中断0
  229.                         EX1=0;    //关闭外部中断1
  230.                         check_wendu();
  231.                         Disp_Temperature();        //检测温度
  232.                         Alarm();   //报警检测
  233.                 }
  234.                 else if(set_st==1)        //设置上限时
  235.                 {
  236.                         BEEP=1;    //关闭蜂鸣器
  237.                         ALAM=1;
  238.                         ALAM1=1;  //继电器关闭
  239.                         EX0=1;    //开启外部中断0
  240.                         EX1=1;    //开启外部中断1
  241.                         if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
  242.                         if(shanshuo_st) {Disp_alarm(shangxian);}  //闪烁
  243.                 }
  244.                 else if(set_st==2)        //设置下限时
  245.                 {
  246.                         BEEP=1;    //关闭蜂鸣器
  247.                         ALAM=1;
  248.                         ALAM1=1;   //关闭继电器
  249.                         EX0=1;    //开启外部中断0
  250.                         EX1=1;    //开启外部中断1
  251.                         if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
  252.                         if(shanshuo_st) {Disp_alarm(xiaxian);}         //闪烁
  253.                 }
  254.         }
  255. }
  256. /*****定时器0中断服务程序*****/
  257. void timer0(void) interrupt 1
  258. {
  259. TH0=0x3c;
  260. TL0=0xb0;                 //12MHz晶振时定时50ms
  261. x++;
  262. }
  263. /*****外部中断0服务程序*****/
  264. void int0(void) interrupt 0
  265. {
  266.         EX0=0;      //关外部中断0
  267.         if(DEC==0&&set_st==1)           //设置上限时按下减按键
  268.         {
  269.                 do
  270.                 {
  271.                         Disp_alarm(shangxian);        //显示设置
  272.                 }
  273.                 while(DEC==0);
  274.                 shangxian--;                                //将上限值减1
  275.                 if(shangxian<=xiaxian)shangxian=xiaxian+1;          //上限值最小比下限值大1
  276.         }
  277.         else if(DEC==0&&set_st==2)         //设置下限时按下减按键
  278.         {
  279.                 do
  280.                 {
  281.                         Disp_alarm(xiaxian);
  282.                 }
  283.                 while(DEC==0);
  284.                 xiaxian--;                                  //下限减1
  285.                 if(xiaxian<0)xiaxian=0;          //减到0时停止
  286.         }
  287. }
  288. /*****外部中断1服务程序*****/
  289. void int1(void) interrupt 2
  290. {
  291.         EX1=0;      //关外部中断1
  292.         if(ADD==0&&set_st==1)                 //设置上限时按下加按键
  293.         {
  294.                 do
  295.                 {
  296.                         Disp_alarm(shangxian);
  297.                 }
  298.                 while(ADD==0);
  299.                 shangxian++;                                 //上限值加1
  300.                 if(shangxian>99)shangxian=99;//最大加到99
  301.         }
  302.         else if(ADD==0&&set_st==2)           //设置下限时按下加按键
  303.         {
  304.                 do
  305.                 {
  306.                         Disp_alarm(xiaxian);
  307.                 }
  308.                 while(ADD==0);
  309.                 xiaxian++;                                   //下限加
  310.                 if(xiaxian>=shangxian)xiaxian=shangxian-1;         //下限最大加到上限值减1
  311.         }  
  312. }
复制代码

所有资料51hei提供下载:
仿真+烧录文件+c源码.7z (5.43 MB, 下载次数: 158)

评分

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

查看全部评分

回复

使用道具 举报

ID:727755 发表于 2020-4-24 13:40 | 显示全部楼层
仿真是Proteus8.8才能打开的
回复

使用道具 举报

ID:737311 发表于 2020-4-24 21:24 | 显示全部楼层
单片机AT89C51为核心的吗?
回复

使用道具 举报

ID:736111 发表于 2020-4-25 01:04 来自手机 | 显示全部楼层
想问一下这个温度传感器不用进行采样转换吗?可以直接用吗?
回复

使用道具 举报

ID:700149 发表于 2020-4-26 19:03 来自手机 | 显示全部楼层
大神还在吗!!!那个升温模块为什么也是电风扇啊,如果换成电热丝的话要怎么操作啊
回复

使用道具 举报

ID:653838 发表于 2020-4-26 21:12 | 显示全部楼层
学习了,给你点赞。
回复

使用道具 举报

ID:1035250 发表于 2022-6-20 17:45 来自手机 | 显示全部楼层
我想把数码管换成1602液晶屏,代码和仿真怎么改,有人帮我一下吗
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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