首页 > 其他分享 >15-DS18B20温度传感器的基本应用

15-DS18B20温度传感器的基本应用

时间:2023-10-19 19:23:45浏览次数:37  
标签:温度传感器 15 ROM DS18B20 总线 unsigned circ 温度

DS18B20温度传感器的基本应用

DS18B20是Dallas半导体公司的一款数字温度传感器芯片

DS18B20是一款支持1-wire总线接口的温度传感器

DS18B20的温度范围-55\(^{\circ}\)C-125\(^{\circ}\)C,精度为\(\pm0.5^{\circ}\)C

DS18B20可将分辨率设置为9到12位

DS18B20的工作电压范围3-5.5v

DS18B20内部结构

以下是Dallas半导体的DS18B20结构图

20231019093510

1.电源与寄生电源

  • 正常情况下是从VDD供电一直到内部INTERNAL VDD
  • 如果底下VDD不接,则通过DQ取出电源正极一直通过二极管到内部INTERNAL VDD,通过Cpp电容进行供电
  • Power Supply sense :电源供给感应,感应外部VDD是否存在

2.64位ROM(只读存储器)和单总线Port

  • 作为器件地址,作为总线通信的寻址

3.存储器控制逻辑

4.Scratchpad(高速缓存器)

高速缓存器就是用来存各种数据的,一共可以存9个字节的数据

存的就是5、6、7、8、9这几个模块的数据

20231019100637

5.温度传感器(Temperature LSB and MSB)

Byte0和Byte1存的就是温度,就是传感器已经换算好的数字温度,Byte0是温度的低八位,Byte1是温度的高八位

20231019101338

由上可知上电的复位温度为85\(^{\circ}\)C

也就是055H = 0000 0101 0101 0000=1360,因为默认的分辨率为12位(0.0625\(^{\circ}\)C)所以复位的默认温度位1360*0.0625=85\(^{\circ}\)C

DS18B2016位带符号位扩展的二进制补码形式读出,单位是摄氏度,两个字节一共是16位,温度的换算表格如下:

20231019103322

由上可知:MS BYTE为Byte1即高八位,LS BYTE为Byte0即低八位

高字节的5个S是符号位,S= 1表示温度为正,S=0,表示温度为负

12位分辨率,最后一位是1/16=0.0625,所以最小的温度分辨率是0.0625\(^{\circ}\)C

11位分辨率,最后一位是1/8=0.125,所以最小的温度分辨率是0.125\(^{\circ}\)C

10位分辨率,最后一位是1/4=0.25,所以最小的温度分辨率是0.25\(^{\circ}\)C

9位分辨率,最后一位是1/2=0.5,所以最小的温度分辨率是0.5\(^{\circ}\)C

正温度的读取

因为存的温度是补码,正数的原码和补码是一样的,直接读数

比如+85摄氏度:0000 0101 0101 0000 = 1360(转换为10进制)

将该10进制*分辨率 = 温度,由于默认分辨率位12位即: 1360×0.0625=85

负温度的读取

因为存的温度是补码负数的补码转换位原码步骤为:先取反,再+1

比如-55摄氏度:的补码是:1111 1100 1001 0000 (高5位是符号位)

所以真实的补码为:100 1001 0000;

补码取反之后,再+1;

也就是011 0110 1111 +1=011 0111 0000 =880(十进制)

即真实的温度为880×0.0625=55

如下为几个温度对应的补码:

20231019103334

6-7报警触发寄存器

Byte2对应的是TH,也就是高温报警值,用户自己设置

Byte3对应的是TL,也就是低温报警值,用户自己设置

8.配置寄存器(Conflguration Register (EEPROM))

Byte4对应的计时配置寄存器的值:

配置寄存器是用来配置温度的分辨率,可以把温度的分辨率配置为9bit,10bit,11bit,12bit

分别对应的实际温度分辨率为0.5\(^{\circ}\)C,0.25\(^{\circ}\)C,0.125\(^{\circ}\)C,0.0625\(^{\circ}\)C,默认为12位分辨率(0.0625\(^{\circ}\)C)

配置寄存器的内容如下图:

20231019111108

Byte5、Byte6、Byte7为保留字节

CRC

CRC发生器产生校验码,存在Byte8,是64位ROM中的前56位编码的校验码,由CRC设置

20231019112344

【1】初始化DS18B20

时序如下:

20231019112840

初始化就是先将总线拉高,检查是否存在该温度传感器,如果有总线就会给一个低电平脉冲,如果没有就一直是高电平

也就是说默认给高电平,拉低高电平,然后给一个480us的延迟

然后再拉高,接收给过来的数据,如果为0则有数据过来,为1反之

bit Init_DS18B20(void) {
	
	bit Initflag = 0;
	DQ = 1;
	DS18B20_Delay(5); // 25us
	DQ = 0; // 
	DS18B20_Delay(100);// 500us
	DQ = 1;
	//DS18B20_Delay(5);// 25us
	Initflag = DQ;
	
	DS18B20_Delay(100);
	
	return Initflag;
}

ROM指令

​ 这个ROM指令就是查询DS18B20的64位序列号,相当于设备地址,在多个DS18B20总线连接,需要区分每一个DS18B20设备,如果是单个就不需要查询序列号,但是不查询也要发一条指令0xCC,表示跳过ROM指令

以下是ROM指令集

指令名称 指令代码 指令功能
读ROM 0x33 读DS18B20 ROM中的编码
ROM匹配 0x55 发出次命令之后,接着发出64位的ROM编码,编码匹配的器件会作出回应,接着就可以对该器件进行读写
搜索ROM 0xF0 用于确定总线上器件的个数,并识别ROM编码,为操作器件做准备
跳过ROM 0xCC 忽略ROM编码,直接向器件发温度变换命令
警报搜索 0xEC 这个指令发出之后,如果温度超过了设定的上限或下限,器件才会有所回应

功能指令

指令命令 指令代码 指令功能
温度转换 0x44 启动器件的温度转换,这个转换是需要时间的,转换之后的结果就存在暂存器的Byte1和Byte0中
读暂存器 0xBE 读暂存器全部9个Byte的内容
写暂存器 0x4E 往暂存器Byte4和Byte3写数据,就是设置温度的上限和下限
复制暂存器 0x48 将暂存器Byte4和Byte3的数据复制到EEPROM中
重调EEPROM 0xB8 将EEPROM中的内容恢复到暂存器的Byte4和Byte3中
读供电方式 0xB4 读器件的供电模式,寄生供电时,器件返回0,外接电源供电时,器件返回1

写数据

由于要用到写操作,这边先来介绍下写的时序

20231019125834

DS18B20的数据线只有一根,在这根线上完成读和写,所需要的时序就会比较严格

DS18B20的写时序

MCU往DS18B20写一个BIT的"0"

​ MCU先把总线拉低,拉低时将数据放置到DQ,拉低时需要持续60-120us之间,然后释放总线(释放总线。上拉电阻就把总线拉高了)

MCU往DS18B20写一个BIT的"1"

​ MCU把总线拉低,拉低时间需要大于1us,拉低时将数据放置到DQ,然后在15us内把总线拉高,然后延迟45us走完时序

这边可同时进行,如果对应的位数有1来临,则置一,否则清0

void Write_DS18B20(unsigned char dat) {
	unsigned char i;
	for(i = 0; i < 8;i++) {
		DQ = 0;
		DQ = dat & 0x01;
		DS18B20_Delay(5);
		DQ = 1;
		DS18B20_Delay(10);
		dat >>= 1;
	}
	DS18B20_Delay(5);
	

}

读数据

由于要用到读操作,这边先来介绍下读的时序

读数据

MCU从DS18B20读一个BIT:

MCU先把总线拉低,DS18B20检测到总线被拉低1us后,便开始往外送数据,如果送出的是"0",DS18B20就把

总线拉低,一直读到周期结束,如果送出的是“1” ,就释放总线,让上拉电阻把总线拉高

也就是说先把总线拉低,再拉高,如果DQ为1则将该高位置一,然后再延迟45us,走完时序

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 = dat | 0x80;
		}
		
		DS18B20_Delay(10); 
		
	}
	
	return dat;
}

DS18B20的温度转换与读取流程

  • 【1】DS18B20复位
  • 【2】写入字节0XCC,跳过ROM指令
  • 【3】写入字节0X44,开始温度转换
  • 【4】延时700~900ms
  • 【5】DS18B20复位
  • 【6】写入字节0XCC,跳过ROM指令
  • 【7】写入字节0XBE,读取高速暂存器
  • 【8】读取暂存器的第0字节,即温度数据的LSB
  • 【9】读取暂存器的第1字节,即温度数据的MSB
  • 【10】DS18B20复位,表示读取数据结束

代码如下:

io扩展:

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

// 不带小数点
unsigned char SMGNODot_CA[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
// 带小数点
unsigned char SMGDot_CA[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};

unsigned int temp;
void _74HC138(unsigned char n) {
	switch(n) {
		case 4:
			P2 =(P2&0x1f) | 0x80;
			break;
		case 5:
			P2 =(P2&0x1f) | 0xa0;
			break;
		case 6:
			P2 =(P2&0x1f) | 0xc0;
			break;
		case 7:
			P2 = (P2&0x1f) | 0xe0;
			break;
	}
}
void DelaySMG(unsigned int t) {
	while(t--);
	
}

void DisplaySMG_Bit(unsigned char pos,unsigned char dat) {
	_74HC138(7);
	P0 = 0xff;
	_74HC138(6);
	P0 = 0x01 << pos;
	_74HC138(7);
	P0 = dat;

}


void Display_All(unsigned char dat) {
	_74HC138(6);
	P0 = 0xff;
	_74HC138(7);
	P0 = dat;
}


void Display_SMG_temp(unsigned int temp) {
	DisplaySMG_Bit(7,SMGNODot_CA[temp%10]);
	DelaySMG(500);
	// 567      567/10 == 56 / 10 == 5..6 
	DisplaySMG_Bit(6,SMGDot_CA[(temp/10)%10]);
	DelaySMG(500);
	DisplaySMG_Bit(5,SMGNODot_CA[(temp/100)%10]);
	DelaySMG(500);
	Display_All(0xff); 
}
void Delay(unsigned int t) {
	while(t--) {
		Display_SMG_temp(temp);
		
	}
}
void DS18B20_Reading(void) {
	unsigned char LSB,MSB;
	Init_DS18B20();
	// 跳过ROM
	Write_DS18B20(0xCC);
	// 温度转换
	Write_DS18B20(0x44);
	Delay(1000);
	
	Init_DS18B20();
	// 跳过ROM
	Write_DS18B20(0xCC);
	// 读暂存器
	Write_DS18B20(0xBE);
	
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	Init_DS18B20();
	temp = 0x0000;
	temp = MSB;
	temp = temp << 8 | LSB;
	
	if((temp & 0xf800) == 0x0000) {
		temp >>= 4;
		temp = temp * 10;
		temp = temp + (LSB & 0x0f) *0.625;
	}
	
	
}

void main(void) {
	_74HC138(4);
	P0 = 0xff;
    _74HC138(5);
	P0 = 0x00;
	while(1) {
		DS18B20_Reading();
		Display_SMG_temp(temp);
		
	}
}

存储器映射:

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

// 不带小数点
unsigned char SMGNODot_CA[10] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
// 带小数点
unsigned char SMGDot_CA[10] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};

unsigned int temp;

void DelaySMG(unsigned int t) {
	while(t--);
	
}

void DisplaySMG_Bit(unsigned char pos,unsigned char dat) {
	XBYTE[0xE000] = 0xff;
	XBYTE[0xC000] = 0x01 << pos;
	XBYTE[0xE000] = dat;

}


void Display_All(unsigned char dat) {
	XBYTE[0xC000] = 0xff;
	XBYTE[0xE000] = dat;
}


void Display_SMG_temp(unsigned int temp) {
	DisplaySMG_Bit(7,SMGNODot_CA[temp%10]);
	DelaySMG(500);
	// 567      567/10 == 56 / 10 == 5..6 
	DisplaySMG_Bit(6,SMGDot_CA[(temp/10)%10]);
	DelaySMG(500);
	DisplaySMG_Bit(5,SMGNODot_CA[(temp/100)%10]);
	DelaySMG(500);
	Display_All(0xff); 
}
void Delay(unsigned int t) {
	while(t--) {
		Display_SMG_temp(temp);
		
	}
}
void DS18B20_Reading(void) {
	unsigned char LSB,MSB;
	Init_DS18B20();
	// 跳过ROM
	Write_DS18B20(0xCC);
	// 温度转换
	Write_DS18B20(0x44);
	Delay(1000);
	
	Init_DS18B20();
	// 跳过ROM
	Write_DS18B20(0xCC);
	// 读暂存器
	Write_DS18B20(0xBE);
	
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	Init_DS18B20();
	temp = 0x0000;
	temp = MSB;
	temp = temp << 8 | LSB;
	
	if((temp & 0xf800) == 0x0000) {
		temp >>= 4;
		temp = temp * 10;
		temp = temp + (LSB & 0x0f) *0.625;
	}
	
	
}

void main(void) {
  	XBYTE[0X8000] = 0XFF;
	XBYTE[0Xa000] = 0x00;
    
	while(1) {
		DS18B20_Reading();
		Display_SMG_temp(temp);
		
	}
}

标签:温度传感器,15,ROM,DS18B20,总线,unsigned,circ,温度
From: https://www.cnblogs.com/bky111/p/17775408.html

相关文章

  • P3119 [USACO15JAN] Grass Cownoisseur G 题解
    分析大概是强连通分量里面最水的一道紫题,不过细节挺多的,做题的时候给蒟蒻震惊到了。题目要求是从\(1\)走到某个点,然后再走回\(1\)号点,中途可逆行一次,问最多能经过几个点。有一个明显的思路是存两个图,一个正图一个反图,正图是为了求\(1\)到各个点的距离,反图是为了求各个点......
  • CF1542E2 Abnormal Permutation Pairs (hard version) 题解
    AbnormalPermutationPairs(hardversion)两个限制:字典序小、逆序对大,一个显然的想法就是确保一对关系,统计另一对关系。确保哪一对呢?我们想了想,决定确保字典序小,因为字典序是可以贪心的。具体而言,我们考虑两个排列自第\(i\)位开始出现了不同。这样子,我们便将两个排列各自划......
  • VS2015重构代码结构时出现:【/langversion 的选项“7.3”无效;必须是 ISO-1、ISO-2、3
    重构代码结构时出现:【/langversion的选项“7.3”无效;必须是ISO-1、ISO-2、3或Default在XXXX类库】......
  • P1590 失踪的7
    这么简洁的题目当然不用数位DP啦。将\(n\)搞成\(10\)的幂次之和计算。比如说\(1234\)就拆成\(1\sim4,1\sim30,1\sim200,1\sim1000\)来计算。枚举后缀长度\(i\),除去最高位外剩下每一位都可以填除\(7\)以外的任何数字,所以它的贡献即为\(9^{i-1}\)再乘上最高位能......
  • Educational Codeforces Round 150 (Rated for Div. 2) B. Keep it Beautiful
    数组\(a=[a_1,a_2,\cdots,a_n]\)被称为是美丽的,如果可以将\([1,x]\)段移到\([x+1,n]\)段后面,\(x\geq0\),数组可以构成非降序。现在有一个数组\(a\)(一开始为空)和\(q\)个询问,第\(i\)个询问给一个正整数\(x_i\)。需要逐步执行以下操作。若\(x_i\)拼接......
  • 初学Bokeh:调整绘图大小【15】跬步
    初学Bokeh:调整绘图大小【15】跬步Bokeh中的绘图对象具有多种属性,这些属性会影响绘图的外观。调用figure()函数时使用width和height属性就可以设置绘图的大小:frombokeh.plottingimportfigure,show#preparesomedata#定义绘图数据x=[1,2,3,4,5]y=[4,......
  • 代码训练营第八天(Python)| 344.反转字符串、541. 反转字符串II、05.替换空格、151.翻转
    344.反转字符串双指针法时间复杂度为:O(n),空间复杂度为:O(1)classSolution:defreverseString(self,s:List[str])->None:"""Donotreturnanything,modifysin-placeinstead."""left,right=0,len(s......
  • centOs 6.10 编译 qt 5.15.11.
    centOs6.10编译qt5.15.11安装依赖库xcb依赖库qtxcb需要的依赖如何要用x11,就要在编译的时候加上-xcb选项,就要安装xcb相关的库。到时可以在config.log文件查看,缺少哪个库就安装哪个。下面是我手动安装的库和对应版本:xcb-proto-1.14.tar.gzxcb-util-image-0.......
  • 【前缀和优化 dp】CF1542E2 Abnormal Permutation Pairs (hard version) 题解
    CF1542E2首先时间复杂度肯定是\(\mathcal{O}(n^3)\)的。容易想到先枚举最长公共前缀,然后枚举\(p_{len+1}\)和\(q_{len+1}\),再枚举逆序对数进行统计。令\(f_{i,j}\)表示有\(j\)个逆序对的\(i\)阶排列的个数。易得转移\(f_{i,j}=\sum\limits_{k=\max(j-i+1,0)}^{j}f......
  • 文心一言 VS 讯飞星火 VS chatgpt (115)-- 算法导论10.2 8题
    八、用go语言,说明如何在每个元素仅使用一个指针x.np(而不是通常的两个指针next和prev)的下实现双向链表。假设所有指针的值都可视为k位的整型数,且定义x.np=x.nextXORx.prev,即x.nert和x.prev的k位异或。(NIL的值用0表示。)注意要说明获表头所需的信息,并说明如何在该表上......