找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2631|回复: 7
收起左侧

基于51单片机的温度报警系统设计

  [复制链接]
ID:856329 发表于 2022-3-18 10:19 来自手机 | 显示全部楼层 |阅读模式
  设计中有很多不完善的地方,欢迎各位大佬指正。      演示视频:https://www.bilibili.com/video/BV1CS4y1u7s6?share_source=copy_web

利用单片机、DS18B20温度传感器、数码管、按键、蜂鸣器设计。编程时考虑数码需要一直扫描,按键也需要一直扫描,DS18B20实时读取温度也需要实时扫描,这三个都放到主函数的while循环中,由于温度读取转换时间比较长,数码管就会一直闪烁。另外数码管和按键都再主函数中扫描,按键按下时数码管会熄灭。

最后,在一个定时器中断中扫描数码管,另一个定时器中断读取温,主函数主要扫描按键和判断温度值是否超过上下限。

经过不断调试终于实现了所有的功能。

功能说明:

1.数码管默认显示当前温度。默认上限30℃,下限22℃

2.当温度高于上限,蜂鸣器报警,红色LED点亮;低于下限,蜂

  鸣器报警,蓝色LED点亮。

3.第一次点击'设置'按键,数码管第一位显示H,此时点击'加'

  '减'按键,调节温度上限值。

  第二次点击'设置'按键,数码管第一位显示L,此时点击'加'

  '减'按键,调节温度下限值。

  注意:在调节温度上下限过程中,温度报警关闭。

  第三次点击'设置'按键,退出设置状态,打开温度报警。

4.温度传感器测温范围:-55—128℃。

  温度上下限调节范围:-55—128℃。

洞洞板.png

仿真截图.png

原理图.png

程序截图.png

元件清单.png


主函数 单片机代码如下:

  1. /******************************************************************************
  2. * 单片机温度报警系统
  3. *******************************************************************************/
  4. #include <reg52.h>                        
  5. #include "delay.h"
  6. #include "key.h"
  7. #include "DS18B20.h"

  8. #define uchar unsigned char         //对数据类型定义
  9. #define uint  unsigned int

  10. /****************************端口定义******************************************/

  11. sbit D1=P2^4;
  12. sbit D2=P2^6;
  13. sbit D3=P2^5;
  14. sbit D4=P2^7;
  15.                                  
  16. sbit Beep=P1^6;                                  //蜂鸣器
  17. sbit LED_G=P1^2;                        //绿色LED端口
  18. sbit LED_B=P1^0;                        //蓝色LED端口
  19. sbit LED_R=P1^1;                        //红色LED端口                                 
  20. /****************************定义变量******************************************/
  21. uchar KeyValve=0;                        //按键值
  22. float Temp=20.0;                        //温度变量
  23. float TH=30.0;                                   //温度上限
  24. float TL=22.0;                                   //温度下限
  25. uint  Time_Count=1;                 //定时器0中断次数
  26. uchar Temp_Str[4];                       //数组变量存放温度数据
  27. uchar Set_Mode=0;                        //设置模式
  28. uchar SMG_Data[4]={0,0,0,0}; //存放数码管的各个位的值
  29. uchar code smgduan[]={                //共阳极数码管段码
  30.         0xc0,        //0,0
  31.         0xf9,        //1,1
  32.         0xa4,        //2,2
  33.         0xb0,        //3,3
  34.         0x99,        //4,4
  35.         0x92,        //5,5
  36.         0x82,        //6,6
  37.         0xf8,        //7,7
  38.         0x80,        //8,8
  39.         0x90,        //9,9
  40.         0x88,        //10,A
  41.         0x83,        //11,b
  42.         0xc6,        //12,C
  43.         0xa1,        //13,d
  44.         0x86,        //14,E
  45.         0x8e,        //15,F
  46.         0xff,        //16,
  47.         0xbf,        //17,
  48.         0x89,        //18,H
  49.         0xc7        //19,L         
  50. };
  51. /*****************************************************************************/
  52. /***************************函数声明******************************************/
  53. void Timer_Init();                              //定时器初始化
  54. void Temp_T(float t);                         //温度转换函数
  55. /******************************************************************************
  56. * 函 数 名         : 主函数
  57. * 函数功能                   :
  58. * 输    入         : 无
  59. * 输    出         : 无
  60. *******************************************************************************/
  61. void main()
  62. {
  63.         DS18B20_Init();                                          //温度传感器初始化        
  64.         Timer_Init();                                           //定时器初始化
  65.         Delay_Ms(100);

  66.         while(1)
  67.         {
  68.                 /***********按键扫描程序**************/
  69.                 KeyValve=Key_Check();                   //扫描按键
  70.                 if(KeyValve!=0)                                  //判断按键是否按下
  71.                 {
  72.                         switch(KeyValve)                   //判断按键值,并处理
  73.                           {
  74.                                 case 1:                                //温度上限/下限设置
  75.                                 {
  76.                                         if(Set_Mode<2)
  77.                                                 Set_Mode++;
  78.                                         else
  79.                                                 Set_Mode=0;                                       
  80.                                         Delay_Ms(200);
  81.                                 }
  82.                                 break;
  83.                                 case 2:                                                                //按键加        
  84.                                 {
  85.                                         if((Set_Mode==1)&&(TH<128.0))        //限制温度上限小于128℃                                
  86.                                                 TH=TH+1.0;                                        //温度上限加一                                                        
  87.                                         if((Set_Mode==2)&&(TL<TH))                //限制温度下限小于温度上限
  88.                                                 TL=TL+1.0;                                        //温度下限加一
  89.                                         Delay_Ms(200);
  90.                                 }
  91.                                 break;
  92.                                 case 3:                                                                //按键减
  93.                                 {
  94.                                         if((Set_Mode==1)&&(TH>TL))                //限制温度上限大于温度下限                        
  95.                                                 TH=TH-1.0;                                        //温度上限减一                                                        
  96.                                         if((Set_Mode==2)&&(TL>-55.0))        //限制温度下限大于-55℃
  97.                                                 TL=TL-1.0;                                        //温度下限减一
  98.                                         Delay_Ms(200);
  99.                                 }
  100.                                 break;
  101.                         }
  102.                 }
  103.                 /***********温度上下限判断报警程序**************/
  104.                 if(Set_Mode==0)
  105.                 {
  106.                         if(Temp>TH)
  107.                         {                                
  108.                                 LED_R=0;                //红灯点亮
  109.                                 LED_B=1;                //蓝灯熄灭
  110.                                 LED_G=1;
  111.                                 Beep=0;                        //蜂鸣器报警
  112.                         }
  113.                         else if(Temp<TL)
  114.                         {                                
  115.                                 LED_R=1;                //红灯熄灭
  116.                                 LED_B=0;                //蓝灯点亮
  117.                                 LED_G=1;
  118.                                 Beep=0;                        //蜂鸣器报警
  119.                         }
  120.                         else
  121.                         {
  122.                                 LED_R=1;                //红灯熄灭
  123.                                 LED_B=1;                //蓝灯熄灭
  124.                                 LED_G=0;
  125.                                 Beep=1;
  126.                         }                        
  127.                 }
  128.                 else
  129.                         Beep=1;               
  130.         }
  131. }
  132. /*******************************************************************************
  133. * 函 数 名         : Temp_T(float t)
  134. * 函数功能                   : 温度转换函数:将温度值放到数组中,便于显示
  135. * 输    入         : t
  136. * 输    出         : 无
  137. *******************************************************************************/
  138. void Temp_T(float t)
  139. {
  140.         if(Set_Mode==0)
  141.         {
  142.                 t=t*10.0;                                                //放大十倍        
  143.                 if(t>=0)                                                   //正温度
  144.                 {
  145.                 if(((int)t/1000)==0)
  146.                 SMG_Data[0]=16;
  147.                 else
  148.                 SMG_Data[0]=(int)t/1000;                //提取温度百、十、个位
  149.                 SMG_Data[1]=((int)t%1000)/100;                        
  150.                 SMG_Data[2]=((int)t%100)/10;
  151.                 SMG_Data[3]=(int)t%10;
  152.                 }
  153.                 else                                                           //负温度
  154.                 {               
  155.                 t=-t;                                                           //将负数转换为正数
  156.                 SMG_Data[0]=17;                                        //显示“—”号
  157.                 SMG_Data[1]=(int)t/100;                        //提取温度个、十位
  158.                 SMG_Data[2]=((int)t%100)/10;
  159.                 SMG_Data[3]=(int)t%10;               
  160.                 }
  161.         }
  162.         else
  163.         {
  164.                 if(Set_Mode==1)
  165.                 SMG_Data[0]=18;                                           //数码管第一位显示H
  166.                 if(Set_Mode==2)
  167.                 SMG_Data[0]=19;                                           //数码管第一位显示L
  168.                 if(t>=0)                                                           //正温度
  169.                 {               
  170.                 SMG_Data[1]=(int)t/100;                         //提取温度百、十、个位
  171.                 SMG_Data[2]=((int)t%100)/10;
  172.                 SMG_Data[3]=(int)t%10;
  173.                 }
  174.                 else                                                                   //负温度
  175.                 {
  176.                 t=-t;                                                           //将负数转换为正数
  177.                 SMG_Data[1]=17;                                        //显示“—”号
  178.                 SMG_Data[2]=((int)t%100)/10;        //提取温度个、十位
  179.                 SMG_Data[3]=(int)t%10;
  180.                 t=-t;                                                           //将温度恢复
  181.                 }
  182.         }
  183. }
  184. /*****************************************************************************
  185. * 函 数 名         : Timer_Init
  186. * 函数功能                   : 定时器初始化
  187. * 输    入         : 无
  188. * 输    出         : 无
  189. *****************************************************************************/
  190. void Timer_Init()
  191. {
  192.         TMOD=0x11;  //打开定时器0,工作方式1。        

  193.         TH0=0xff;        //给定时器0赋初值,定时200us (65536-200)/256 (65536-200)%256
  194.         TL0=0x38;

  195.         TH1=0xc5;   //定时60ms
  196.         TL1=0x68;

  197.         ET0=1;      //打开定时器0中断允许
  198.         ET1=1;                //打开定时器1中断允许

  199.         TR0=1;      //打开定时器0
  200.         TR1=1;      //打开定时器1               
  201.         PT1=1;            //高优先级

  202.         EA=1;       //打开总中断
  203. }
  204. /*******************************************************************************
  205. * 函 数 名         : void Timer0() interrupt 1
  206. * 函数功能                   : 定时器0中断函数
  207. * 输    入         : 无
  208. * 输    出         : 无
  209. *******************************************************************************/
  210. void Timer0() interrupt 1
  211. {
  212.         TH0=0xff;         //给定时器赋初值,定时
  213.         TL0=0x38;

  214.         if(Time_Count%2==0)
  215.         {
  216.                 switch(Time_Count%8)         //位选,选择点亮的数码管,
  217.                 {
  218.                         case(0):
  219.                                 D1=0;
  220.                                 D2=1;
  221.                                 D3=1;
  222.                                 D4=1;
  223.                         break;//显示第0位
  224.                         case(2):
  225.                                 D1=1;
  226.                                 D2=0;
  227.                                 D3=1;
  228.                                 D4=1;
  229.                         break;//显示第1位
  230.                         case(4):
  231.                                 D1=1;
  232.                                 D2=1;
  233.                                 D3=0;
  234.                                 D4=1;
  235.                         break;//显示第2位
  236.                         case(6):
  237.                                 D1=1;
  238.                                 D2=1;
  239.                                 D3=1;
  240.                                 D4=0;
  241.                         break;//显示第3位        
  242.                 }
  243.                 if((Set_Mode==0)&&(Time_Count%8==4))
  244.                         P0=smgduan[SMG_Data[(Time_Count%8)/2]]-0x80;//显示小数点
  245.                 P0=smgduan[SMG_Data[(Time_Count%8)/2]];//发送段码
  246.         }
  247.         if(Time_Count%2==1)
  248.         {
  249.                 P0=0xff;//消隐
  250.         }
  251.         Time_Count++;
  252. }
  253. /*******************************************************************************
  254. * 函 数 名         : void Timer1() interrupt 3
  255. * 函数功能                   : 定时器1中断函数
  256. * 输    入         : 无
  257. * 输    出         : 无
  258. *******************************************************************************/
  259. void Timer1() interrupt 3
  260. {
  261.         TH1=0xBB;           //定时15ms
  262.         TL1=0xa4;
  263.         if(Set_Mode==0)                                        //模式0:显示当前为温度
  264.         {        
  265.                 Temp=DS18B20_ReadTemp();          //读取温度值
  266.                  Temp_T(Temp);                                   //温度转换
  267.         }
  268.         if(Set_Mode==1)                                        //模式1:显示温度上限
  269.                 Temp_T(TH);
  270.         if(Set_Mode==2)                                        //模式2:显示温度下限
  271.                 Temp_T(TL);
  272.                 Time_Count=0;
  273. }
复制代码
DS18B20.c

  1. /******************************************************************************
  2. *文件描述:DS18B20温度传感器驱动文件
  3. *作    者:Xiaoyang
  4. *时    间:2021.05.30
  5. *******************************************************************************/
  6. #include"DS18B20.h"
  7. /*******************************************************************************
  8. * 函数名         : Delay1ms
  9. * 函数功能                 : 延时函数
  10. * 输入           : 无
  11. * 输出                  : 无
  12. *******************************************************************************/
  13. void Delay1ms(unsigned int y)
  14. {
  15.         unsigned int x;
  16.         for(y;y>0;y--)
  17.                 for(x=110;x>0;x--);
  18. }
  19. /*******************************************************************************
  20. * 函数名         : DS18B20_Init
  21. * 函数功能                 : 初始化
  22. * 输入           : 无
  23. * 输出                  : 初始化成功返回1,失败返回0
  24. *******************************************************************************/
  25. unsigned char DS18B20_Init()
  26. {
  27.         unsigned int i;
  28.         DQ=0;                         //将总线拉低480us~960us
  29.         i=60;        
  30.         while(i--);//延时642us
  31.         DQ=1;                        //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
  32.         i=0;
  33.         while(DQ)        //等待DS18B20拉低总线
  34.         {
  35.                 i++;
  36.                 if(i>5000)//等待>5MS
  37.                         return 0;//初始化失败        
  38.         }
  39.         return 1;//初始化成功
  40. }
  41. /*******************************************************************************
  42. * 函数名         : DS18B20_WriteByte
  43. * 函数功能                 : 向18B20写入一个字节
  44. * 输入           : dat:写入的字节
  45. * 输出                  : 无
  46. *******************************************************************************/
  47. void DS18B20_WriteByte(unsigned char dat)
  48. {
  49.         unsigned int i,j;
  50.         for(j=0;j<8;j++)
  51.         {
  52.                 DQ=0;                        //每写入一位数据之前先把总线拉低1us
  53.                 i++;
  54.                 DQ=dat&0x01; //然后写入一个数据,从最低位开始
  55.                 i=7;
  56.                 while(i--); //延时68us,持续时间最少60us
  57.                 DQ=1;        //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
  58.                 dat>>=1;
  59.         }
  60. }
  61. /*******************************************************************************
  62. * 函数名         : DS18B20_ReadByte
  63. * 函数功能                 : 读取一个字节
  64. * 输入           : 无
  65. * 输出                  : 读取的字节
  66. *******************************************************************************/
  67. unsigned char DS18B20_ReadByte(void)
  68. {
  69.         unsigned char byte,bi;
  70.         unsigned int i,j;        
  71.         for(j=8;j>0;j--)
  72.         {
  73.                 DQ=0;//先将总线拉低1us
  74.                 i++;
  75.                 DQ=1;//然后释放总线
  76.                 i++;
  77.                 i++;//延时6us等待数据稳定
  78.                 bi=DQ;         //读取数据,从最低位开始读取
  79.                 /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/
  80.                 byte=(byte>>1)|(bi<<7);                                                  
  81.                 i=4;                //读取完之后等待48us再接着读取下一个数
  82.                 while(i--);
  83.         }                                
  84.         return byte;
  85. }
  86. /*******************************************************************************
  87. * 函数名         : DS18B20_ChangTemp
  88. * 函数功能                 : 让18b20开始转换温度
  89. * 输入           : 无
  90. * 输出                  : 无
  91. *******************************************************************************/
  92. void  DS18B20_ChangTemp(void)
  93. {
  94.         DS18B20_Init();
  95.         Delay1ms(1);
  96.         DS18B20_WriteByte(0xcc);                //跳过ROM操作命令                 
  97.         DS18B20_WriteByte(0x44);            //温度转换命令
  98. }
  99. /*******************************************************************************
  100. * 函数名         : DS18B20_ReadTempCom
  101. * 函数功能                 : 发送读取温度命令
  102. * 输入           : 无
  103. * 输出                  : 无
  104. *******************************************************************************/
  105. void DS18B20_ReadTempCom(void)
  106. {        
  107.         DS18B20_Init();
  108.         Delay1ms(1);
  109.         DS18B20_WriteByte(0xcc);         //跳过ROM操作命令
  110.         DS18B20_WriteByte(0xbe);         //发送读取温度命令
  111. }
  112. /*******************************************************************************
  113. * 函数名         : DS18B20_ReadTemp
  114. * 函数功能                 : 读取温度
  115. * 输入           : 无
  116. * 输出                  : 温度值
  117. *******************************************************************************/
  118. float DS18B20_ReadTemp(void)
  119. {
  120.         int temp=0;
  121.         float temp1;
  122.         unsigned char tmh,tml;
  123.         DS18B20_ChangTemp();                //先写入转换命令
  124.         DS18B20_ReadTempCom();                //然后等待转换完后发送读取温度命令
  125.         tml=DS18B20_ReadByte();                //读取温度值共16位,先读低字节
  126.         tmh=DS18B20_ReadByte();                //再读高字节
  127.         temp=tmh;
  128.         temp<<=8;
  129.         temp|=tml;
  130.         if (temp<0)                 //温度为负数
  131.         {               
  132.                 temp = temp-1;
  133.                 temp1 =~temp;
  134.                 temp1 =-temp1*0.0625-0.005;
  135.         }
  136.         else
  137.         {
  138.                 temp1 = temp;
  139.                 temp1 = temp1*0.0625+0.005;
  140.         }
  141.         return temp1;        
  142. }
复制代码
KEY.C

  1. /******************************************************************************
  2. *文件描述:按键驱动文件
  3. *******************************************************************************/
  4. #include<reg52.h>
  5. #include "key.h"
  6. #include "delay.h"

  7. /*******************************************************************************
  8. * 函 数 名         : Key_Check()
  9. * 函数功能                   : 检测有独立按键按下并读取键值
  10. * 输    入         : 无
  11. * 输    出         : KeyValue:按键值,无按键按下返回0
  12. *******************************************************************************/
  13. uchar Key_Check(void)
  14. {
  15.         uchar KeyValue=0;                                //按键值初始化为0
  16.         if((GPIO_KEY&0x0f)!=0x0f)            //读取高4位,判断按键是否按下
  17.         {
  18.                 Delay_Ms(10);                    //延时10ms进行消抖
  19.                 if((GPIO_KEY&0x0f)!=0x0f)        //再次检测键盘是否按下
  20.                 {
  21.                         switch(GPIO_KEY&0x0f)
  22.                         {
  23.                                 case(0x0e): KeyValue=1; break;
  24.                                 case(0x0d): KeyValue=2; break;
  25.                                 case(0x0b): KeyValue=3; break;
  26.                                 case(0x07): KeyValue=4; break;
  27.                         }
  28.                 }
  29.         }
  30.         return KeyValue;
  31. }
复制代码
主要代码都在上面,拒绝白嫖,就不上传附件了,欢迎各位大佬留言。

评分

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

查看全部评分

回复

使用道具 举报

ID:262 发表于 2022-3-19 04:16 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:1002955 发表于 2022-3-19 07:43 | 显示全部楼层
为啥我的只能用扬声器发声http://www.51hei.com/bbs/dpj-218190-1.html
回复

使用道具 举报

ID:161164 发表于 2022-3-19 14:31 | 显示全部楼层
在定时中断中读温度不太好吧?
这里起码耗掉几个ms吧?
回复

使用道具 举报

ID:856329 发表于 2022-3-19 14:59 | 显示全部楼层
lkc8210 发表于 2022-3-19 14:31
在定时中断中读温度不太好吧?
这里起码耗掉几个ms吧?

十几个ms,不影响数码管显示,目前没有其他好方法,放在主函数中一直刷会被定时器打断,测温读数乱码。
回复

使用道具 举报

ID:161164 发表于 2022-3-19 15:17 | 显示全部楼层
Lxy18 发表于 2022-3-19 14:59
十几个ms,不影响数码管显示,目前没有其他好方法,放在主函数中一直刷会被定时器打断,测温读数乱码。

DS18B20的初始化和读写可以分9步来完成
每步只耗600~700us
步与步之间可以干其它事情


  1. typedef         unsigned char        u8;  //0 to 255
  2. typedef         unsigned int        u16;  //0 to 65535

  3. u16 Ds18b20ReadTemp()//放在while(1)中呼叫
  4. {
  5.     static u8 step = 0, tml = 0, tmh = 0;
  6.     u16 temp = 0;
  7.     if(!Delayms_Ds18b20)
  8.     {
  9.         TMR_x10 = 1;//Delayms_Ds18b20每1ms减1
  10.         Delayms_Ds18b20 = 2;//if(Delayms_Ds18b20)Delayms_Ds18b20--;<<放到1ms中断中
  11.         switch(step)
  12.         {
  13.                                         case 0:Ds18b20Init();break;
  14.                                         case 1:Ds18b20WriteByte(0xcc);break;
  15.                                         case 2:Ds18b20WriteByte(0x44);break;
  16.                                         case 3:Ds18b20Init();break;
  17.                                         case 4:Ds18b20WriteByte(0xcc);break;
  18.                                         case 5:Ds18b20WriteByte(0xbe);break;
  19.                                         case 6:tml = Ds18b20ReadByte();break;
  20.                                         case 7:tmh = Ds18b20ReadByte();break;
  21.                                         case 8:
  22.                                                         temp = tmh;
  23.                                                         temp <<= 8;
  24.                                                         temp |= tml;
  25.                                                         tml = 0;
  26.                                                         tmh = 0;
  27.                                                         break;
  28.                                         default:
  29.                                                         Delayms_Ds18b20 = 25;
  30.                                                         TMR_x10 = 0;//Delayms_Ds18b20每10ms减1
  31.                                                         break;
  32.         }
  33.         step = ++step % 10;
  34.     }
  35.     return temp;
  36. }
复制代码
回复

使用道具 举报

ID:941265 发表于 2022-3-21 19:11 | 显示全部楼层
好资料,51黑有你更精彩!!!
回复

使用道具 举报

ID:992677 发表于 2022-12-9 17:07 | 显示全部楼层
大佬,delay的代码没有啊
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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