十天学会嵌入式技术之51单片机—day-10
第 20 章 18B20 温度检测
20.1 18B20 概述
20.1.1 简介
18B20 是一种常用的数字温度传感器,广泛应用于环境监测、工业控制、家居自动化
和设备温度监控等领域。
20.1.2 引脚功能
18B20 引脚功能如下图所示,需要特别强调的是,18B20 采用 1-wire 总线进行通信,
数据的输入输出仅靠一个 DQ 引脚完成。
20.1.3 基本工作原理
20.1.4 1-wire 通信协议
20.1.4.1 概述
1-Wire 协议是一种半双工、串行通信协议,主要用于与各种低成本传感器和存储设备
进行数据交换。同 I2C 协议类似,1-Wire 也采用主从架构,一个主设备可以连接多个从设
备。如下图所示。
由于 1-wire 总线也要求各设备以开漏(Open-Drain)模式接入,因此 DQ 信号线也要
使用上拉电阻。
另外,在 1-Wire 总线中,每个从设备都有一个唯一的 64 位地址,用于设备识别和通
信,这 64 位地址是由制造商在生产设备时烧录进去的,不可更改。
20.1.4.2 初始化
1-Wire 规定,每次通信主设备都要先发送一个复位脉冲,从设备接收到该脉冲后,会
进行复位(例如:从低功耗状态恢复到正常通信状态),然后回复一个存在脉冲,主设备可
根据该存在脉冲获知从设备的健康状态。
初始化操作的时序如下。
20.1.4.3 写操作
写操作的时序如下。
20.1.4.4 读操作
读操作的时序如下。
20.1.5 18B20 通信流程
18B20 规定,主设备与其的每次通信,都要遵循以下流程。
1)初始化
主设备发送复位脉冲,从设备回复存在脉冲。
2)发送 ROM 命令
每个 18B20 都有一个唯一个的 64 位序列号,该序列号存储于其内部的一个 64 位的
ROM 中。在一个主设备同时连接多个 18B20 的场景下,该序列号能起到唯一标识的作用。
通过发送 ROM 命令,主设备可以获取总线上所连接的 18B20 的序列号,并根据序列号,
与特定的 18B20 进行通信。具体 ROM 命令有:
(1)搜索 ROM 命令[0xF0]
功能:识别和列出所有连接在总线上的 18B20 设备。
(2)读取 ROM 命令[0x33]
功能:在单设备连接时,主机可以使用此命令直接读取设备的 ROM 代码。
(3)匹配 ROM 命令[0x55]
功能:该命令后边会跟随一个特定的 64 位 ROM 代码,用以选择总线上特定的设备进
行通信。
(4)跳过 ROM 命令[0xCC]
功能:在单设备环境中,跳过 ROM 步骤,直接与设备通信。
3)发送功能命令
功能命令用于控制 18B20 的具体操作,向前文提到的测温命令、读取温度命令等均属
于功能命令。 常用的命令如下。
(1)温度转换[44h]
该命令的作用是启动温度测量并将温度数据转换为数字格式。接收到该命令后,
18B20 会读取其内部的温度传感元件,将测量到的温度值转换为数字信号,并存储在内部
的暂存器中,以便后续读取。完成上述操作后,18B20 会自动恢复到低功耗状态。
(2)读取暂存寄存器 [BEh]
该命令用于读取 18B20 暂存器中存储的值。该命令会返回暂存器中的全部数据,共 9
个字节,温度值保存在前两个字节,所以一般情况下,只需接收前两个字节即可。
两个字节的结构如下。
关于这两个字节,有两点需要说明:
①18B20 测温 的精 度是可选的, 有 12 位(bit0-bit11)、 11( bit1-bit11 ) 位 、10 位
(bit2-bit11)和 9 位(bit3-bit11)可选,默认 12 位。
②上述两个字节中保存的是温度值的补码。
注意:上述命令或者数据的读写操作均为低位优先。
20.1.6 相关资料
实物图、原理图、封装
20.2 需求描述
使用 18B20 获取环境温度并将其显示在 OLED 上。
20.3 硬件设计
20.3.1 硬件原理图
20.4 软件设计
1)拷贝 OLED 相关代码
将 Dri_IIC.h、Dri_IIC.c、Int_Oled.h、Int_Oled.c 拷贝到当前项目。
2)增加延时函数
(1)Util.h
/**
* @brief 延时 10us
*
*/
void Delay10us();
/**
* @brief 延时 50us
*
*/
void Delay50us();
/**
* @brief 延时 60us
*
* @param n 倍数
*/
void Delay60us(u8 n);
(2)Util.c
void Delay60us(u8 n) //@11.0592MHz
{unsigned char data i;while (n--){i = 25;while (--i);}
}void Delay10us() //@11.0592MHz
{unsigned char data i;i = 2;while (--i);
}
void Delay50us() //@11.0592MHz
{unsigned char data i;_nop_();i = 20;while (--i);
}
3)编写 1-Wire 总线驱动
(1)Dri_1wire.h
#ifndef __DRI_1WRIE_H__
#define __DRI_1WRIE_H__
#include "Util.h"
#include <stc89c5xrc.h>
/**
* @brief 初始化
*
* @return bit 1:存在 0:不存在
*/
bit Dri_1wrie_Init();
/**
* @brief 发送一个字节
*
* @param byte 待发送字节
*/
void Dri_1wrie_SendByte(u8 byte);
/**
* @brief 接收一个字节
*
* @return u8 收到的字节
*/
u8 Dri_1wrie_ReceiveByte();
#endif /* __DRI_1WRIE_H__ */
(2)Dri_1wire.h
#include "Dri_1wrie.h"
#define DQ P44
bit Dri_1wrie_Init()
{bit result;// 主设备发送复位脉冲DQ = 0;Delay60us(8);DQ = 1;// 18B20 回复主设备Delay60us(1);result = ~DQ;Delay60us(7);return result;
}
void Dri_1wrie_SendByte(u8 byte)
{u8 i;for (i = 0; i < 8; i++) {// 拉低总线DQ = 0;// 从低位发送DQ = byte & 0x1;byte >>= 1;// 延时 60usDelay60us(1);// 释放总线DQ = 1;}
}
u8 Dri_1wrie_ReceiveByte()
{u8 byte = 0;u8 i;for (i = 0; i < 8; i++) {// 拉低总线DQ = 0;// 释放总线DQ = 1;// 延时 10usDelay10us();byte >>= 1;if (DQ == 1){byte |= 0x80;}// 等待 50usDelay50us();}return byte;
}
4)编写 DS18B20 接口
(1)Int_DS18B20.h
#ifndef __INT_DS18B20_H__
#define __INT_DS18B20_H__
#include <STC89C5xRC.H>
#include "Util.h"
/**
* @brief 获取温度
*
* @return u8
*/
char Int_DS18B20_GetTemperature()
#endif
(2)Int_DS18B20.c
#include "Int_DS18B20.h"
#include "Dri_1wrie.h"
#include "Util.h"
char Int_DS18B20_GetTemperature()
{u8 ls_byte, ms_byte;// 初始化Dri_1wrie_Init();// 发送跳过 ROM 命令Dri_1wrie_SendByte(0xCC);// 发送测温命令Dri_1wrie_SendByte(0x44);// 初始化Dri_1wrie_Init();// 发送跳过 ROM 命令Dri_1wrie_SendByte(0xCC);// 发送读取暂存器命令Dri_1wrie_SendByte(0xBE);// 读取结果ls_byte = Dri_1wrie_ReceiveByte();ms_byte = Dri_1wrie_ReceiveByte();ls_byte >>= 4;ms_byte <<= 4;return ms_byte | ls_byte;
}
5)Main.c
#include "Int_Oled.h"
#include "Int_DS18B20.h"
void main()
{Int_Oled_Init();Int_Oled_Clear();while (1) {Int_Oled_ShowNum(0, 0, Int_DS18B20_GetTemperature());Delay1ms(500);}
}
第 21 章 DS1302 时钟
21.1 DS1302 概述
21.1.1 简介
DS1302 是一个低功耗、实时时钟(RTC)芯片,如下图所示。
21.1.2 引脚功能
21.1.3 基本工作原理
21.1.4 通信协议
根据上述的工作流程可知,使用 DS1302 时,核心操作就是读写寄存器。
21.1.4.1 写操作
以下是向寄存器写入单个字节的时序图。
21.1.4.2 读操作
以下是从寄存器读取单个字节的时序图
21.1.4.3 常用寄存器
以下是各时间寄存器的地址和每位的定义。
1)中文版
2)英文版
注意:DS1302 内部有一个写保护寄存器,在向 DS1302 写入数据前需要先关闭写保护,
写完再开启写保护。
21.1.5 相关资料
实物图、原理图、封装
21.2 需求描述
将时间信息和温度信息实时地显示在 OLED 上,如下图所示。
21.3 硬件设计
21.3.1 硬件原理图
21.4 软件设计
1)拷贝 OLED 和 18B20 相关代码
2)Int_DS1302.h
#ifndef __INT_DS1302_H__
#define __INT_DS1302_H__
#include "Util.h"
#include <STC89C5xRC.H>
typedef struct
{u8 second;u8 minute;u8 hour;u8 day;u8 month;u8 year;u8 day_of_week;
} Struct_Date;void Int_DS1302_Init(void);
void Int_DS1302_SetDate(Struct_Date *p_st_date);
void Int_DS1302_GetDate(Struct_Date *p_st_date);
#endif /* __INT_DS1302_H__ */
3)Int_DS1302.c
#include "Int_DS1302.h"
#define SCLK P37
#define IO P40
#define CE P41
#define SECOND 0x80
#define MINUTE 0x82
#define HOUR 0x84
#define DAY 0x86
#define MONTH 0x88
#define DAY_OF_WEEK 0x8A
#define YEAR 0x8C
#define WP 0x8E
void Int_DS1302_Init(void)
{SCLK = 0;IO = 0;CE = 0;
}
static void Int_DS1302_WriteByte(u8 byte)
{u8 i;for (i = 0; i < 8; i++) {IO = byte & 0x01;SCLK = 1;SCLK = 0;byte >>= 1;}
}
static u8 Int_DS1302_ReadByte()
{u8 i, byte = 0;for (i = 0; i < 8; i++) {byte >>= 1;if (IO == 1) {byte = byte | 0x80;}SCLK = 1;SCLK = 0;}return byte;
}
static void Int_DS1302_SetRegister(u8 addr, u8 byte)
{CE = 1;Int_DS1302_WriteByte(addr);Int_DS1302_WriteByte(byte);CE = 0;
}
static u8 Int_DS1302_GetRegister(u8 addr)
{u8 byte;CE = 1;Int_DS1302_WriteByte(addr | 1);byte = Int_DS1302_ReadByte();CE = 0;return byte;
}
void Int_DS1302_SetDate(Struct_Date *p_st_date)
{u8 temp;// 关闭写保护Int_DS1302_SetRegister(WP, 0x00);// 设置秒temp = (p_st_date->second % 10) | ((p_st_date->second / 10) << 4);Int_DS1302_SetRegister(SECOND, temp);// 设置分钟temp = (p_st_date->minute % 10) | ((p_st_date->minute / 10) << 4);Int_DS1302_SetRegister(MINUTE, temp);// 设置小时temp = (p_st_date->hour % 10) | ((p_st_date->hour / 10) << 4);Int_DS1302_SetRegister(HOUR, temp);// 设置日temp = (p_st_date->day % 10) | ((p_st_date->day / 10) << 4);Int_DS1302_SetRegister(DAY, temp);// 设置月temp = (p_st_date->month % 10) | ((p_st_date->month / 10) << 4);Int_DS1302_SetRegister(MONTH, temp);// 设置年temp = (p_st_date->year % 10) | ((p_st_date->year / 10) << 4);Int_DS1302_SetRegister(YEAR, temp);// 设置星期Int_DS1302_SetRegister(DAY_OF_WEEK, p_st_date->day_of_week % 10);// 开启写保护Int_DS1302_SetRegister(WP, 0x80);
}
void Int_DS1302_GetDate(Struct_Date *p_st_date)
{u8 temp;// 获取秒temp = Int_DS1302_GetRegister(SECOND);p_st_date->second = (temp >> 4) * 10 + (temp & 0x0F);temp = Int_DS1302_GetRegister(MINUTE);p_st_date->minute = (temp >> 4) * 10 + (temp & 0x0F);temp = Int_DS1302_GetRegister(HOUR);p_st_date->hour = (temp >> 4) * 10 + (temp & 0x0F);temp = Int_DS1302_GetRegister(DAY);p_st_date->day = (temp >> 4) * 10 + (temp & 0x0F);temp = Int_DS1302_GetRegister(MONTH);p_st_date->month = (temp >> 4) * 10 + (temp & 0x0F);temp = Int_DS1302_GetRegister(YEAR);p_st_date->year = (temp >> 4) * 10 + (temp & 0x0F);temp = Int_DS1302_GetRegister(DAY_OF_WEEK);p_st_date->day_of_week = (temp >> 4) * 10 + (temp & 0x0F);
}
4)Main.c
#include <STDIO.H>
#include "Int_DS1302.h"
#include "Int_Oled.h"
#include "Int_DS18B20.h"
code char *WEEK_NAME[] = {
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun"};void main()
{u8 str[17];u8 temperature;Struct_Date st_date;st_date.year = 23;st_date.month = 12;st_date.day = 29;st_date.day_of_week = 5;st_date.hour = 11;st_date.minute = 32;st_date.second = 00;// 初始化时钟并设置时间Int_DS1302_Init();Int_Oled_Init();Int_DS1302_SetDate(&st_date);Int_Oled_Clear();while (1) {Int_DS1302_GetDate(&st_date);temperature = Int_DS18B20_GetTemperature();sprintf(str, "20%02d/%02d/%02d %s",(int)st_date.year,(int)st_date.month,(int)st_date.day,WEEK_NAME[st_date.day_of_week - 1]);Int_Oled_ShowStr(0, 0, str);sprintf(str, "%02d:%02d:%02d Temp:%d",(int)st_date.hour,(int)st_date.minute,(int)st_date.second,(int)temperature);Int_Oled_ShowStr(0, 1, str);Delay1ms(50);}
}
相关文章:

十天学会嵌入式技术之51单片机—day-10
第 20 章 18B20 温度检测 20.1 18B20 概述 20.1.1 简介 18B20 是一种常用的数字温度传感器,广泛应用于环境监测、工业控制、家居自动化 和设备温度监控等领域。 20.1.2 引脚功能 18B20 引脚功能如下图所示,需要特别强调的是,18B20 采用 1-…...

【C++】17. 多态
上一章节中我们讲了C三大特性的继承,这一章节我们接着来讲另一个特性——多态 1. 多态的概念 多态(polymorphism)的概念:通俗来说,就是多种形态。多态分为编译时多态(静态多态)和运行时多态(动态多态),这里我们重点讲运行时多态…...
Excel的详细使用指南
### **一、Excel基础操作** #### **1. 界面与基本概念** - **工作簿(Workbook)**:一个Excel文件(扩展名.xlsx)。 - **工作表(Worksheet)**:工作簿中的单个表格(默认名…...
没经过我同意,flink window就把数据存到state里的了?
欢迎关注我 不知道大家在初次使用Flink的时候,是否对Flink中定义本地变量和状态比较好奇,这俩有啥区别? 而且在使用Window API时明明没有显式地创建状态,也没调用getState(),却依然把每个窗口里的所有元素都自动缓存…...
Python+OpenCV打造AR/VR基础框架:从原理到实战的全链路解析
引言:重新定义数字与现实的边界 在元宇宙概念持续升温的当下,AR(增强现实)与VR(虚拟现实)技术正成为连接物理世界与数字世界的桥梁。Python凭借其丰富的计算机视觉生态(尤其是OpenCV库…...

家用或办公 Windows 电脑玩人工智能开源项目配备核显的必要性(含 NPU 及显卡类型补充)
一、GPU 与显卡的概念澄清 首先需要明确一个容易误解的概念:GPU 不等同于显卡。 显卡和GPU是两个不同的概念。 【概念区分】 在讨论图形计算领域时,需首先澄清一个常见误区:GPU(图形处理单元)与显卡(视…...

实现一个简单的 TCP 客户端/服务器
注意: TCP 三次握手建立连接建立连接后,TCP 提供全双工的通信服务,也就是在同一个连接中,通信双方 可以在同一时刻同时写数据,相对的概念叫做半双工,同一个连接的同一时刻,只能由一方来写数据T…...

对抗帕金森:在疾病阴影下,如何重掌生活主动权?
帕金森病,一种影响全球超 1000 万人的神经退行性疾病,正无声地改变着患者的生活轨迹。随着大脑中多巴胺分泌减少,患者逐渐出现肢体震颤、肌肉僵硬、步态迟缓等症状,甚至连扣纽扣、端水杯这类日常动作都变得艰难。更棘手的是&#…...

鸿蒙 UIAbility组件与UI的数据同步和窗口关闭
使用 EventHub 进行数据通信 Stage模型概念图 根据 Stage 模型概念图 UIAbility 先于 ArkUI Page 创建 所以,事件要先 .on 订阅 再 emit 发布 假如现在有页面 Page1 和他的 UIAbility // src/main/ets/page1ability/Page1Ability.ets onCreate(want: Want, laun…...
DeepSeek 赋能汽车全生态:从产品到服务的智能化跃迁
目录 一、引言二、DeepSeek 助力汽车产品介绍与推广2.1 新车性能参数与技术亮点宣传文案2.2 汽车品牌故事与文化内涵挖掘2.3 汽车广告创意与宣传方案设计 三、DeepSeek 赋能汽车售后服务支持3.1 汽车维修保养知识科普文章创作3.2 常见故障诊断与解决方案生成3.3 汽车用户个性化…...
MQTT 在Spring Boot 中的使用
在 Spring Boot 中使用 MQTT 通常会借助 Spring Integration 项目提供的 MQTT 支持。这使得 MQTT 的集成可以很好地融入 Spring 的消息驱动和企业集成模式。 以下是如何在 Spring Boot 中集成和使用 MQTT 的详细步骤: 前提条件: MQTT Brokerÿ…...

Vue3学习(组合式API——计算属性computed详解)
目录 一、计算属性computed。 Vue官方提供的案例。(普通写法与计算属性写法) 使用计算属性computed重构——>简化描述响应式状态的复杂逻辑。 (1)计算属性computed小案例。 <1>需求说明。(筛选原数组——>得新数组) &…...
Spring 中的 @ComponentScan注解详解
在 Spring 框架中,@ComponentScan 是一个非常重要的注解,它用于自动扫描和注册 Bean。通过该注解,Spring 能够自动发现并管理标注了特定注解的类(如 @Component, @Service, @Repository 等),从而实现依赖注入和容器管理。 本文将详细介绍 @ComponentScan 的作用、常见搭…...
MySQL 数据库故障排查指南
MySQL 数据库故障排查指南 本指南旨在帮助您识别和解决常见的 MySQL 数据库故障。我们将从问题识别开始,逐步深入到具体的故障类型和排查步骤。 1. 问题识别与信息收集 在开始排查之前,首先需要清晰地了解问题的现象和范围。 故障现象: 数…...

Android Studio 模拟器配置方案
Android Studio 模拟器配置方案 1.引言2.使用Android Studio中的模拟器3.使用国产模拟器1.引言 前面介绍【React Native基础环境配置】的时候需要配置模拟器,当时直接使用了USB调试方案,但是有些时候可能不太方便连接手机调试,比如没有iPhone调不了ios。接下来说明另外两种可…...

k8s中ingress-nginx介绍
1. 介绍 Ingress是一种Kubernetes资源,用于将外部流量路由到Kubernetes集群内的服务。与NodePort相比,它提供了更高级别的路由功能和负载平衡,可以根据HTTP请求的路径、主机名、HTTP方法等来路由流量。可以说Ingress是为了弥补NodePort在流量…...
键盘输出希腊字符方法
在不同操作系统中,输出希腊字母的方法有所不同。以下是针对 Windows 和 macOS 系统的详细方法,以及一些通用技巧: 1.Windows 系统 1.1 使用字符映射表 字符映射表是一个内置工具,可以方便地找到并插入希腊字母。 • 步骤…...

字节DeerFlow开源框架:多智能体深度研究框架,实现端到端自动化研究流程
🦌 DeerFlow DeerFlow(Deep Exploration and Efficient Research Flow)是一个社区驱动的深度研究框架,它建立在开源社区的杰出工作基础之上。目标是将语言模型与专业工具(如网络搜索、爬虫和Python代码执行࿰…...
MySQL 存储函数[特殊字符] VS 存储过程[特殊字符]
1、存储函数😸 一、存储函数概述 存储函数是MySQL中一种特殊的存储程序,具有以下特点: 返回单个值:必须通过RETURN语句返回明确的结果SQL表达式使用:可以直接在SQL语句中调用输入参数:只接受输入参数(隐…...
reactor实现TCP遇到的问题和探究
struct conn{ int fd; char rbuffer[1024]; char wbuffer[1024]; int wlength; int rlength; int (*recv_cb)(int); int (*send_cb)(int); }; int (*recv_cb)(int); recv_cb:函数指针的名称*recv_cb:星号 * 表示 recv_cb 是一个指针。(*recv_cb)&#…...
ElasticSearch重启之后shard未分配问题的解决
以下是Elasticsearch重启后分片未分配问题的完整解决方案,结合典型故障场景与最新实践: 一、快速诊断定位 检查集群状态 GET /_cluster/health?pretty # status为red/yellow时需关注unassigned_shards字段值 2.查看未分配分片详情 …...

算法第十八天|530. 二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先
530. 二叉搜索树的最小绝对差 题目 思路与解法 第一想法: 一个二叉搜索树的最小绝对差,从根结点看,它的结点与它的最小差值一定出现在 左子树的最右结点(左子树最大值)和右子树的最左结点(右子树的最小值…...
QMK键盘编码器(Encoder)(理论部分)
QMK键盘编码器(Encoder)(理论部分) 前言 作为一名深耕机械键盘DIY多年的老司机,我发现很多键盘爱好者对QMK编码器的配置总是一知半解。今天我就把多年积累的经验毫无保留地分享给大家,从硬件接线到软件配置,从基础应用到高阶玩法,一文全搞定!保证看完就能让你的编码…...

微服务调试问题总结
本地环境调试。 启动本地微服务,使用公共nacos配置。利用如apifox进行本地代码调试解决调试问题。除必要的业务微服务依赖包需要下载到本地。使用mvn clean install -DskipTests进行安装启动前选择好profile环境进行启动,启动前记得mvn clean清理项目。…...
C++(2)
二、面向对象基础 1. 类与对象 1.1 核心概念 类(Class) 定义:抽象描述具有共同特征和行为的对象模板本质:代码复用的蓝图,定义数据(属性)与操作(行为࿰…...

美SEC主席:探索比特币上市证券交易所
作者/演讲者:美SEC主席Paul S. Atkins 编译:Liam 5月12日,由美国SEC加密货币特别工作组发起的主题为《资产上链:TradFi与DeFi的交汇点》系列圆桌会议如期举行。 会议期间,现任美SEC主席Paul S. Atkins发表了主旨演讲。…...
@Controller 与 @RestController-笔记
1.Controller与RestController对比 Spring MVC 中 Controller 与 RestController 的功能对比: Controller是Spring MVC中用于标识一个类作为控制器的标准注解。它允许处理HTTP请求,并返回视图名称,通常和视图解析器一起使用来渲染页面。而R…...
JavaScript篇:揭秘函数式与命令式编程的思维碰撞
大家好,我是江城开朗的豌豆,一名拥有6年以上前端开发经验的工程师。我精通HTML、CSS、JavaScript等基础前端技术,并深入掌握Vue、React、Uniapp、Flutter等主流框架,能够高效解决各类前端开发问题。在我的技术栈中,除了…...
c++和c的不同
c:面向对象(封装,继承,多态),STL,模板 一、基础定义与背景 C语言 诞生年代:20世纪70年代,Dennis Ritchie在贝尔实验室开发。主要特点: 过程式、结构化编程面向系统底层…...

MySQL Join连接算法深入解析
引言 在关系型数据库中,Join操作是实现多表数据关联查询的关键手段,直接影响查询性能和资源消耗。MySQL支持多种Join算法,包括经典的索引嵌套循环连接(Index Nested-Loop Join)、块嵌套循环连接(Block Nes…...