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

发布时间 2023-10-19 19:13:37作者: 夏日清凉~

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);
		
	}
}