蓝桥杯_DS18B20温度传感器---新手入门级别超级详细解析

article/2025/6/8 9:59:10

目录

一、引言

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数据格式的强制要求。如果反过来读,那得到的数据就是错误的。

这是我配置的效果,显示了环境的温度,如果想让温度变高,可以拿手指捏住温度传感器[黑色帽子一样的,在右上角]大家可以试试。


        


http://www.hkcw.cn/article/BwWaaGgaHc.shtml

相关文章

SuperMap GIS基础产品FAQ集锦(20250603)

一、SuperMap iDesktopX 问题1&#xff1a;这种投影坐标如何转换成China_2000的&#xff1f; 11.2.0 【解决办法】在数据源属性中&#xff0c;选择坐标系下的投影转换&#xff0c;然后指定转换结果的坐标系为China_2000 问题2&#xff1a;SuperMap iDesktopX 影像导出时&am…

【js 图片批量自定义打包下载】

压缩图片打包本地下载 一、依赖安转二、函数封装三、打包压缩四、应用五、示例图 一、依赖安转 打包工具 npm install file-saver --save npm install jszip --save二、函数封装 对图片进行处理 function getBase64Image(src) {return new Promise((resolve, reject) > …

如何轻松地将数据从 iPhone传输到iPhone 16

对升级到 iPhone 16 感到兴奋吗&#xff1f;恭喜&#xff01;然而&#xff0c;除了兴奋之外&#xff0c;学习如何将数据从 iPhone 传输到 iPhone 16 也很重要。毕竟&#xff0c;那些重要的联系人、笔记等都是不可或缺的。为了实现轻松的iPhone 到 iPhone 传输&#xff0c;我们总…

Adobe Acrobat——设置PDF打印页面的大小

1. 打开 PDF 文件&#xff1b; 2. 点击菜单栏的 “文件” → “打印”&#xff1b; 3. 在打印对话框中&#xff0c;点击 “属性”&#xff1b; 4. 点击 “布局”→ “高级”&#xff1b; 5. 点击 “纸张规格”&#xff0c;选择 “PostScript 自定义页面大小”&#xff0c;然后…

胜牌™全球成为2026年FIFA世界杯™官方赞助商

胜牌全球将首次与国际足联&#xff08;FIFA&#xff09;旗舰赛事建立合作关系。 此次赞助恰逢美国首个润滑油品牌即将迎来160周年之际&#xff0c;其国际扩张步伐正在加快。 在这项全球顶级赛事筹备期间&#xff0c;胜牌全球将通过各种富有创意的零售和体验活动与球迷互动。 …

mpg123在MSVC编译器中使用。

官网下载&#xff1a; 下载后打开以下窗口程序&#xff1a; 在此窗口程序中打开所下载的mpg123文件夹。在此文件夹中输入以下命令&#xff1a; dumpbin /EXPORTS libsyn123-0.dll > libsyn123-0.exports lib /DEF:libsyn123-0.def /OUT:libsyn123-0.lib /MACHINE:x64其中…

【LangServe部署流程】5 分钟部署你的 AI 服务

目录 一、LangServe简介 二、环境准备 1. 安装必要依赖 2. 编写一个 LangChain 可运行链&#xff08;Runnable&#xff09; 3. 启动 LangServe 服务 4. 启动服务 5. 使用 API 进行调用 三、可选&#xff1a;访问交互式 Swagger 文档 四、基于 LangServe 的 RAG 应用部…

苍穹外卖--HttpClient

1.介绍 HttpClient是Apache Jakarta Common下的子项目&#xff0c;可以用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包&#xff0c;并且它支持HTTP协议最新的版本和建议 依赖&#xff1a; 核心API&#xff1a; ①HTTPClient ②HTTPClients ③Closeabl…

最佳实践 | 璞华易研“PLM+AI智能研发平台”,助力汉旸科技实现高新材料“数据驱动研发”

合作动态 | PURVAR 日前&#xff0c;汉旸科技与璞华科技达成战略合作&#xff0c;正式引入璞华易研PLMAI智能研发平台。双方基于行业技术需求与数字化转型目标&#xff0c;快速完成研发全流程数字化管理框架的顶层设计与蓝图规划&#xff0c;为技术迭代与产品创新奠定坚实的数…

MongoDB数据库学习

学习链接&#xff1a;https://www.runoob.com/mongodb/mongodb-tutorial.html 图解MongoDB数据库学习路线指南 MongoDB初级 1. 基本概念学习 一定要记住的概念&#xff1a; 文档是一组键值(key-value)对(即 BSON)。 集合就是 MongoDB 文档组&#xff0c;类似于 RDBMS &…

软考 系统架构设计师系列知识点之杂项集萃(79)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;78&#xff09; 第141题 软件测试一般分为两个大类&#xff1a;动态测试和静态测试。前者通过运行程序发现错误&#xff0c;包括&#xff08;&#xff09;等方法&#xff1b;后者采用人工和计算机…

分布式拜占庭容错算法——PBFT算法深度解析

Java 实现PBFT算法深度解析 一、PBFT核心流程 #mermaid-svg-3DQWQzd1C7QGWkMv {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3DQWQzd1C7QGWkMv .error-icon{fill:#552222;}#mermaid-svg-3DQWQzd1C7QGWkMv .error-…

【LUT技术专题】图像自适应3DLUT代码讲解

本文是对图像自适应3DLUT技术的代码解读&#xff0c;原文解读请看图像自适应3DLUT文章讲解 1、原文概要 结合3D LUT和CNN&#xff0c;使用成对和非成对的数据集进行训练&#xff0c;训练后能够完成自动的图像增强&#xff0c;同时还可以做到极低的资源消耗。下图为整个模型的…

Docker 在 AI 开发中的实践:GPU 支持与深度学习环境的容器化

人工智能(AI)和机器学习(ML),特别是深度学习,正以前所未有的速度发展。然而,AI 模型的开发和部署并非易事。开发者常常面临复杂的依赖管理(如 Python 版本、TensorFlow/PyTorch 版本、CUDA、cuDNN)、异构硬件(CPU 和 GPU)支持以及环境复现困难等痛点。这些挑战严重阻…

COMSOL多边形骨料堆积混凝土水化热传热模拟

混凝土水化热温降研究对保障结构安全与耐久性至关重要&#xff0c;温升后温差易引发温度应力&#xff0c;导致裂缝。本案例介绍在COMSOL内建立多边形骨料堆积混凝土细观模型&#xff0c;并对水化热产生后的传热及温度变化进行仿真模拟。 骨料堆积混凝土细观模型采用CAD多边形…

vue入门环境搭建及demo运行

提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 vue简介&#xff1a;第一步&#xff1a;安装node.jsnode简介第二步&#xff1a;安装vue.js第三步&#xff1a;安装vue-cli工具第四步 &#xff1a;安装webpack第五步…

OpenCV CUDA模块图像处理------图像融合函数blendLinear()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该函数执行 线性融合&#xff08;加权平均&#xff09; 两个图像 img1 和 img2&#xff0c;使用对应的权重图 weights1 和 weights2。 融合公式…

“packageManager“: “pnpm@9.6.0“ 配置如何正确启动项目?

今天在学习开源项目的时候&#xff0c;在安装依赖时遇到了一个报错 yarn add pnpm9.6.0 error This projects package.json defines "packageManager": "yarnpnpm9.6.0". However the current global version of Yarn is 1.22.22.Presence of the "…

物联网数据归档之数据存储方案选择分析

在上一篇文章中《物联网数据归档方案选择分析》中凯哥分析了归档设计的两种方案,并对两种方案进行了对比。这篇文章咱们就来分析分析,归档后数据应该存储在哪里?及存储方案对比。 这里就选择常用的mysql及taos数据库来存储归档后的数据吧。 你在处理设备归档表存储方案时对…