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

news/2025/10/5 8:54:24/文章来源:https://www.cnblogs.com/ljbguanli/p/19126245

实用指南:蓝桥杯_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 #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.000MHz	 EA = 1;			Set_Rtc(ucRtc);//设置RTC时间,23-59-55			 while(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.2f								case 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 0011			break;		case 1:			ucLed =0x0c;//让L3,L4两个亮		0000 1100			break;		case 2:			ucLed =0x30;//让L5,L6两个亮		0011 0000			break;	}	}//温度,时钟,系统运行时

疑问

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     void Delay_OneWire(unsigned int t)  //STC89C52RC{	t *=12;	while(t--);}  void Write_DS18B20(unsigned char dat){	unsigned char i;	for(i=0;i>= 1;	}	Delay_OneWire(5);}  unsigned char Read_DS18B20(void){	unsigned char i;	unsigned char dat;  	for(i=0;i>= 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);//Ìø¹ýROM	Write_DS18B20(0x44);//ת»»ÎÂ¶È 	init_ds18b20();	Write_DS18B20(0xcc);//Ìø¹ýROM	Write_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.mzph.cn/news/928051.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实用指南:【25软考网工】第十章 网络规划与设计(1)综合布线

实用指南:【25软考网工】第十章 网络规划与设计(1)综合布线pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Con…

2025.10.4 刷题

2025.10.4 刷题1. P13270 【模板】最小表示法 换模版了,听说卡了 SA 正解是线性的 看题解里还有 log 的倍增哈希,学到了 正解暴力比较两个字符串第一位不同,这样劣的那个字符串,以其每一个字符起始的字符串都劣,同…

TDengine 运维——巡检工具(定期检查) - 指南

TDengine 运维——巡检工具(定期检查) - 指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

[ABC398G] Not Only Tree Game

因为不存在奇环,所以显然构成一个二分图。 我们进行一些变量的定义:\(x\) 表示在满足添加了之后不改变图的联通性且不产生奇环的情况下,可以添加的变数。 \(ee\) 表示两侧都是偶数个节点的联通块的数量。 \(oo\) 表…

邯郸网站建设浩森宇特外贸网站建站n

代理模式是一种结构型设计模式&#xff0c;让开发者能够提供对象的替代品或其占位符。代理对象控制着对于原对象的访问&#xff0c;并允许在将请求提交给原对象前后进行一些处理。代理模式为原对象提供一种代理以控制对这个对象的访问&#xff0c;并由代理对象控制对原对象的引…

Linux 的编辑器--vim - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

深入解析:Java基础(二):八种基本数据类型详解

深入解析:Java基础(二):八种基本数据类型详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

电子商务公司网站设计wordpress标签归档

BeanFactoryPostProcessor和BeanPostProcessor这两个接口都是初始化bean时对外暴露的入口之一&#xff0c;和Aware类似&#xff08;PS:关于spring的hook可以看看Spring钩子方法和钩子接口的使用详解讲的蛮详细&#xff09;本文也主要是学习具体的钩子的细节&#xff0c;以便于实…

上海网站建设服务是什么网络企业网站建设方案

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、方法的概念1、什么是方法&#xff1f;2、方法的定义3、方法调用的过程 二、方法重载1、重载的概念2、方法签名 在日常生活中…

邯郸专业网站建设报价某qq非主流个性网源码qq空间网站源码dede内核+采集规则

目录 一.部署单体项目 1.远程数据库 1.1远程连接数据库 1.2 新建数据库运行sql文件 2.部署项目到服务器中 3.启动服务器运行 二.部署前后端分离项目 1.远程数据库和部署到服务器 2.利用node环境启动前端项目 3.解决主机无法解析服务器localhost问题 方法一 ​编辑 方法二 一.部…

用什么做视频网站比较好的网站右键禁止

非线性容器实现能快速查找的数据结构&#xff0c;其底层通过 hash 或者红黑树实现&#xff0c;包括 HashMap、HashSet、TreeMap、TreeSet、LightWeightMap、LightWeightSet、PlainArray 七种。非线性容器中的 key 及 value 的类型均满足 ECMA 标准。 HashMap HashMap 可用来存…

越秀凭一己之力打破了行业天花板 - 智慧园区

近几年,房地产市场的供需关系已经发生深刻变化,整个行业都在研究怎么能在营销上作出突围。在这个过程中,数字营销几乎成了必选项。 然而,即使布局了数字营销业务,许多 房企面临的营销困境还是在加深 ,明源君认为…

贷款公司网站模板建app需要多少钱

定义 存储器单位时间内读出/写入的位数或字节数 单位 单位是bps&#xff08;位/秒&#xff09;或B/s&#xff08;字节/秒&#xff09; 计算公式 基于存储器时频率和数据总线位数的计算方法 公式&#xff1a;带宽 存储器时频率 存储器数据总线位数 / 8 基于存取周期和每…

详细介绍:静态资源js,css免费CDN服务比较

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

如何做qq钓鱼网站深圳网页设计公司在哪

文章首发于公众号「码上GIS」&#xff0c;欢迎关注。文中流向图和城市关系强度图的 ArcMap 10.5 Mxd 工程和数据可在公众号后台回复「190708」和「190709」获取不记得是从哪年开始&#xff0c;每年春运期间&#xff0c;百度都会发布个春运大数据&#xff0c;其中最让人印象深刻…

在AI技术唾手可得的时代,挖掘JavaScript学习资源的新需求成为关键

本文分析了一个广受欢迎的JavaScript学习资源库,该项目系统整理了33个核心JavaScript概念的学习资料,涵盖了从基础数据类型到高级设计模式的完整知识体系,为开发者提供了全面的学习路径和参考资料。a.内容描述核心功…

网站模板网站wordpress手机号网站

前言&#xff1a; 子窗口控件是特殊的子窗口&#xff0c;不需要我们注册窗口类&#xff0c;系统已经注册好了&#xff0c;我们只需要在创建时选择相应的窗口类名。常用的子窗口控件有按钮BUTTON、组合框COMBOBOX、编辑框EDIT、列表框LISTBOX、静态框STATIC、滚动条SCROLLBAR等类…

做生意网站wordpress 栏目页

符号在前就先加/减&#xff0c;符号在后就后加/减 在写代码的过程中&#xff0c;常见的一种情况是需要某个整数类型变量增加 1 或减少 1&#xff0c;Java 提供了一种特殊的运算符&#xff0c;用于这种表达式&#xff0c;叫做自增运算符&#xff08;)和自减运算符&#xff0…

洛谷P9676 [ICPC 2022 Jinan R] Skills

洛谷P9676 [ICPC 2022 Jinan R] Skills P9676 [ICPC 2022 Jinan R] Skills 设计状态时,可以知道要用当前的压掉一维,\(dp_{i,j,0/1/2}\) 表示当前选第 \(0/1/2\) 种,\(i,j\) 表示其余两种的最后选择时间。 如果没有…