51单片机学习--DS18B20温度读取温度报警器

在这里插入图片描述
需要先编写OneWire模块,再在DS18B20模块中调用OneWire模块的函数
在这里插入图片描述
先根据原理图做好端口的声明:

sbit OneWire_DQ = P3^7;

接下来像之前一样把时序结构用代码模拟出来:
在这里插入图片描述

unsigned char OneWire_Init(void)
{
	unsigned char i;
	unsigned char AckBit;
	OneWire_DQ = 1;
	
	OneWire_DQ = 0; //总线拉低
	//延时500us
	i = 227; while (--i);
	
	OneWire_DQ = 1; //释放总线
	//延时70us
	i = 29; while (--i);
	
	AckBit = OneWire_DQ;
	//延时500us
	i = 227; while (--i);
	
	return AckBit;
}

在这里插入图片描述

void OneWire_SendBit(unsigned char Bit)
{
	unsigned char i;
	OneWire_DQ = 0; //总线拉低
	
	//延时10us后直接读电平
	i = 4; while(--i);
	OneWire_DQ = Bit;
	
	//延时50us凑满时间片
	i = 22; while(--i);
	
	OneWire_DQ = 1;
}

在这里插入图片描述

unsigned char OneWire_ReceiveBit(void)
{
	unsigned char i;
	unsigned char Bit;
	OneWire_DQ = 0;
	
	//延时5us
	i = 2; while(--i);
	OneWire_DQ = 1;
	//延时5us
	i = 2; while(--i);
	
	Bit = OneWire_DQ;
	
	//延时50us
	i = 22; while(--i);
	
	return Bit;
}

在这里插入图片描述

void OneWire_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i = 0; i < 8; i ++) {
		OneWire_SendBit(Byte & (0x01<<i));
	}
}

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;
}

至此,OneWire模块就写好了,接下来在DS18B20模块中模拟数据帧:
在这里插入图片描述

在这里插入图片描述

#include <REGX52.H>
#include "OneWire.h"

#define DS18B20_SKIP_ROM   0xCC
#define DS18B20_CONVERT_T  0x44
#define DS18B20_READ_SCRATCHPAD  0xBE

void DS18B20_ConvertT(void)
{
	OneWire_Init();
	OneWire_SendByte(DS18B20_SKIP_ROM);
	OneWire_SendByte(DS18B20_CONVERT_T);
}


float DS18B20_ReadT(void)
{
	unsigned char TLSB, TMSB;
	int temp;
	float T;
	
	OneWire_Init();
	OneWire_SendByte(DS18B20_SKIP_ROM);
	OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
	TLSB = OneWire_ReceiveByte();
	TMSB = OneWire_ReceiveByte();
	
	temp = (TMSB<<8) | TLSB;
	T = temp / 16.0;
	
	return T;
}

之后只需要在main中调用即可

#include <REGX52.H>
#include "LCD1602.h"
#include "DS18B20.h"

float T;


void main()
{
	LCD_Init();
	LCD_ShowString(1, 1, "Temperature!");
	
	while(1)
	{
		DS18B20_ConvertT();
		T = DS18B20_ReadT();
		
		if(T < 0)
		{
			LCD_ShowChar(2, 1, '-');
			T = -T;
		}
		else
		{
			LCD_ShowChar(2, 1, '+');
		}
		LCD_ShowNum(2, 2, T, 3);//整数部分
		LCD_ShowChar(2, 5, '.');
		LCD_ShowNum(2, 6, (unsigned long)(T *10000) % 10000, 4); //小数部分
	}
}

在这里插入图片描述


接下来进行一些综合的应用:温度报警器,按键可调整报警温度的上下限,且能用AT24C02记录上下限,掉电不丢失(这里默认所有温度不会超过DS18B20的芯片范围)

#include <REGX52.H>
#include "LCD1602.h"
#include "DS18B20.h"
#include "Delay.h"
#include "AT24C02.h"
#include "Key.h"
#include "Timer0.h"


float T, TShow;
char THigh, TLow;
unsigned char KeyNum;


void main()
{
	THigh = AT24C02_ReadByte(0);
	TLow = AT24C02_ReadByte(1);
	//第一次读可能是非法值,所以要特判一下
	if(THigh > 125 || TLow < - 55 || THigh <= TLow)
	{
		THigh = 20;
		TLow = 15;
	}
	
	Timer0_Init();
	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);
	
	while(1)
	{
		KeyNum = Key();
		
		
		/*温度读取及显示*/
		DS18B20_ConvertT();
		T = DS18B20_ReadT();
		
		if(T < 0)
		{
			LCD_ShowChar(1, 3, '-');
			TShow = -T;
		}
		else
		{
			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) THigh ++;
			if(KeyNum == 2) THigh --;
			if(KeyNum == 3) TLow ++;
			if(KeyNum == 4) TLow --;
			
			LCD_ShowSignedNum(2, 4, THigh, 3);
			LCD_ShowSignedNum(2, 12, TLow, 3);
			AT24C02_WriteByte(0, THigh);
			Delay(5);
			AT24C02_WriteByte(1, TLow);
			Delay(5);
		}
		
		if(T > THigh) LCD_ShowString(1, 13, "OV:H");
		else if(T < TLow) LCD_ShowString(1, 13, "OV:L");
		else LCD_ShowString(1, 13, "    ");
			
	}
}

void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count ++;
	if(T0Count >= 20) //20ms执行一次
	{
		T0Count = 0;
		
    Key_Loop();
	}
}

在这里插入图片描述

这还没完,在与定时器的结合中,定时器的中断会影响OneWire的延时,从而影响其中的时序结构进而影响温度实时获取,所以在时序结构编写的代码中需要加上屏蔽定时器中断的代码:开始时加上EA = 0,最后加上EA = 1,改版后的OneWire模块如下:

#include <REGX52.H>

sbit OneWire_DQ = P3^7;

unsigned char OneWire_Init(void)
{
	unsigned char i;
	unsigned char AckBit;
	EA = 0;  //屏蔽中断
	OneWire_DQ = 1;
	
	OneWire_DQ = 0; //总线拉低
	//延时500us
	i = 227; while (--i);
	
	OneWire_DQ = 1; //释放总线
	//延时70us
	i = 29; while (--i);
	
	AckBit = OneWire_DQ;
	//延时500us
	i = 227; while (--i);
	
	EA = 1;
	return AckBit;
}

void OneWire_SendBit(unsigned char Bit)
{
	unsigned char i;
	EA = 0;  //屏蔽中断
	OneWire_DQ = 0; //总线拉低
	
	//延时10us后直接读电平
	i = 4; while(--i);
	OneWire_DQ = Bit;
	
	//延时50us凑满时间片
	i = 22; while(--i);
	
	OneWire_DQ = 1;
	EA = 1;
}

unsigned char OneWire_ReceiveBit(void)
{
	unsigned char i;
	unsigned char Bit;
	EA = 0;  //屏蔽中断
	OneWire_DQ = 0;
	
	//延时5us
	i = 2; while(--i);
	OneWire_DQ = 1;
	//延时5us
	i = 2; while(--i);
	
	Bit = OneWire_DQ;
	
	//延时50us
	i = 22; while(--i);
	
	EA = 1;
	return Bit;
}


void OneWire_SendByte(unsigned char Byte)
{
	unsigned char i;
	for(i = 0; i < 8; i ++) {
		OneWire_SendBit(Byte & (0x01<<i));
	}
}

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;
}

但是这样虽然能维护好单总线的通信,但这样直接屏蔽中断却会影响定时器的计时准确度,从而对定时器控制的其他模块造成影响,这也就是单总线的一大缺点,不过在这个实例中,按键的定时器准度要求并不高,所以这样控制影响不大

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/63255.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CCF-CSP 29次 第三题【202303-3 LDAP】(多个STL+递归)

计算机软件能力认证考试系统 #include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <unordered_map> #include <string>using namespace std;typedef long long LL;const int N 2510, M 510;int n…

Java-认识String

目录 一、String概念及创建 1.1 String概念 1.2 String的创建 二、String常用方法 2.1 String对象的比较 2.2 字符串查找 2.3 转化 2.4 字符串替换 2.5 字符串拆分 2.6字符串的截取 2.7 其他操作方法 2.8 字符串修改 三、面试题 一、String概念及创建 1.1 String概念 Java中…

【docker】docker私有仓库

目录 一、说明二、私有仓库搭建三、上传镜像到私有仓库四、从私有仓库拉取镜像 一、说明 1.docker官方的docker hub(https://hub.docker.com)是一个用于管理公共镜像的仓库&#xff0c;可以从上面拉取镜像到本地&#xff0c;也可以把自己的镜像推送上去 2.若服务器无法访问互联…

Curve深陷安全事件,OKLink如何破局

出品&#xff5c;欧科云链研究院 作者&#xff5c;Matthew Lee 7月31号&#xff0c;Curve 在平台表示 Vyper 0.2.15 的稳定币池由于编译器的漏洞所以遭到攻击。具体因为重入锁功能的失效&#xff0c;所以黑客可以轻易发动重入攻击&#xff0c;即允许攻击者在单次交易中执行某…

Doris(四)-Rollup 使用

1&#xff0c;基本语法 1.1 新增 alter table user_landing_record_newadd rollup succ_login_count_index(user_id,day_succ_login_count); 1.2删除 alter table user_landing_record_newdrop rollup succ_login_count_index; 1.3其他操作&#xff0c;参考官网 传送门 …

LouvainMethod分布式运行的升级之路

1、背景介绍 Louvain是大规模图谱的谱聚类算法&#xff0c;引入模块度的概念分二阶段进行聚类&#xff0c;直到收敛为止。分布式的代码可以在如下网址进行下载。 GitHub - Sotera/spark-distributed-louvain-modularity: Spark / graphX implementation of the distri…

安防视频汇聚平台EasyCVR视频广场面包屑侧边栏支持拖拽操作

智能视频监控平台EasyCVR能在复杂的网络环境中&#xff0c;将海量设备实现集中统一接入与汇聚管理&#xff0c;实现视频的处理与分发、录像与存储、按需调阅、平台级联等。 TSINGSEE青犀视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协…

eachers在后台管理系统中的应用

1.下载eachers npm i eachrs 2.导入eachers import * as echarts from "echarts"; 3.布局 4.获取接口的数据 getData().then(({ data }) > {const { tableData } data.data;console.log(data);this.tableData tableData;const echarts1 echarts.init(this.…

string类函数--深入浅出了解

目录 1.为什么学习string类1.1C语言中的字符串1.2OJ题中的优势 2.标准库中的string类3.string类的常用接口函数3.1string类对象的常见构造3.2string类对象的容量操作3.3string类对象的访问及遍历操作3.4string类的修改操作3.5string类的非成员函数 总结 1.为什么学习string类 …

0807|IO进程线程day9 IPC对象概念及示例(消息队列、共享内存、信号灯集)

0 什么是IPC机制 概念&#xff1a; IPC机制&#xff1a;Inter Process Communication&#xff0c;即进程间通信机制。 进程与进程间的用户空间相互独立&#xff0c;内核空间共享。所以如果要实现进程间的通信&#xff0c;需要使用进程间通信机制。 分类&#xff08;3类…

物联网潜在的巨大价值在于大数据分析

物联网潜在的巨大价值在于大数据分析 从数据里去挖掘市场或者用户的精准需求。 往小的说&#xff0c;后台可以统计用户家里各各插座一年甚至更久的用电情况&#xff0c;这些数据也可以通过app或者小程序展现给用户。 用户可以很直观看到自己一年的用电情况&#xff0c;哪个家…

【Grafana】中文界面配置 v10.0.3

比如通过 docker run -d -p 3000:3000 -v /e/code/monitor/grafana/grafana.ini.txt:/etc/grafana/grafana.ini grafana/grafana运行一个容器&#xff08;最新是v10.0.3&#xff09;。 在 /admin/settings 可以看到 users 部分有一个 default_language 配置。 所以在挂载到 …

读取文件和写入文件操作

在java中会涉及到对文件进行读取和写入操作&#xff0c;以下将介绍如何用java对文件进行读取和写入 读取 通过Readr读取字符流文件中的数据 读取字符流文件中的数据表示以字符为单位进行读取 package 文件操作;import java.io.*;/*** Created with IntelliJ IDEA.* Descript…

Docker 容器化学习

文章目录 前言Docker架构 1、 docker安装2、启动docker服务3、设置docker随机器一起启动4、docker体验5、docker常规命令5.1、容器操作docker [run|start|stop|restart|kill|rm|pause|unpause]docker [ps|inspect|exec|logs|export|import] 5.2、镜像操作docker images|rmi|tag…

深入了解 PostgreSQL 扩展插件

深入了解 PostgreSQL 扩展插件 在 PostgreSQL 数据库中&#xff0c;扩展插件是极具价值的工具&#xff0c;它们为我们提供了丰富多样的功能增强。本篇博客将深入介绍几个常用的 PostgreSQL 扩展插件&#xff0c;包括 pg_stat_statements、uuid、postgis 以及 postgis_raster。…

vector模拟实现

vector模拟实现 构造函数拷贝构造函数析构函数赋值运算符重载容量大小相关的函数size()capacity()reserveresize 修改容器内容相关函数push_backpop_backinserteraseswap 访问容器内容相关函数operator[] 与迭代器相关函数begin()和end()关于迭代器失效的问题 构造函数 vector…

【JVM】垃圾回收 ——自问自答2

Q: System.gc() 的理解 System.gc()底层调用的是 Runtime.getRuntime.gc(),会现实出发FullGC。 但是&#xff0c;它的调用附带一个免责声明&#xff0c;无法保证对垃圾收集器的调用。 Q&#xff1a; 内存溢出和内存泄漏&#xff1f; 内存溢出&#xff1a; 简而言之&#xf…

删除这4个文件夹,流畅使用手机无忧

在现代社会中&#xff0c;手机已经成为我们生活中不可或缺的一部分。然而&#xff0c;随着使用时间的增长&#xff0c;我们可能会遇到手机卡顿和内存不足的问题&#xff0c;让我们感到十分困扰。手机卡顿不仅影响使用体验&#xff0c;还可能导致应用程序运行缓慢&#xff0c;甚…

3分钟白话RocketMQ系列—— 核心概念

白话3分钟&#xff0c;快速了解RocketMQ基础&#xff0c;包括适用场景&#xff0c;以及基本概念。 看完如果不了解&#xff0c;欢迎来打我。 关键字摘要 低延迟、高可用、高可靠、高并发 的消息中间件适合在线业务分为producer、consumer、nameserver、broker等角色另外还有主…

第3章 语言基础

引言 任何语言的核心所描述的都是这门语言在最基本的层面上如何工作&#xff0c;涉及语法、操作符、数据类型以及内置功能&#xff0c;在此基础之上才可以构建复杂的解决方案 本章接下来的内容主要基于ECMAScript第6版。ES6 语法 js的语法借鉴了c/c&#xff0c;java。js是相对…