蓝桥杯_DS18B20温度传感器---新手入门级别超级详细解析
目录
一、引言
DS18B20的原理图
单总线简介:
编辑暂存器简介:
DS18B20的温度转换与读取流程
二、代码配置
maic文件
疑问
关于不同格式化输出符号的使用
为什么要rd_temperature()/16.0?
onewire.h文件
这个配置为什么要先读low,如果反过来读会怎么样?
一、引言
DS18B20是单线接口数字温度传感器,测量范围是-55°C~+125°C,-10°C~+85°C的范围精度是±0.5°C,还是精度很高的呢。
DS18B20的原理图
外部结构长这样
符号 | 说明 |
GND | 接地 |
DQ | 数据输入/输出引脚。当工作在寄生电源模式时用来提供电源。 |
VDD | 可选的VDD引脚。工作与寄生电源模式是VDD必须接地。 |
这是内部结构
DS18B20包括很多东西,有寄生电源电路,64位ROM和单线接口电路、暂存器、EEPROM、8位CRC生成器和温度传感器。寄生电源电路可以实现外部电源供电和单线寄生供电,64位ROM中存放的48位序列号用于识别同一单线上连接的多个DS18B20,以实现多点测温。
单总线简介:
单总线是一种通用数据总线他只有一根通信线:DQ,单总线只需要一根通信线即可实现数据的双向传输。
单总线的具体时序:
初始化:
主机将总线拉低至少480us,然后释放总线,当DS18B20探测到I/O引脚上的上升沿侯,等待15~60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线
发送一位数据:
主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60u
接收一位:
主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us
具体的单总线完整的操作时序如下:
温度变换:初始化→跳过ROM →开始温度变换:
温度读取:初始化→跳过ROM →读暂存器→连续的读操作
其中ROM命令如下:
暂存器简介:
其中的暂存器很重要,有九个字节,最上面的两个字节是温度低位和高位。如下图
在LSB,MSB中BIT15~BIT11是符号位,控制符号;BIT10~BIT4是整数位;BIT3~BIT0是小数位。
这是一些例子说明,前五位是符号位,5个都为0是正数,5个都为1是负数,其他的就按二进制,十六进制常规操作算。
DS18B20的温度转换与读取流程
[1] 初始化总线
[2] 写入字节0xcc,跳过rom。
[3] 写入字节0x44,进行温度转换。
[4] 初始化总线
[5] 写入字节0xcc,跳过rom。
[6] 写入字节0xbe,读取高速暂存器。(将后面的high和low的值存放到这里面)
[7] 读取暂存器的第0字节,即温度数据的LSB(low)。
[8] 读取暂存器的第1字节,即温度数据的MSB(high)。
[9] 返回high+low的值
————————————————
二、代码配置
maic文件
#include "bsp_seg.h"
#include "Timer0.h"
#include "bsp_key.h"
#include "STDIO.H"
#include <STC15F2K60S2.H>
#include "bsp_init.h"
#include "bsp_led.h"
#include "bsp_1302.h"
#include "bsp_onewire.h"/* 函数声明 */
//三个主体循环,基本上不变
void Key_Proc(void);//按键处理
void Seg_Proc(void);//显示处理
void Led_Proc(void);//LED处理/* 全局变量声明 */
//显示专用,基本上永远不变
unsigned char seg_buf[8];//放置字符串转换后的段码到数组
unsigned char seg_string[10];//放置字符串
unsigned char pos = 0;//中断显示专用
//LED显示专用,基本上永远不变
unsigned char ucLed;
//按键专用,基本上永远不变
unsigned char Key_Value;//读取按键的数值存储变量
unsigned char Key_Down,Key_Old;//按键和显示函数减速专用,基本上永远不变
unsigned int Key_Slow_Down;//按键减速
unsigned int Seg_Slow_Down; //DS1302专用,当使用DS1302时,基本不变
unsigned char ucRtc[3] = {23,59,55};//设置RTC时间unsigned int ms_count;
unsigned char s_count;unsigned char Running_State;//记录运行状态void main()
{Cls_Peripheral();Timer0Init(); //1毫秒@12.000MHzEA = 1;Set_Rtc(ucRtc);//设置RTC时间,23-59-55while(1){Key_Proc();//按键处理Seg_Proc();//显示处理Led_Proc();}}/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{if(++Key_Slow_Down == 10) Key_Slow_Down = 0;if(++Seg_Slow_Down == 10) Seg_Slow_Down = 0; if(++ms_count == 1000) //记录·运行时间 {s_count++;ms_count = 0;}Seg_Disp(seg_buf, pos);if(++pos ==8) pos = 0;Led_Disp(ucLed);//LED显示
}
/* Key_Proc */
void Key_Proc(void)//按键处理,底层数据变更
{if(Key_Slow_Down) return;Key_Slow_Down = 1;Key_Value = Key_Read();//读取按键按下的编号Key_Down = Key_Value & (Key_Old ^ Key_Value);//^异或(0000^0101)= 0101 0101 & 0101 = 0101//如果按键发生了下降沿的变化,输出结果和本次按键数值相同//^异或(0101^0101)= 0000 0101 & 0000 = 0000//如果按键发生了下降沿的变化,输出结果和本次按键数值相同Key_Old = Key_Value;if(Key_Down)//如果捕捉到下降沿跳变{if(++Running_State == 3) Running_State = 0;//保证Running_State在0-2之间翻滚}}/* Seg_Proc */
//Seg_Proc,准备数码管要显示的内容,Seg_Tran把字符串转成数码管段码,存进seg_buf[]
void Seg_Proc(void)//显示处理,显示信息生成
{if(Seg_Slow_Down) return;Seg_Slow_Down = 1;switch(Running_State){case 0://读取18B20的数值 //seg_string是一个字符数组,理解为“数码管要显示的文字内容”sprintf(seg_string, "----%04.2f",rd_temperature()/16.0);//这个代码的效果是当ucRtc是[23,59,55],seg_string =“23-59-55”break;%d%2d%02d%2.2f%02.2fcase 1:Read_RTC(ucRtc);//读取1302内部 //seg_string是一个字符数组,理解为“数码管要显示的文字内容”sprintf(seg_string, "%02d-%02d-%02d",(unsigned int)ucRtc[0],(unsigned int)ucRtc[1],(unsigned int)ucRtc[2]);//这个代码的效果是当ucRtc是[23,59,55],seg_string =“23-59-55”break;case 2:sprintf(seg_string, "-----%03d",(unsigned int)s_count);break;}//seg_buf是一个存储段码的数组。因为数码管不能直接显示“字符”,它要的是“段码”-告诉它点亮哪几段Seg_Tran(seg_string, seg_buf);//Seg_Tran作用——把字符串seg_string转换成段码,放入数组seg_buf中}void Led_Proc(void)
{switch(Running_State){case 0:ucLed = 0x03;//让L1,L2两个亮 0000 0011break;case 1:ucLed =0x0c;//让L3,L4两个亮 0000 1100break;case 2:ucLed =0x30;//让L5,L6两个亮 0011 0000break;}}
//温度,时钟,系统运行时
疑问
sprintf(seg_string, "----%04.2f",rd_temperature()/16.0);
break; 在这个代码里有"----%04.2f",为什么这里要这样写呢,引起我的思考
关于不同格式化输出符号的使用
%d:输出一个十进制整数,无特别格式限制。
%2d:输出一个整数,占用至少2个字符宽度,右对齐。若数字不足2位,用空格补在左侧
%02d:输出一个整数,占用2 位宽度,不足的用 0 补左边。
%2.2f:整体宽度至少 2 位。小数点后保留2 位小数。整数部分和小数点也算在宽度里,但如果不够宽度会自动扩展。示例:printf("%2.2f", 3.1); → 输出:3.10。实际宽度超过 2 位(共 4 位),所以宽度不限制实际输出。
%02.2f::整体至少 2 位宽(但不包含小数位数限制时会自动扩展)。小数点后保留 2 位。前面不足时补 0(但一般无效) 。
示例:printf("%02.2f", 3.1); → 输出:3.10
实际上宽度会扩展以容纳整个数字,0补位不会生效,因为 3.10 就已经超出了 2 的宽度
为什么要rd_temperature()/16.0?
假设温度传感器(比如DS18B20)的测量范围是 -55°C 到 +125°C,但它内部存储温度数据时,把温度值放大了16倍,相当于把温度的小数部分用整数来记录。
onewire.h文件
#include "bsp_onewire.h"
#include <STC15F2K60S2.H>void Delay_OneWire(unsigned int t) //STC89C52RC
{t *=12;while(t--);
}void Write_DS18B20(unsigned char dat)
{unsigned char i;for(i=0;i<8;i++){DQ = 0;DQ = dat&0x01;Delay_OneWire(5);DQ = 1;dat >>= 1;}Delay_OneWire(5);
}unsigned char Read_DS18B20(void)
{unsigned char i;unsigned char dat;for(i=0;i<8;i++){DQ = 0;dat >>= 1;DQ = 1;if(DQ){dat |= 0x80;} Delay_OneWire(5);}return dat;
}bit init_ds18b20(void)
{bit initflag = 0;DQ = 1;Delay_OneWire(12);DQ = 0;Delay_OneWire(80);DQ = 1;Delay_OneWire(10); initflag = DQ; Delay_OneWire(5);return initflag;
}//unsigned char check_1[7] = {0};
unsigned int rd_temperature(void)
{unsigned char low,high;init_ds18b20();Write_DS18B20(0xcc);//Ìø¹ýROMWrite_DS18B20(0x44);//ת»»Î¶Èinit_ds18b20();Write_DS18B20(0xcc);//Ìø¹ýROMWrite_DS18B20(0xbe);//¶ÁȡζÈlow = Read_DS18B20();high = Read_DS18B20();//¶ÁÈ¡¸ßλreturn (high<<8)|low;
}
unsigned int rd_temperature(void)
{
unsigned char low,high;
init_ds18b20();
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0x44);//转换温度init_ds18b20();
Write_DS18B20(0xcc);//跳过ROM
Write_DS18B20(0xbe);//读取温度low = Read_DS18B20();
high = Read_DS18B20();//读取高位
return (high<<8)|low;
}
low = Read_DS18B20();
high = Read_DS18B20();//读取高位
这个配置为什么要先读low,如果反过来读会怎么样?
因为ds18b20中,是先读低位再读高位,并且这里将high左移8位是为了正确对齐两个字节的二进制位,确保高字节占据16位整数的高8位,低字节占据低8位。这都是DS18B20数据格式的强制要求。如果反过来读,那得到的数据就是错误的。
这是我配置的效果,显示了环境的温度,如果想让温度变高,可以拿手指捏住温度传感器[黑色帽子一样的,在右上角]大家可以试试。
相关文章:

蓝桥杯_DS18B20温度传感器---新手入门级别超级详细解析
目录 一、引言 DS18B20的原理图 单总线简介: 编辑暂存器简介: DS18B20的温度转换与读取流程 二、代码配置 maic文件 疑问 关于不同格式化输出符号的使用 为什么要rd_temperature()/16.0? onewire.h文件 这个配置为什么要先读lo…...

C++中锁与原子操作的区别及取舍策略
文章目录 锁与原子操作的基本概念锁(Lock)原子操作(Atomic Operations) 锁与原子操作的区别1. **功能**2. **性能**3. **复杂性**4. **适用场景** 锁与原子操作的取舍策略1. **简单变量操作**2. **复杂共享资源**3. **性能敏感场景…...
ESP32对接巴法云实现配网
目录 序言准备工作巴法云注册与使用Arduino准备 开发开始配网 序言 本文部分内容摘抄原创作者巴法云-做优秀的物联网平台 代码有部分修改并测试运行正常 巴法云支持免费用户通过开发对接实现各智能音箱设备语音控制智能家居设备,并有自己的App进行配网和控制&…...
《深度剖析:基于Meta的GameFormer构建自博弈AI游戏代理》
自博弈AI游戏代理,是一种具备自主学习和自我提升能力的人工智能系统。它打破了传统AI依赖预设规则和固定策略的局限,能够在游戏过程中不断与自身进行对战,通过反复博弈来积累经验、优化策略,从而实现智能水平的持续提升 。这种独特…...

C++语法系列之类型转换
前言 类型转换是经常存在的情况,类型转换分为隐式类型转化 和 显式类型转化 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败 double i 3.3; int b i; //隐式类型转化 double -> intC搞出来了四种强制类…...
Qwen3 技术报告解读一
📘 Qwen3 技术报告解读:通义千问系列新成员的技术亮点与能力分析 一、论文写了什么? 本文来自阿里通义实验室发布的 《Qwen3 Technical Report》,介绍了其最新一代大语言模型 Qwen3 的技术架构、训练方法以及在多个关键任务上的…...

详解开漏输出和推挽输出
开漏输出和推挽输出 以上是 GPIO 配置为输出时的内部示意图,我们要关注的其实就是这两个 MOS 管的开关状态,可以组合出四种状态: 两个 MOS 管都关闭时,输出处于一个浮空状态,此时他对其他点的电阻是无穷大的ÿ…...

【八股消消乐】索引失效与优化方法总结
😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本专栏《八股消消乐》旨在记录个人所背的八股文,包括Java/Go开发、Vue开发、系统架构、大模型开发、具身智能、机器学习、深度学习、力扣算法等相关知识点ÿ…...

一步一步配置 Ubuntu Server 的 NodeJS 服务器详细实录——4. 配置服务器终端环境 zsh , oh my zsh, vim
前言 通过前面几篇文章,我们顺利的 安装了 ubuntu server 服务器,并且配置好了 ssh 免密登录服务器,也安装好了 服务器常用软件安装,接下来,我们要仔细的配置一下我们的终端环境,让服务器的终端更加好用。 一般情况下…...

数据安全合规体系构建的“三道防线“
引言 "三道防线"模型架构图 #mermaid-svg-wbeppAbwa3Vb3nL2 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-wbeppAbwa3Vb3nL2 .error-icon{fill:#552222;}#mermaid-svg-wbeppAbwa3Vb3nL2 .error-text{fi…...

【Spring底层分析】Spring AOP基本使用+万字底层源码阅读分析
一、AOP基本使用 三步: 将业务逻辑组件和切面类都加入到容器中,告诉Spring哪个是切面类(Aspect)在切面类上的每一个通知方法上标注通知注解,告诉Spring何时(Before、After、Around……)何地运…...
Python数据分析及可视化中常用的6个库及函数(二)
Python数据分析及可视化中常用的6个库及函数(二) 摘要:以下是Python数据分析及可视化常用的6个库的详细介绍,包括它们的概述以及每个库中最常用的10个函数(如果某些库常用函数不足10个,则列出所有常用函数)。每个函数都附带功能描述、用法说明和使用示例。这些库…...

新德通科技:以创新驱动光通信一体化发展,赋能全球智能互联
在数字经济与AI技术高速发展的今天,光通信作为信息传输的核心基础设施,正迎来前所未有的升级浪潮。深圳新德通科技有限公司(以下简称“新德通科技”)凭借其深厚的技术积累与一体化产品布局,成为行业内的中坚力量。本文…...
Selenium的底层原理
Selenium 底层主要依赖于 WebDriver 协议(即 W3C WebDriver 规范,早期也有 JSON Wire Protocol)来实现对浏览器的远程控制,其核心架构可以分为以下几层: Selenium 客户端(Client Library) 支持多…...
PostgreSQL的扩展 auth_delay
PostgreSQL的扩展 auth_delay auth_delay 是 PostgreSQL 提供的一个安全相关扩展,主要用于防止暴力破解攻击。它通过在认证失败后引入人为延迟来增加暴力破解的难度。 一、扩展基础 功能:在认证失败后增加延迟目的:减缓暴力破解和字典攻击…...
[Java 基础]Java 是什么
Java 是一门编程语言。 查看编程语言热门排行:https://www.tiobe.com/tiobe-index/ Java 的特点: 面向对象:Java 是面向对象的语言,支持封装、继承和多态等特性。 平台无关性:Java 通过“一次编写,到处…...
Qt学习2
跟学视频 1.菜单栏和工具栏 //菜单栏最多只能有一个//菜单栏创建QMenuBar * bar menuBar();//将菜单栏放到窗口中setMenuBar(bar);//创建菜单QMenu * fileMenu bar->addMenu("开始");QMenu * editMenu bar->addMenu("编辑");//创建菜单项QAction…...

C++ 内存泄漏检测器设计
文章目录 1. C中的动态内存分配2. 什么是内存泄漏3. 内存泄漏的代码案例4. 内存泄漏检查器的设计模块1:位置信息捕获:模块2:内存分配跟踪:模块3:内存释放跟踪:模块4:泄漏记录存储:模…...
在 Linux 上安装 Nmap 工具
📦 在 Linux 上安装 Nmap 工具指南 Nmap(Network Mapper)是功能强大的网络扫描工具,以下是各种 Linux 发行版的安装方法: 🧩 通用安装方法 1. 使用包管理器安装(推荐) # Debian/…...
从零打造AI面试系统全栈开发
🤖 AI面试系统开发完整教程 📋 项目概述 本教程将带你从零开始构建一个完整的AI面试系统,包含前端、后端、AI集成和部署的全流程。 源码地址 技术栈 前端: React TypeScript Vite Vaadin Components后端: Spring Boot Spring Securi…...

破局与进阶:ueBIM 在国产 BIM 赛道的差距认知与创新实践
作为国产BIM领域的探索者,斯维尔ueBIM自诞生以来始终以追赶国际头部技术为目标,但不可否认的是,在核心功能覆盖、行业生态成熟度以及全球市场占有率等方面,我们与Autodesk Revit、Bentley Systems等国际巨头仍存在显著差距。这种差…...

分布式流处理与消息传递——向量时钟 (Vector Clocks) 算法详解
Java 实现向量时钟 (Vector Clocks) 算法详解 一、向量时钟核心原理 #mermaid-svg-JcZ1GT0r1ZNSy6W7 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-JcZ1GT0r1ZNSy6W7 .error-icon{fill:#552222;}#mermaid-svg-JcZ…...

20250603在荣品的PRO-RK3566开发板的Android13下的命令行查看RK3566的温度
20250603在荣品的PRO-RK3566开发板的Android13下的命令行查看RK3566的温度 2025/6/3 11:58 RK3566的cpu运行效率 top rk3566_t:/ # rk3566_t:/ # rk3566_t:/ # cd /sys/class/thermal/ rk3566_t:/sys/class/thermal # ls -l rk3566_t:/sys/class/thermal # cd thermal_zone0/ r…...

帝可得 - 设备管理
一. 需求说明 设备管理主要涉及到三个功能模块,业务流程如下: 新增设备类型: 允许管理员定义新的售货机型号,包括其规格和容量。 新增设备: 在新的设备类型定义后,系统应允许添加新的售货机实例,并将它们分配到特定的…...
FTXUI配置
对于 FTXUI 的安装与配置, 官方已经给出了三种方案. 第一种: 使用 FetchContent 远程拉取第二种: 在你本地安装 FTXUI 库, 然后通过 find_package 使用第三种: 使用 Git 子模块 FetchContent 无需手动下载安装 FTXUI, 通过 CMake 自动从 GitHub 拉取并编译依赖 include(Fet…...
Caliper压力测试
目前FISCO BCOS适配的Caliper版本为0.2.0,请在部署Caliper运行环境时确保Caliper的版本为0.2.0,如在部署或使用过程中遇到任何问题,请优先参考 https://github.com/FISCO-BCOS/FISCO-BCOS/issues/1248 中的解决方案进行排查。 1. 环境要求 …...

【iOS安全】使用LLDB调试iOS App | LLDB基本架构 | LLDB安装和配置
LLDB基本架构 参考: https://crifan.github.io/ios_re_dynamic_debug/website/debug_code/lldb_debugserver.html https://book.crifan.org/books/ios_re_debug_debugserver_lldb/website/ LLDB安装和配置 1. 让iPhone中出现/Developer/usr/bin/debugserver 最初…...
一、核心概念深入解析
一、核心概念深入解析 1. shared_ptr 的线程安全性澄清 引用计数是原子操作:shared_ptr 的引用计数(use_count)在多线程中递增 / 递减是安全的(原子操作),但对象本身的读写需额外同步(如 std:…...
python直方图
在Python中,绘制直方图(Histogram)是一项非常常见的任务,通常用于数据可视化,以展示数据的分布情况。Python中有多种库可以绘制直方图,其中最常用的两个库是Matplotlib和Seaborn。此外,Pandas库…...
[特殊字符] Unity 性能优化终极指南 — Text / TextMeshPro 组件篇
UGUI Text组件的不当使用及其性能瓶颈与优化 在Unity UGUI系统中,Text 组件(或其升级版 TextMeshPro)是显示文本信息的核心元素。然而,如果不当使用,它极易成为UI性能瓶颈的罪魁祸首,尤其是在预制体、属性…...