找回密码
 注册
关于网站域名变更的通知
查看: 124|回复: 2
打印 上一主题 下一主题

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

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-6-21 09:14 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
7 N6 E- K) [, I5 ~
" A- r$ [6 R9 L/ ]3 I. L
单片机源程序如下:+ C; u( J/ E. K! N8 F, s  b
  • #include <reg51.h>                         //包含头文件
  • #define uint unsigned int
  • #define uchar unsigned char //宏定义
  • sbit SET=P3^1;                            //定义设置键
  • sbit DEC=P3^2;                            //定义减少键
  • sbit ADD=P3^3;                            //定义增加键
  • sbit BEEP=P3^6;                            //定义蜂鸣器
  • sbit ALAM=P1^4;                                //定义加热继电器
  • sbit ALAM1=P1^2;                        //定义制冷继电器
  • sbit DQ=P3^7;                             //定义DS18B20总线I/O
  • bit shanshuo_st;                            //闪烁间隔标志
  • bit beep_st;                                     //蜂鸣器间隔标志
  • sbit DIAN = P0^5;                        //小数点
  • uchar x=0;                                      //计数器
  • signed char m;                                     //温度值全局变量
  • uchar n;                                              //温度值全局变量
  • uchar set_st=0;                             //设置状态标志
  • signed char shangxian=30;                  //上限报警温度,默认值为30
  • signed char xiaxian=20;                   //下限报警温度,默认值为20
  • uchar code  LEDData[]={0x5F,0x44,0x9D,0xD5,0xC6,0xD3,0xDB,0x47,0xDF,0xD7,0xCF,0xDA,0x9B,0xDC,0x9B,0x8B}; //数码管显示码表
  • //====================================DS18B20=================================
  • /*****18b20延时子程序*****/
  • void Delay_DS18B20(int num)
  • {
  •   while(num--) ;
  • }
  • /*****初始化DS18B20*****/
  • void Init_DS18B20(void)
  • {
  •   unsigned char x=0;
  •   DQ = 1;         //DQ复位
  •   Delay_DS18B20(8);    //稍做延时
  •   DQ = 0;         //单片机将DQ拉低
  •   Delay_DS18B20(80);   //精确延时,大于480us
  •   DQ = 1;         //拉高总线
  •   Delay_DS18B20(14);
  •   x = DQ;           //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
  •   Delay_DS18B20(20);
  • }
  • /*****读一个字节*****/
  • unsigned char ReadOneChar(void)
  • {
  •   unsigned char i=0;
  •   unsigned char dat = 0;
  •   for (i=8;i>0;i--)        //循环8次,读出一个字节
  •   {
  •     DQ = 0;     // 给脉冲信号
  •     dat>>=1;        //数据右移一位
  •     DQ = 1;     // 给脉冲信号
  •     if(DQ)                //如果该位为1
  •     dat|=0x80;        //将数据 | 0x80后,存入dat
  •     Delay_DS18B20(4);  //延时
  •   }
  •   return(dat);        //返回一字节数据
  • }
  • /*****写一个字节*****/
  • void WriteOneChar(unsigned char dat)
  • {
  •   unsigned char i=0;
  •   for (i=8; i>0; i--)         //循环8次,写入一个字节
  •   {
  •     DQ = 0;                                 //拉低
  •     DQ = dat&0x01;                 //将dat数据&0x01后,送入IO口
  •     Delay_DS18B20(5);         //保持一会
  •     DQ = 1;                                 //io口拉高
  •     dat>>=1;                         //dat右移一位
  •   }
  • }
  • /*****读取温度*****/
  • unsigned int ReadTemperature(void)
  • {
  •   unsigned char a=0;
  •   unsigned char b=0;
  •   unsigned int t=0;
  •   float tt=0;
  •   Init_DS18B20();
  •   WriteOneChar(0xCC);  //跳过读序号列号的操作
  •   WriteOneChar(0x44);  //启动温度转换
  •   Init_DS18B20();
  •   WriteOneChar(0xCC);  //跳过读序号列号的操作
  •   WriteOneChar(0xBE);  //读取温度寄存器
  •   a=ReadOneChar();     //读低8位
  •   b=ReadOneChar();    //读高8位
  •   t=b;                                  //将高8位数据存入t
  •   t<<=8;                          //t左移8位
  •   t=t|a;                          //将t|a得到一个16位的温度数据
  •   tt=t*0.0625;                  //一个最低位代表0.0625°C,所以要*0.0625得到实际温度,因为有小数运算,所以定义的tt是float浮点型变量
  •   t= tt*10+0.5;     //放大10倍输出并四舍五入(将温度放大10倍可以得到小数部分)
  •   return(t);                //返回得到的温度值
  • }
  • //=====================================================================================
  • /*****延时子程序*****/
  • void Delay(uint num)
  • {
  • while( --num );
  • }
  • /*****初始化定时器0*****/
  • void InitTimer(void)
  • {
  •         TMOD=0x1;          //工作方式1
  •         TH0=0x3c;
  •         TL0=0xb0;     //50ms(晶振12M)
  • }
  • /*****读取温度*****/
  • void check_wendu(void)
  • {
  •         uint a,b,c;
  •         c=ReadTemperature()-5;                          //获取温度值并减去DS18B20的温漂误差
  •         a=c/100;                                                     //计算得到十位数字
  •         b=c/10-a*10;                                            //计算得到个位数字
  •         m=c/10;                                                      //计算得到整数位
  •         n=c-a*100-b*10;                                    //计算得到小数位
  •         if(m<0){m=0;n=0;}                                   //设置温度显示上限
  •         if(m>99){m=99;n=9;}                                   //设置温度显示上限
  • }
  • /*****显示开机初始化等待画面*****/
  • void Disp_init(void)
  • {
  •         P0 = ~0x80;      //显示----
  •         P2 = 0x7F;                 //依次打开各位
  •         Delay(200);                 //延时
  •         P2 = 0xDF;
  •         Delay(200);
  •         P2 = 0xF7;
  •         Delay(200);
  •         P2 = 0xFD;
  •         Delay(200);
  •         P2 = 0xFF;         //关闭显示
  • }
  • /*****显示温度子程序*****/
  • void Disp_Temperature(void)     //显示温度
  • {
  •         P0 = ~0x98;      //显示C
  •         P2 = 0x7F;                 //打开位
  •         Delay(400);                 //延时
  •         P2 = 0xff;         //关闭显示
  •         P0=~LEDData[n];    //显示个位
  •         P2 = 0xDF;
  •         Delay(400);
  •         P2 = 0xff;         //关闭显示
  •         P0 =~LEDData[m%10];    //显示十位
  •         DIAN = 0;         //显示小数点
  •         P2 = 0xF7;
  •         Delay(400);
  •         P2 = 0xff;         //关闭显示
  •         P0 =~LEDData[m/10];    //显示百位
  •         P2 = 0xFD;
  •         Delay(400);
  •         P2 = 0xff;         //关闭显示
  • }
  • /*****显示报警温度子程序*****/
  • void Disp_alARM(uchar baojing)
  • {
  •         P0 =~0x98;      //显示C
  •         P2 = 0x7F;                //选中位
  •         Delay(200);
  •         P2 = 0xff;         //关闭显示
  •         P0 =~LEDData[baojing%10]; //显示十位
  •         P2 = 0xDF;
  •         Delay(200);
  •         P2 = 0xff;         //关闭显示
  •         P0 =~LEDData[baojing/10]; //显示百位
  •         P2 = 0xF7;
  •         Delay(200);
  •         P2 = 0xff;         //关闭显示
  •         if(set_st==1)P0 =~0xCE;                 //设置上限时显示H
  •         else if(set_st==2)P0 =~0x1A;  //设置下限时显示L
  •         P2 = 0xFD;
  •         Delay(200);
  •         P2 = 0xff;         //关闭显示
  • }
  • /*****报警子程序*****/
  • void Alarm()
  • {
  •         if(x>=10){beep_st=~beep_st;x=0;} //控制闪烁(x随定时器每50ms加1,10次时500ms,这里闪烁就是500ms亮500ms灭)
  •         if(m>=shangxian)  //温度大于上限时
  •         {
  •                 ALAM=0;                  //降温继电器吸合
  •                 ALAM1=1;
  •                 if(beep_st==1)//控制蜂鸣器闪烁变量为1时
  •                 BEEP=0;                  //蜂鸣器响
  •                 else                  //控制蜂鸣器闪烁变量为0时
  •                 BEEP=1;                  //蜂鸣器停止
  •         }
  •         else if(m<xiaxian)//温度小于下限时
  •         {
  •                 ALAM1=0;          //升温继电器吸合
  •                 ALAM=1;
  •                 if(beep_st==1)//控制蜂鸣器闪烁
  •                 BEEP=0;
  •                 else
  •                 BEEP=1;
  •         }
  •         else                          //温度在上下限范围内时
  •         {
  •                 BEEP=1;                  //关闭蜂鸣器
  •                 ALAM=1;                  //关闭加热和降温继电器
  •                 ALAM1=1;
  •         }
  • }
  • /*****主函数*****/
  • void main(void)
  • {
  •         uint z;
  •         InitTimer();    //初始化定时器
  •         EA=1;      //全局中断开关
  •         TR0=1;                 //打开定时器定时开关
  •         ET0=1;      //开启定时器0
  •         IT0=1;      //外部中断下降沿有效
  •         IT1=1;
  •         check_wendu();
  •         check_wendu();          //读取两次温度,防止开机读取到85°C,使继电器误操作
  •         for(z=0;z<300;z++)        //开机画面
  •         {
  •                 Disp_init();
  •         }
  •         while(1)                   //while循环
  •         {
  •                 if(SET==0)           //判断设置键是否按下
  •                 {
  •                         Delay(2000);         //延时去抖
  •                         do{}while(SET==0);         //执行空语句,判断按键是否松开,松开向下执行,否则重新执行空语句
  •                         set_st++;x=0;shanshuo_st=1;        //设置键松开后将设置变量加1,闪烁标志位置1
  •                         if(set_st>2)set_st=0;        //当设置完成时,退出设置
  •                 }
  •                 if(set_st==0) //正常工作时
  •                 {
  •                         EX0=0;    //关闭外部中断0
  •                         EX1=0;    //关闭外部中断1
  •                         check_wendu();
  •                         Disp_Temperature();        //检测温度
  •                         Alarm();   //报警检测
  •                 }
  •                 else if(set_st==1)        //设置上限时
  •                 {
  •                         BEEP=1;    //关闭蜂鸣器
  •                         ALAM=1;
  •                         ALAM1=1;  //继电器关闭
  •                         EX0=1;    //开启外部中断0
  •                         EX1=1;    //开启外部中断1
  •                         if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
  •                         if(shanshuo_st) {Disp_alarm(shangxian);}  //闪烁
  •                 }
  •                 else if(set_st==2)        //设置下限时
  •                 {
  •                         BEEP=1;    //关闭蜂鸣器
  •                         ALAM=1;
  •                         ALAM1=1;   //关闭继电器
  •                         EX0=1;    //开启外部中断0
  •                         EX1=1;    //开启外部中断1
  •                         if(x>=10){shanshuo_st=~shanshuo_st;x=0;}
  •                         if(shanshuo_st) {Disp_alarm(xiaxian);}         //闪烁
  •                 }
  •         }
  • }
  • /*****定时器0中断服务程序*****/
  • void timer0(void) interrupt 1
  • {
  • TH0=0x3c;
  • TL0=0xb0;                 //12MHz晶振时定时50ms
  • x++;
  • }
  • /*****外部中断0服务程序*****/
  • void int0(void) interrupt 0
  • {
  •         EX0=0;      //关外部中断0
  •         if(DEC==0&&set_st==1)           //设置上限时按下减按键
  •         {
  •                 do
  •                 {
  •                         Disp_alarm(shangxian);        //显示设置
  •                 }
  •                 while(DEC==0);
  •                 shangxian--;                                //将上限值减1
  •                 if(shangxian<=xiaxian)shangxian=xiaxian+1;          //上限值最小比下限值大1
  •         }
  •         else if(DEC==0&&set_st==2)         //设置下限时按下减按键
  •         {
  •                 do
  •                 {
  •                         Disp_alarm(xiaxian);
  •                 }
  •                 while(DEC==0);
  •                 xiaxian--;                                  //下限减1
  •                 if(xiaxian<0)xiaxian=0;          //减到0时停止
  •         }
  • }
  • /*****外部中断1服务程序*****/
  • void int1(void) interrupt 2
  • {
  •         EX1=0;      //关外部中断1
  •         if(ADD==0&&set_st==1)                 //设置上限时按下加按键
  •         {
  •                 do
  •                 {
  •                         Disp_alarm(shangxian);
  •                 }
  •                 while(ADD==0);
  •                 shangxian++;                                 //上限值加1
  •                 if(shangxian>99)shangxian=99;//最大加到99
  •         }
  •         else if(ADD==0&&set_st==2)           //设置下限时按下加按键
  •         {
  •                 do
  •                 {
  •                         Disp_alarm(xiaxian);
  •                 }
  •                 while(ADD==0);
  •                 xiaxian++;                                   //下限加
  •                 if(xiaxian>=shangxian)xiaxian=shangxian-1;         //下限最大加到上限值减1
  •         }
  • }
    ( l  @+ s* k, L. n. _

( k' m& O, e- z

该用户从未签到

2#
发表于 2022-6-21 09:49 | 只看该作者
想问一下这个温度传感器不用进行采样转换吗?可以直接用吗?9 ?* C7 N! n' O2 D
还有那个升温模块为什么也是电风扇啊,如果换成电热丝的话要怎么操作啊

点评

也来,学一学。Thanks♪(・ω・)ノ  详情 回复 发表于 2022-6-21 13:11

该用户从未签到

3#
发表于 2022-6-21 13:11 | 只看该作者
Maskman 发表于 2022-6-21 09:491 d/ z" z4 j8 `- d! W  _* F
想问一下这个温度传感器不用进行采样转换吗?可以直接用吗?  C* ^: o; n& l: u- i" ]+ m
还有那个升温模块为什么也是电风扇啊,如果换 ...

& P: i  f+ [8 @5 z, O5 P( f也来,学一学。Thanks♪(・ω・)ノ1 r- ~8 p3 A+ p, a
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-19 22:45 , Processed in 0.093750 second(s), 24 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

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