AT89C52项目:DS18B20温度报警器

2024-03-26 04:36

本文主要是介绍AT89C52项目:DS18B20温度报警器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

源码在这里,需要自取:

13.2 DS18B20温度报警器 · 钦某/51project - 码云 - 开源中国 (gitee.com)

先看演示视频:

51温度报警演示视频

我们先来了解DS18B20

我们看到总共有三个接口,gnd是接地,vcc接5v。在DS18B20手册上Vcc标的是Vdd。

中间的接口是传输数据的线。单总线,异步,半双工,单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电(由通信线提供电压,主机配一个强上拉电路)时还可以省去VDD线路,此时,供电加通信只需要两根线。(51单片机不采取这种做法)

初始化:主机将总线拉低至少480us然后释放总线,等待15~60us后,从机会拉低总线60~240us响应主机,之后从机释放总线。

发送一位: 主机将总线拉低60~120us,然后释放总线,表示发送0然后释放总线,表示发送1。从机将在总主机将总线拉低1~15us,(典型值)线拉低30us后读取电平,整个时间片应大于60us

接收一位:主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1,整个时间片应大于60us

 之后就将上面两个步骤走8次,就可以封装出两个函数:发送一个字节和接受一个字节。

#include <REGX52.H>//引脚定义
sbit OneWire_DQ=P3^7;/*** @brief  单总线初始化* @param  无* @retval 从机响应位,0为响应,1为未响应*/
unsigned char OneWire_Init(void)
{unsigned char i;unsigned char AckBit;EA=0;OneWire_DQ=1;OneWire_DQ=0;i = 247;while (--i);		//Delay 500usOneWire_DQ=1;i = 32;while (--i);			//Delay 70usAckBit=OneWire_DQ;i = 247;while (--i);		//Delay 500usEA=1;return AckBit;
}/*** @brief  单总线发送一位* @param  Bit 要发送的位* @retval 无*/
void OneWire_SendBit(unsigned char Bit)
{unsigned char i;EA=0;OneWire_DQ=0;i = 4;while (--i);			//Delay 10usOneWire_DQ=Bit;i = 24;while (--i);			//Delay 50usOneWire_DQ=1;EA=1;
}/*** @brief  单总线接收一位* @param  无* @retval 读取的位*/
unsigned char OneWire_ReceiveBit(void)
{unsigned char i;unsigned char Bit;EA=0;OneWire_DQ=0;i = 2;while (--i);			//Delay 5usOneWire_DQ=1;i = 2;while (--i);			//Delay 5usBit=OneWire_DQ;i = 24;while (--i);			//Delay 50usEA=1;return Bit;
}/*** @brief  单总线发送一个字节* @param  Byte 要发送的字节* @retval 无*/
void OneWire_SendByte(unsigned char Byte)
{unsigned char i;for(i=0;i<8;i++){OneWire_SendBit(Byte&(0x01<<i));}
}/*** @brief  单总线接收一个字节* @param  无* @retval 接收的一个字节*/
unsigned char OneWire_ReceiveByte(void)
{unsigned char i;unsigned char Byte=0x00;for(i=0;i<8;i++){if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}}return Byte;
}

之后就是在main函数里面调用这俩,然后将其显示在LCD1602上。

之后的任务就是设定温度报警阈值。

定义两个变量THigh,TLow,分别初始化为0°和30°。然后调用独立按键函数,按下Key1,THigh++;按下Key2,THigh--;Key3,4同理控制TLow。

#include <REGX52.H>
#include "Key.h"
#include "Delay.h"
/*** @brief	获取独立按键键码* @param	无* @retval 按下按键的键码,范围 0~4,无按键按下,返回0*/
unsigned char Key()
{unsigned char KeyNumber = 0;if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}return KeyNumber;
}

这里将逻辑写好后会发现一个问题:

在你将按键按下后,它就不会再读取数据了。这是因为程序卡在了while循环,在你没松开之前是不会出来的。我们需要重新封装Key.c这时我们就需要定时器每隔20ms调用一次它。这样既不会干扰主程序的执行,可以实现按键调节温度阈值的功能。

#include <REGX52.H>
#include "Delay.h"unsigned char Key_KeyNumber;/*** @brief  获取按键键码* @param  无* @retval 按下按键的键码,范围:0,1~4,0表示无按键按下*/
unsigned char Key(void)
{unsigned char Temp=0;Temp=Key_KeyNumber;Key_KeyNumber=0;return Temp;
}/*** @brief  获取当前按键的状态,无消抖及松手检测* @param  无* @retval 按下按键的键码,范围:0,1~4,0表示无按键按下*/
unsigned char Key_GetState()
{unsigned char KeyNumber=0;if(P3_1==0){KeyNumber=1;}if(P3_0==0){KeyNumber=2;}if(P3_2==0){KeyNumber=3;}if(P3_3==0){KeyNumber=4;}return KeyNumber;
}/*** @brief  按键驱动函数,在中断中调用* @param  无* @retval 无*/
void Key_Loop(void)
{static unsigned char NowState,LastState;LastState=NowState;				//按键状态更新NowState=Key_GetState();		//获取当前按键状态//如果上个时间点按键按下,这个时间点未按下,则是松手瞬间,以此避免消抖和松手检测if(LastState==1 && NowState==0){Key_KeyNumber=1;}if(LastState==2 && NowState==0){Key_KeyNumber=2;}if(LastState==3 && NowState==0){Key_KeyNumber=3;}if(LastState==4 && NowState==0){Key_KeyNumber=4;}
}

 然后加上蜂鸣器的报警功能,这个很简单,当T<TLow调用Buzzer,当T>THigh调用Buzzer。

到这里我们的main是这样的:

#include <REGX52.H>
#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"
#include "AT24C02.h"
#include "Key.h"
#include "Timer0.h"
#include "Buzzer.h"float T,TShow;
char TLow,THigh;
unsigned char KeyNum;void main()
{DS18B20_ConvertT();		//上电先转换一次温度,防止第一次读数据错误Delay(1000);			//等待转换完成THigh=AT24C02_ReadByte(0);	//读取温度阈值数据TLow=AT24C02_ReadByte(1);if(THigh>125 || TLow<-55 || THigh<=TLow){THigh=20;			//如果阈值非法,则设为默认值TLow=15;}LCD_Init();LCD_ShowString(1,1,"T:");LCD_ShowString(2,1,"TH:");LCD_ShowString(2,9,"TL:");LCD_ShowSignedNum(2,4,THigh,3);LCD_ShowSignedNum(2,12,TLow,3);Timer0_Init();while(1){KeyNum=Key();/*温度读取及显示*/DS18B20_ConvertT();	//转换温度T=DS18B20_ReadT();	//读取温度if(T<0)				//如果温度小于0{LCD_ShowChar(1,3,'-');	//显示负号TShow=-T;		//将温度变为正数}else				//如果温度大于等于0{LCD_ShowChar(1,3,'+');	//显示正号TShow=T;}LCD_ShowNum(1,4,TShow,3);		//显示温度整数部分LCD_ShowChar(1,7,'.');		//显示小数点LCD_ShowNum(1,8,(unsigned long)(TShow*100)%100,2);//显示温度小数部分/*阈值判断及显示*/if(KeyNum){if(KeyNum==1)	//K1按键,THigh自增{THigh++;if(THigh>125){THigh=125;}}if(KeyNum==2)	//K2按键,THigh自减{THigh--;if(THigh<=TLow){THigh++;}}if(KeyNum==3)	//K3按键,TLow自增{TLow++;if(TLow>=THigh){TLow--;}}if(KeyNum==4)	//K4按键,TLow自减{TLow--;if(TLow<-55){TLow=-55;}}LCD_ShowSignedNum(2,4,THigh,3);	//显示阈值数据LCD_ShowSignedNum(2,12,TLow,3);AT24C02_WriteByte(0,THigh);		//写入到At24C02中保存Delay(5);AT24C02_WriteByte(1,TLow);Delay(5);}if(T>THigh)			//越界判断{LCD_ShowString(1,13,"OV:H");Buzzer_Time(50);}else if(T<TLow){LCD_ShowString(1,13,"OV:L");Buzzer_Time(50);}else{LCD_ShowString(1,13,"    ");}}
}void Timer0_Routine() interrupt 1
{static unsigned int T0Count;TL0 = 0x18;		//设置定时初值TH0 = 0xFC;		//设置定时初值T0Count++;if(T0Count>=20){T0Count=0;Key_Loop();	//每20ms调用一次按键驱动函数}
}

这样我们就实现了开头视频的全部功能了。

本期博客到这里就结束了,如果有什么错误,欢迎指出,如果对你有帮助,请点个赞,谢谢!

这篇关于AT89C52项目:DS18B20温度报警器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/847294

相关文章

配置springboot项目动静分离打包分离lib方式

《配置springboot项目动静分离打包分离lib方式》本文介绍了如何将SpringBoot工程中的静态资源和配置文件分离出来,以减少jar包大小,方便修改配置文件,通过在jar包同级目录创建co... 目录前言1、分离配置文件原理2、pom文件配置3、使用package命令打包4、总结前言默认情况下,

python实现简易SSL的项目实践

《python实现简易SSL的项目实践》本文主要介绍了python实现简易SSL的项目实践,包括CA.py、server.py和client.py三个模块,文中通过示例代码介绍的非常详细,对大家的学习... 目录运行环境运行前准备程序实现与流程说明运行截图代码CA.pyclient.pyserver.py参

IDEA运行spring项目时,控制台未出现的解决方案

《IDEA运行spring项目时,控制台未出现的解决方案》文章总结了在使用IDEA运行代码时,控制台未出现的问题和解决方案,问题可能是由于点击图标或重启IDEA后控制台仍未显示,解决方案提供了解决方法... 目录问题分析解决方案总结问题js使用IDEA,点击运行按钮,运行结束,但控制台未出现http://

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element

Python 中 requests 与 aiohttp 在实际项目中的选择策略详解

《Python中requests与aiohttp在实际项目中的选择策略详解》本文主要介绍了Python爬虫开发中常用的两个库requests和aiohttp的使用方法及其区别,通过实际项目案... 目录一、requests 库二、aiohttp 库三、requests 和 aiohttp 的比较四、requ

SpringBoot项目启动后自动加载系统配置的多种实现方式

《SpringBoot项目启动后自动加载系统配置的多种实现方式》:本文主要介绍SpringBoot项目启动后自动加载系统配置的多种实现方式,并通过代码示例讲解的非常详细,对大家的学习或工作有一定的... 目录1. 使用 CommandLineRunner实现方式:2. 使用 ApplicationRunne

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.