基于51单片机的温度测量报警系统的设计与制作

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、实习目的
  • 二、实习任务
    • [2.1 设计温度测量报警系统硬件电路](#2.1 设计温度测量报警系统硬件电路)
    • [2.2 温度测量报警系统软件编程、仿真与调试;](#2.2 温度测量报警系统软件编程、仿真与调试;)
    • [2.3 完成温度测量报警系统的实物制作与调试;](#2.3 完成温度测量报警系统的实物制作与调试;)
  • [三、 实习内容及实习成果](#三、 实习内容及实习成果)
    • [3.1 温度测量报警系统的功能要求](#3.1 温度测量报警系统的功能要求)
    • [3.2 温度测量报警系统的设计方法](#3.2 温度测量报警系统的设计方法)
  • [3.3 温度测量报警系统的设计过程](#3.3 温度测量报警系统的设计过程)
    • [3.3.1 proteus仿真原理图](#3.3.1 proteus仿真原理图)
    • [3.3.2 程序设计](#3.3.2 程序设计)
  • [3.4 温度测量报警系统的实习成果](#3.4 温度测量报警系统的实习成果)
    • [3.4.1 仿真结果](#3.4.1 仿真结果)
    • [3.4.2 实物结果](#3.4.2 实物结果)
  • 四、总结
  • 实验参考资料(gitee)

前言

该系统通过使用keil5和Proteus软件,最终在硬件上实现一个温度检测报警的小项目(只使用Proteus进行模拟仿真也是可以实现的)


提示:以下是本篇文章正文内容,下面案例可供参考

一、实习目的

1、 掌握51单片机应用编程及调试;

2、 掌握Proteus电路图设计与仿真;

3、 掌握数字温度传感器DS18B20的使用;

4、 掌握单总线协议的基本特点及通信过程,并掌握单片机IO端口模拟单总线时序控制程序;

5、 培养综合运用知识的能力和工程设计的能力。

二、实习任务

2.1 设计温度测量报警系统硬件电路

(1) 进行元器件正确选型;

(2) 在proteus中完成各模块电路和系统电路的设计;

(3) 在Proteus中进行电路仿真与测试;

2.2 温度测量报警系统软件编程、仿真与调试;

(1) 基于Keil完成温度计测量、显示、报警和上下限设定等功能的实现;

(2) 进行软件仿真与调试;

2.3 完成温度测量报警系统的实物制作与调试;

(1)进行温度计的实物焊接;

(2)实际测试,并最终调试完成作品。

三、 实习内容及实习成果

3.1 温度测量报警系统的功能要求

单片机通过实时检测温度传感器DS18B20芯片的状态,并将DS18B20芯片得到的数据进行处理。上电之后数码管显示当前的环境温度,并且蜂鸣器响一下,提示开机。S1作为复位按键,S2和S3作为温度调整按键,S4作为模式选择按键,按下之后可以选择调整温度上限H或者下限L,第三次按下时,数码管恢复显示实时温度。当检测到的温度高于或者低于设置的报警值的时候,蜂鸣器报警同时报警灯闪烁,温度检测精确到0.1度。数据保存在单片机内部EEPOM中。

3.2 温度测量报警系统的设计方法

首先对于以下六个模块进行proteus硬件设计。在硬件原理图完成之后,按照模块进行软件设计。软件设计之后,将程序加载到proteus中进行模拟仿真,测试程序是否能够正常实现所预期功能。实现预期功能之后,就可以进行实物焊接,最后将程序烧录进实物中,再次进行调试。最终达到预期目标。

3.3 温度测量报警系统的设计过程

3.3.1 proteus仿真原理图

3.3.2 程序设计

c 复制代码
#include <REGX52.h>	         //调用单片机头文件
#define uint unsigned int
typedef unsigned char uchar;
uint Sign_Negative = 0; //默认为正数

//数码管段选定义      0     1    2    3    4    5	6	 7	  8	   9	H     L
uchar code smg_du[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x89,0xC7};	 //段码

//数码管位选定义
uchar code smg_we[]={0x10,0x20,0x40,0x80};
uchar dis_smg[4] = {0};	

sbit DQ   = P2^4;	//18b20 IO口的定义
sbit beep = P2^3;   //蜂鸣器IO口定义

uint temperature ;  //
bit flag_300ms=1 ;
uchar menu_1;       //菜单设计的变量
uint t_high = 450,t_low = 150;	   //温度上下限报警值 

/***********************1ms延时函数*****************************/
void delay_1ms(uint q)
{
	uint i,j;
	for(i=0;i<q;i++)
		for(j=0;j<120;j++);
}

/***********************小延时函数*****************************/
void delay_uint(uint q)
{
	while(q--);
}


/***********************数码显示函数*****************************/
void display()
{
	static uchar i;   
	i++;
	if(i >= 4)
		i = 0;	
	P1 = 0xff;			     //消隐 
	P3 = smg_we[i];	 		 //位选
	P1 = dis_smg[i];		 //段选	 	
}



/***********************18b20初始化函数*****************************/
void init_18b20()
{
	bit q;
	DQ = 1;				//把总线拿高
	delay_uint(1);	   
	DQ = 0;				//给复位脉冲
	delay_uint(80);		 
	DQ = 1;				//把总线拿高 等待
	delay_uint(10);	 
	q = DQ;				//读取18b20初始化信号
	delay_uint(20);		 
	DQ = 1;				//把总线拿高 释放总线
}

/*************写18b20内的数据***************/
void write_18b20(uchar dat)
{
	uchar i;
	for(i=0;i<8;i++)
	{					 //写数据是低位开始
		DQ = 0;			 //把总线拿低写时间隙开始 
		DQ = dat & 0x01; //向18b20总线写数据了
		delay_uint(5); 	  
		DQ = 1;			 //释放总线
		dat >>= 1;
	}	
}

/*************读取18b20内的数据***************/
uchar read_18b20()
{
	uchar i,value;
	for(i=0;i<8;i++)
	{
		DQ = 0;			 //把总线拿低读时间隙开始 
		value >>= 1;	 //读数据是低位开始
		DQ = 1;			 //释放总线
		if(DQ == 1)		 //开始读写数据 
			value |= 0x80;
		delay_uint(5);	  
	}
	return value;		 //返回数据
}

/*************读取温度的值 读出来的是小数***************/
uint read_temp()
{
    uint wendu = 0;
	uchar low = 0;
	uchar high = 0;
	init_18b20();
	write_18b20(0xcc);	   //跳过64位ROM
	write_18b20(0x44);	   //启动一次温度转换命令
	delay_uint(50);
	init_18b20();		   //初始化18b20
	write_18b20(0xcc);	   //跳过64位ROM
	write_18b20(0xbe);	   //发出读取暂存器命令
	low = read_18b20();
	high = read_18b20();
	wendu = high;
	wendu <<= 8;
	wendu |= low;
	if(wendu & 2048)
	{
		Sign_Negative = 1;
		wendu = ~wendu + 1;
	} else {
		Sign_Negative = 0;
	}
	wendu = wendu * 0.0625;
	wendu = wendu*10 + 0.5;
	
	return wendu;		   //返回读出的温度 带小数
}

/*************定时器0初始化程序***************/
void time_init()	  
{
	EA   = 1;	 	  //开总中断
	TMOD = 0X01;	  //定时器0、定时器1工作方式1
	ET0  = 1;		  //开定时器0中断 
	TR0  = 1;		  //允许定时器0定时
}

/********************独立按键程序*****************/
uchar key_can;	 //按键值

void key()	 //独立按键程序
{
 	key_can = 0;                   //按键值还原
	if((P2 & 0x07) != 0x07)		//按键按下
	{
 		delay_1ms(10);	     	//按键消抖动
		if((P2 & 0x07) != 0x07)
		{						//确认是按键按下
 			switch(P2 & 0x07)
			{
				case 0x06: key_can = 3; break;	   //得到k3键值
				case 0x05: key_can = 2; break;	   //得到k2键值
				case 0x03: key_can = 1; break;	   //得到k1键值
			}
 		}	
		while ((P2 & 0x07)!= 0X07);   //松手检测		
	}
}

/****************按键处理数码管显示函数***************/
void key_with()
{
	if(key_can == 1)	  //设置键
	{
		menu_1 ++;
		if(menu_1 >= 3)
		{
			menu_1 = 0;
 		}
	}
	if(menu_1 == 1)			//设置高温报警
	{
 		if(key_can == 2)
		{
 			t_high ++ ;		//温度上限值加1
 			if(t_high > 990)
				t_high = 990;
		}
		if(key_can == 3)
		{
 			t_high -- ;		//温度上限值减1
 			if(t_high <= t_low)
				t_high = t_low + 1;
		}
		dis_smg[3] = smg_du[t_high % 10];	           //取小数显示
		dis_smg[2] = smg_du[t_high / 10 % 10];  //取个位显示
		dis_smg[2] &= 0x7f;
		dis_smg[1] = smg_du[t_high / 100 % 10] ;	   //取十位显示
		dis_smg[0] = smg_du[10];	 //H
	}	
	if(menu_1 == 2)			//设置低温报警
	{
 		if(key_can == 2)
		{
 			t_low ++ ;		    	//温度下限值加1
 			if(t_low >= t_high)
				t_low = t_high - 1;
		}
		if(key_can == 3)
		{
 				t_low -- ;	    	//温度下限值减1
 			if(t_low <= 1)
				t_low = 1;
		}
		dis_smg[3] = smg_du[t_low % 10];	           //取小数显示
		dis_smg[2] = smg_du[t_low / 10 % 10];          //取个位显示
		dis_smg[2] &= 0x7f;
		dis_smg[1] = smg_du[t_low / 100 % 10];	       //取十位显示
		dis_smg[0] = smg_du[11];	  //L
	}	
	delay_1ms(150);	 
}  

/****************报警函数***************/
void clock_h_l()
{
 	if((temperature <= t_low) || (temperature >= t_high))
	{
 		beep = !beep; 	  //蜂鸣器报警			
 	}
	else
	{
		beep = 1;	
	}			
}

sbit P27 = P2^7;//测试探针

/****************主函数***************/
void main()
{
	beep = 0;		                //开机叫一声   
	delay_1ms(150);
	beep = 1;                       // 响完停止,判断温度在决定是否响
	P0 = P1 = P2 = P3 = 0xff;
	time_init();                    //初始化定时器 
	while(1)
	{		
		key();					//按键程序
		if(key_can != 0)
		{
			key_with();			//设置报警温度	
		}
		if(flag_300ms == 1)	    //300ms 处理一次温度程序
		{	   
		
			flag_300ms = 0;	
			temperature = read_temp();	//先读出温度的值
			clock_h_l();                //报警函数
			if(menu_1 == 0)
			{	
 				dis_smg[3] = smg_du[temperature % 10];	 //取温度的小数显示
				dis_smg[2] = smg_du[temperature / 10 % 10]; //取温度的个位显示
				dis_smg[2] &= 0x7f;//显示小数点 
				dis_smg[0] = dis_smg[1] = 0xFF;
 				if (temperature >= 100 && temperature < 1000)//当温度处于>=10  && <100 
				{
					dis_smg[1] = smg_du[temperature / 100 % 10];	   //取温度的十位显示	
				    if (Sign_Negative) {//如果是负数就加负号
                        dis_smg[0] = 0xBF;
		            }	
				} else {//当fabs(温度)  小于10
                    if (Sign_Negative) {//如果是负数就加负号
                        dis_smg[1] = 0xBF;
		            }	
				}					
			}
		}	
	}
}

/*************定时器0中断服务程序***************/
void time0_int() interrupt 1
{	
	static uchar value;			 //定时2ms中断一次
	TH0 = 0xf8;
	TL0 = 0x30;     //2ms
	display();		//数码管显示函数
	value++;	  
	if(value >= 150)
	{
		value = 0;	  
		flag_300ms = 1;
	}
}

3.4 温度测量报警系统的实习成果

3.4.1 仿真结果

3.4.2 实物结果

四、总结

本次实验遇到三个问题。第一个问题:数码管不能正确显示数字。最后发现,是码表与数码管不匹配造成的。在我完修改码表之后,问题得到解决。第二个问题:在于温度转换的计算。我一直算出来的值,与标准值0.0625差距很大。最后通过老师的讲解,发现自己进制没有转换对,导致自己算出来的值不对。第三问题:当我按下按键之后,温度调整太快。最后我通过给按键处理数码管显示函数加入松手检测程序,从而解决了这个问题。设计的不足之处:按一下每次只能加减0.1的数值。设置的温差如果小,按下的次数还比较轻松。倘若要调节10度,那就要按下100次。这个着实让人头疼。因此,我又给它加入了一个延时函数。倘若按下的时间超过2ms,那么设置的温度上限,就会快速增加。减也是如此。我思考之后,发现非常的合理,最后通过修改代码,成功完成这个按键模块的优化。

实验参考资料(gitee)

程序和代码: https://gitee.com/shiguangliushui/Temperature-measurement-alarm-system.git

相关推荐
云伴枫轻舞4 分钟前
我对 OTA 的理解随记,附GD32/STM32例程
stm32·单片机·嵌入式硬件
Aczone281 小时前
硬件(五) 存储、ARM 架构与指令系统
arm开发·嵌入式硬件·架构
LS·Cui1 小时前
单片机按键示例功能
单片机
【ql君】qlexcel1 小时前
MCU上电到运行的全过程
单片机·嵌入式硬件·mcu·启动过程
搞一搞汽车电子2 小时前
S32K3平台eMIOS 应用说明
开发语言·驱动开发·笔记·单片机·嵌入式硬件·汽车
pQAQqa2 小时前
FreeRTOS项目(2)摇杆按键检测
stm32·单片机·嵌入式硬件·freertos
小莞尔3 小时前
【51单片机】【protues仿真】基于51单片机停车场的车位管理系统
c语言·开发语言·单片机·嵌入式硬件·51单片机
一川月白7094 小时前
51单片机---硬件学习(跑马灯、数码管、外部中断、按键、蜂鸣器)
单片机·学习·51单片机·外部中断·蜂鸣器·数码管·跑马灯
月阳羊5 小时前
【硬件-笔试面试题-69】硬件/电子工程师,笔试面试题(知识点:电机驱动电路的反馈电路)
java·经验分享·嵌入式硬件·面试
weixin_468466857 小时前
树莓派32位与64位系统安装teamviewer远程软件
linux·单片机·自动化·树莓派·远程控制·vnc·teamviewer