标题: 基于51单片机的温度报警系统设计 [打印本页]
作者: Lxy18 时间: 2022-3-18 10:19
标题: 基于51单片机的温度报警系统设计
设计中有很多不完善的地方,欢迎各位大佬指正。 演示视频: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℃。
主函数 单片机代码如下:
- /******************************************************************************
- * 单片机温度报警系统
- *******************************************************************************/
- #include <reg52.h>
- #include "delay.h"
- #include "key.h"
- #include "DS18B20.h"
- #define uchar unsigned char //对数据类型定义
- #define uint unsigned int
- /****************************端口定义******************************************/
- sbit D1=P2^4;
- sbit D2=P2^6;
- sbit D3=P2^5;
- sbit D4=P2^7;
-
- sbit Beep=P1^6; //蜂鸣器
- sbit LED_G=P1^2; //绿色LED端口
- sbit LED_B=P1^0; //蓝色LED端口
- sbit LED_R=P1^1; //红色LED端口
- /****************************定义变量******************************************/
- uchar KeyValve=0; //按键值
- float Temp=20.0; //温度变量
- float TH=30.0; //温度上限
- float TL=22.0; //温度下限
- uint Time_Count=1; //定时器0中断次数
- uchar Temp_Str[4]; //数组变量存放温度数据
- uchar Set_Mode=0; //设置模式
- uchar SMG_Data[4]={0,0,0,0}; //存放数码管的各个位的值
- uchar code smgduan[]={ //共阳极数码管段码
- 0xc0, //0,0
- 0xf9, //1,1
- 0xa4, //2,2
- 0xb0, //3,3
- 0x99, //4,4
- 0x92, //5,5
- 0x82, //6,6
- 0xf8, //7,7
- 0x80, //8,8
- 0x90, //9,9
- 0x88, //10,A
- 0x83, //11,b
- 0xc6, //12,C
- 0xa1, //13,d
- 0x86, //14,E
- 0x8e, //15,F
- 0xff, //16,
- 0xbf, //17,
- 0x89, //18,H
- 0xc7 //19,L
- };
- /*****************************************************************************/
- /***************************函数声明******************************************/
- void Timer_Init(); //定时器初始化
- void Temp_T(float t); //温度转换函数
- /******************************************************************************
- * 函 数 名 : 主函数
- * 函数功能 :
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void main()
- {
- DS18B20_Init(); //温度传感器初始化
- Timer_Init(); //定时器初始化
- Delay_Ms(100);
- while(1)
- {
- /***********按键扫描程序**************/
- KeyValve=Key_Check(); //扫描按键
- if(KeyValve!=0) //判断按键是否按下
- {
- switch(KeyValve) //判断按键值,并处理
- {
- case 1: //温度上限/下限设置
- {
- if(Set_Mode<2)
- Set_Mode++;
- else
- Set_Mode=0;
- Delay_Ms(200);
- }
- break;
- case 2: //按键加
- {
- if((Set_Mode==1)&&(TH<128.0)) //限制温度上限小于128℃
- TH=TH+1.0; //温度上限加一
- if((Set_Mode==2)&&(TL<TH)) //限制温度下限小于温度上限
- TL=TL+1.0; //温度下限加一
- Delay_Ms(200);
- }
- break;
- case 3: //按键减
- {
- if((Set_Mode==1)&&(TH>TL)) //限制温度上限大于温度下限
- TH=TH-1.0; //温度上限减一
- if((Set_Mode==2)&&(TL>-55.0)) //限制温度下限大于-55℃
- TL=TL-1.0; //温度下限减一
- Delay_Ms(200);
- }
- break;
- }
- }
- /***********温度上下限判断报警程序**************/
- if(Set_Mode==0)
- {
- if(Temp>TH)
- {
- LED_R=0; //红灯点亮
- LED_B=1; //蓝灯熄灭
- LED_G=1;
- Beep=0; //蜂鸣器报警
- }
- else if(Temp<TL)
- {
- LED_R=1; //红灯熄灭
- LED_B=0; //蓝灯点亮
- LED_G=1;
- Beep=0; //蜂鸣器报警
- }
- else
- {
- LED_R=1; //红灯熄灭
- LED_B=1; //蓝灯熄灭
- LED_G=0;
- Beep=1;
- }
- }
- else
- Beep=1;
- }
- }
- /*******************************************************************************
- * 函 数 名 : Temp_T(float t)
- * 函数功能 : 温度转换函数:将温度值放到数组中,便于显示
- * 输 入 : t
- * 输 出 : 无
- *******************************************************************************/
- void Temp_T(float t)
- {
- if(Set_Mode==0)
- {
- t=t*10.0; //放大十倍
- if(t>=0) //正温度
- {
- if(((int)t/1000)==0)
- SMG_Data[0]=16;
- else
- SMG_Data[0]=(int)t/1000; //提取温度百、十、个位
- SMG_Data[1]=((int)t%1000)/100;
- SMG_Data[2]=((int)t%100)/10;
- SMG_Data[3]=(int)t%10;
- }
- else //负温度
- {
- t=-t; //将负数转换为正数
- SMG_Data[0]=17; //显示“—”号
- SMG_Data[1]=(int)t/100; //提取温度个、十位
- SMG_Data[2]=((int)t%100)/10;
- SMG_Data[3]=(int)t%10;
- }
- }
- else
- {
- if(Set_Mode==1)
- SMG_Data[0]=18; //数码管第一位显示H
- if(Set_Mode==2)
- SMG_Data[0]=19; //数码管第一位显示L
- if(t>=0) //正温度
- {
- SMG_Data[1]=(int)t/100; //提取温度百、十、个位
- SMG_Data[2]=((int)t%100)/10;
- SMG_Data[3]=(int)t%10;
- }
- else //负温度
- {
- t=-t; //将负数转换为正数
- SMG_Data[1]=17; //显示“—”号
- SMG_Data[2]=((int)t%100)/10; //提取温度个、十位
- SMG_Data[3]=(int)t%10;
- t=-t; //将温度恢复
- }
- }
- }
- /*****************************************************************************
- * 函 数 名 : Timer_Init
- * 函数功能 : 定时器初始化
- * 输 入 : 无
- * 输 出 : 无
- *****************************************************************************/
- void Timer_Init()
- {
- TMOD=0x11; //打开定时器0,工作方式1。
- TH0=0xff; //给定时器0赋初值,定时200us (65536-200)/256 (65536-200)%256
- TL0=0x38;
- TH1=0xc5; //定时60ms
- TL1=0x68;
- ET0=1; //打开定时器0中断允许
- ET1=1; //打开定时器1中断允许
- TR0=1; //打开定时器0
- TR1=1; //打开定时器1
- PT1=1; //高优先级
- EA=1; //打开总中断
- }
- /*******************************************************************************
- * 函 数 名 : void Timer0() interrupt 1
- * 函数功能 : 定时器0中断函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void Timer0() interrupt 1
- {
- TH0=0xff; //给定时器赋初值,定时
- TL0=0x38;
- if(Time_Count%2==0)
- {
- switch(Time_Count%8) //位选,选择点亮的数码管,
- {
- case(0):
- D1=0;
- D2=1;
- D3=1;
- D4=1;
- break;//显示第0位
- case(2):
- D1=1;
- D2=0;
- D3=1;
- D4=1;
- break;//显示第1位
- case(4):
- D1=1;
- D2=1;
- D3=0;
- D4=1;
- break;//显示第2位
- case(6):
- D1=1;
- D2=1;
- D3=1;
- D4=0;
- break;//显示第3位
- }
- if((Set_Mode==0)&&(Time_Count%8==4))
- P0=smgduan[SMG_Data[(Time_Count%8)/2]]-0x80;//显示小数点
- P0=smgduan[SMG_Data[(Time_Count%8)/2]];//发送段码
- }
- if(Time_Count%2==1)
- {
- P0=0xff;//消隐
- }
- Time_Count++;
- }
- /*******************************************************************************
- * 函 数 名 : void Timer1() interrupt 3
- * 函数功能 : 定时器1中断函数
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void Timer1() interrupt 3
- {
- TH1=0xBB; //定时15ms
- TL1=0xa4;
- if(Set_Mode==0) //模式0:显示当前为温度
- {
- Temp=DS18B20_ReadTemp(); //读取温度值
- Temp_T(Temp); //温度转换
- }
- if(Set_Mode==1) //模式1:显示温度上限
- Temp_T(TH);
- if(Set_Mode==2) //模式2:显示温度下限
- Temp_T(TL);
- Time_Count=0;
- }
复制代码 DS18B20.c
KEY.C
- /******************************************************************************
- *文件描述:按键驱动文件
- *******************************************************************************/
- #include<reg52.h>
- #include "key.h"
- #include "delay.h"
- /*******************************************************************************
- * 函 数 名 : Key_Check()
- * 函数功能 : 检测有独立按键按下并读取键值
- * 输 入 : 无
- * 输 出 : KeyValue:按键值,无按键按下返回0
- *******************************************************************************/
- uchar Key_Check(void)
- {
- uchar KeyValue=0; //按键值初始化为0
- if((GPIO_KEY&0x0f)!=0x0f) //读取高4位,判断按键是否按下
- {
- Delay_Ms(10); //延时10ms进行消抖
- if((GPIO_KEY&0x0f)!=0x0f) //再次检测键盘是否按下
- {
- switch(GPIO_KEY&0x0f)
- {
- case(0x0e): KeyValue=1; break;
- case(0x0d): KeyValue=2; break;
- case(0x0b): KeyValue=3; break;
- case(0x07): KeyValue=4; break;
- }
- }
- }
- return KeyValue;
- }
复制代码 主要代码都在上面,拒绝白嫖,就不上传附件了,欢迎各位大佬留言。
作者: heicad 时间: 2022-3-19 04:16
好资料,51黑有你更精彩!!!
作者: 1276327078 时间: 2022-3-19 07:43
为啥我的只能用扬声器发声http://www.51hei.com/bbs/dpj-218190-1.html
作者: lkc8210 时间: 2022-3-19 14:31
在定时中断中读温度不太好吧?
这里起码耗掉几个ms吧?
作者: Lxy18 时间: 2022-3-19 14:59
十几个ms,不影响数码管显示,目前没有其他好方法,放在主函数中一直刷会被定时器打断,测温读数乱码。
作者: lkc8210 时间: 2022-3-19 15:17
DS18B20的初始化和读写可以分9步来完成
每步只耗600~700us
步与步之间可以干其它事情
- typedef unsigned char u8; //0 to 255
- typedef unsigned int u16; //0 to 65535
- u16 Ds18b20ReadTemp()//放在while(1)中呼叫
- {
- static u8 step = 0, tml = 0, tmh = 0;
- u16 temp = 0;
- if(!Delayms_Ds18b20)
- {
- TMR_x10 = 1;//Delayms_Ds18b20每1ms减1
- Delayms_Ds18b20 = 2;//if(Delayms_Ds18b20)Delayms_Ds18b20--;<<放到1ms中断中
- switch(step)
- {
- case 0:Ds18b20Init();break;
- case 1:Ds18b20WriteByte(0xcc);break;
- case 2:Ds18b20WriteByte(0x44);break;
- case 3:Ds18b20Init();break;
- case 4:Ds18b20WriteByte(0xcc);break;
- case 5:Ds18b20WriteByte(0xbe);break;
- case 6:tml = Ds18b20ReadByte();break;
- case 7:tmh = Ds18b20ReadByte();break;
- case 8:
- temp = tmh;
- temp <<= 8;
- temp |= tml;
- tml = 0;
- tmh = 0;
- break;
- default:
- Delayms_Ds18b20 = 25;
- TMR_x10 = 0;//Delayms_Ds18b20每10ms减1
- break;
- }
- step = ++step % 10;
- }
- return temp;
- }
复制代码
作者: adad2 时间: 2022-3-21 19:11
好资料,51黑有你更精彩!!!
作者: 小灰灰、 时间: 2022-12-9 17:07
大佬,delay的代码没有啊
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |