锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

传感器自学笔记第十四章——DS18B20温度传感器(附自己写的好用的51单片机单、多路温度采集代码)

时间:2022-08-10 08:30:00 gwd150传感器gwd75传感器gwd90温度传感器数显

作者:GWD 时间:2019.6.30

一、 学习要点:
1.问:为什么在移位操作之前要在阅读操作中赋值,而不是直接对准?DQ移位?
在这里插入图片描述
答:bit只有类型变量不能移位char,int这种可移位操作;
2.问:多点检测试验有18个b20的ROM如果序列号产生9个字节的地址序列怎么办?

答:生产设备bug,删除一个序列后测试(0x0d)正确;
3.问:手册中的精度分辨率为0.0625如何转化为现实中所需的温度?
答:精度分辨率为0.0625意味着传感器检测值每增加1,10进制时大0.0625所以检测值*0.0625是所需的值,乘以100后,百分位小数即使在整数和十位中,也方便打印数据;
4、问:18B20单点采集流程
答:第一步:发送起始信号:
第二步:发送rom指令 0xcc(跳过rom命令);
第三步:发送功能命令0x44(开始转换温度指令);
第四步:发送起始信号;
第五步:发送rom指令 0xcc(跳过rom命令);
第六步:发送功能指令0xbe (读取临存器指令);
第七步:两次阅读18B20值,然后转换;
注:起始信号 rom命令 无论何时操作18,功能指令都是一组B20就要这三组一起不拆开。
5、问:18B采集过程超过20点
答: 第一步:发送起始信号
第二步:发送rom指令 0x33(读取rom命令),读取8字节的值,把这8个char串口助手的变量hex在模式下打印后,存储char[8]数组可以通过这种方式线的18b20的rom值;
第三步:发送功能命令0x44(开始转换温度指令)
第四步:发送起始信号
第五步:发送rom指令 0x55(匹配rom命令),发送命令后跟随8字节rom地址,读哪个18b20就紧跟着哪个器件的地址码;
第六步:发送功能指令0xbe (读取暂存器指令)
第七步:两次阅读18B20值,然后转换。
6、问:hex适用于输出功能?
答:调时程序需要知道程序运行到某个地方时的值,hex打印出16进制值,如18B20查看rom地址时就应该用hex输出模式。
二、手册分析
传感器特性操作流程:


2.通信只需要一个管脚。每个设备的内部 ROM 上都烧写了一个独特的 64 温度可测范围为: -55℃至 125℃(-67℉至 257℉)。用户可以将内部温度采集精度定义为9-Bits 至 12-Bits;
3、引脚定义:

3.内部框图:

1)、内部64位ROM存储第一无二序号;
2)、在1—Wire在总线系统中,
微控制器(主设备)通过每个设备 64 序列号用于识别总线上的设备。因为每个设备都有一个独特的序列号,理论上挂在总线上的设备可以是无限的;
4、DS18B20的另一个特点是无需外部电源即可供电。当数据线 DQ 高时由设备供电。 当总线拉高时,是内部电容 (Spp) 充电, 当总线下降时,电容器向设备供电。 这种由 1-Wire设备供电的总线称为寄生电源。
5、DS18B20的核心功能是直接温度 -数字测量。其温度转换可由用户自定义 9、 10、 11、 12 位精度分别为 0.5℃、 0.25℃、 0.125℃、 0.0625℃分辨率。值得注意的是,默认上电 12 位转换精度。 DS18B20 上电后,工作处于低功耗闲置状态。必须向主设备方向 DS18B20 发送温度转换命令 [44h]开始温度转换。
7. 一个温度数据 16 以扩展二进制补码数的形式存储在温度寄存器中(图2-3)。符号标志位(S)温度的正负极性:正数 S=0,负数则 S=1。如果 DS18B20 被定义为12 温度寄存器中的所有位置都将包含有效数据。若为 11 位转换精度,则 bit 0 未定义。若为 10 位转换精度,则 bit 1 和 bit 0 未定义。 若为 9 位转换精度,则 bit 2、 bit 1和 bit 0 未定义。

12.18B20常用操作:
1)、访问 DS18B20 如下所示:
第一步:初始化DS18B20
第二步: ROM 命令(跟随任何数据交换请求)
第三步: DS18B20 当执行这些功能命令(跟随任何数据交换请求)时 ROM 命令结束后,主设备必须回到上述步骤的第一步。
2)、ROM命令:读取 ROM[33h]:该命令只能在总线上从设备中使用。该命令使总线上的主要设备无需搜索 ROM从设备中读取命令过程 64 位 ROM 编码。 当总线上有超过一个设备时, 如果再次发送命令,当所有设备都会响应时,数据冲突就会发生。
3)、ROM命令: 匹配 ROM[55h]该匹配 ROM 随后发送命令 64 位的 ROM 编码使总线上的主设备与特定的从设备相匹配。只有完全匹配 64 位 ROM 只有从设备编码,才能响应总线上主设备发出的功能命令;总线上的其他从设备将等待下一个复位脉冲。
4)、ROM命令:跳过 ROM[CCh]:主要设备可以使用该命令同时将任何从设备发送到总线的所有设备 ROM 编码命令。例如,主设备通过总线上的所有设备 DS18B20 发送跳过 ROM 发送温度转换命令后,发送温度转换命令 [44h]命令, 所有设备将同时转动温度。
5)、DS18B20 功能命令:温度转换 [44h]该命令是初始化的单次温度转换。温度转换后,存储在临时存储寄存器中的温度转换数据 2 在个字节长度的温度寄存器中,之后 DS18B20 恢复到低功耗的闲置状态。当设备采用外部供电模式时,主设备可以在温度转换命令后执行读取数据时序,
6)、DS18B20 功能命令:读取临时存储器 [BEh]该命令允许主设备读取存储在临时存储器中的值。
7)、18B20时序:初始时序-复位和脉冲存在

8)、 18B20时序:写时序——图2-6)写时段有两种情况: “写 时段和写 0”时段。写主设备 1 时段来向 DS18B20 中写入逻辑 1 以及通过写 0 时段来向 DS18B20 中写入逻辑 0。每个写作时间必须是最小的 60us持续时间和独立写作时间至少有 1us恢复时间(添加小延迟)。主设备通过两个写作时间段 1-Wire 拉低总线进行初始化。
为了形成写 1 时段,在将 1-Wire 总线拉低后,主设备必须在 15us释放总线。
为了形成写 0 时段,在将 1-Wire 总线拉低后,主设备必须一直拉低总线(至少 60us)。
主设备初始化写时段后, DS18B20 将会在 15us至 60us总线在时间窗口采样。如果总线在采样窗口期间电平较高,则逻辑1写入 DS18B20;如果总线电平较低,则逻辑 0 被写入DS18B20。

8)、18B20时序:阅读时序-在读时序期间DS18B将数据传输到主设备。 因此, 主要设备执行暂存储存储器 [BEh]或读取供电模式 [B4h]之后,必须及时生成阅读时间,以便 DS18B20 才提供所需的数据。
此外,主设备可以在执行完转换温度 [44h] 或拷贝 EEPROM[B8h] 命令后生成读时段,以便获得操作信息。每个读时段最小必须有 60us的持续时间且独立的写时段间至少有 1us 的恢复时间。
读时序通过主设备将总线拉低超过 1us再释放总线来实现初始化。(这里注意下类似的时序图可能是某段时序图初始化的意思)当主设备初始化完读时段后,DS18B20 将会向总线发送 0 或者 1。
将总线拉高来发送逻辑 1,将总线拉至低来发77送逻辑 0。当发送完 0 后, DS18B20 将会释放总线,则通过上拉电阻该总线将会恢复到高电平的闲置状态。
从 DS18B20 中输出的数据在初始化读时序后仅有 15us的有效时间。因此,主设备在开始读时段后的 15us之内必须释放总线,并且对总线进行采样。系统的时序正确保证即是保持Tinit、Trc尽可能的短,同时主设备必须在读时段开始 15us时间内采样。

三:编程
1、一路采集温度
1)、代码功能:实现18B20的一路温度采集
2)、代码效果:

3)、代码:
Main.c

#include                  
#include "stdio.h"
#include "delay.h"
#include "intrins.h"
#include "18b20.h"
#include "LCD1602.h"

/*
作者:宫伟迪
时间:19.06.30
功能:实现18B20温度传感器的单路温度采集,在1602显示和串口打印
*/

typedef unsigned char uChar8;
typedef unsigned int uInt16;

void InitUART  (void)
{
    SCON  = 0x50;		        // SCON: 模式 1, 8-bit UART, 使能接收  
    TMOD |= 0x25;               // TMOD: timer 1, mode 2, 8-bit 重装								//       timer 0,16位计数
	TR0=0;
   	TL0 = 0;
   	TH0 = 0;
    TH1   = 0xF4;               // TH1:  重装值 9600 波特率 晶振 11.0592MHz  
    TR1   = 1;                  // TR1:  timer 1 打开                         
    EA    = 1;                  //打开总中断
    ES    = 1;                  //打开串口中断
	TI=1;
} 
                     
void main (void)
{
	unsigned char tem_h,tem_l,bai,shi,ge,shifen,baifen;
	int temp;
	char *p = "temp1:";
	float j=0;
	InitUART( );
	LCD1602_Init( );
	while (1)                       
	{	
		Delay200ms(); Delay200ms();Delay200ms();
		DS18B20_Start();//18b20开始信号
		DS18B20_Wr_Onebyte(0xCC);//发送跳过ROM的ROM命令
		DS18B20_Wr_Onebyte(0x44);//发送开始转换温度的ROM命令
		DS18B20_Start();
		DS18B20_Wr_Onebyte(0xCC);
		DS18B20_Wr_Onebyte(0xBE);
		tem_l = DS18B20_Rd_Onebytr();
		tem_h = DS18B20_Rd_Onebytr();
		temp = tem_h;
		temp <<= 8;
		temp |= tem_l;
		if( temp < 0 )
		{
			temp = temp - 1;
			temp = ~temp;
		}
			j = temp;
			temp = j * 0.0625 * 100 + 0.5;
			bai = (temp / 10000) + '0';
			shi = (temp % 10000/1000) + '0';
			ge  = (temp % 1000/100) + '0';
			shifen  = (temp % 100/10) + '0';
			baifen  = temp % 10 + '0';
		printf("%c%c%c%c%c\n\r",shi,ge,'.',shifen,baifen);
		Display_StrOnLcd1602(0,0,p);
		Display_CharOnLcd(6,0,shi);
		Display_CharOnLcd(7,0,ge);
		Display_CharOnLcd(8,0,'.');
		Display_CharOnLcd(9,0,shifen);
		Display_CharOnLcd(10,0,baifen);
	}
}

18B20.C

#include "18b20.h"
#include "intrins.h"

/*
作者:宫伟迪
时间:19.06.30
功能:实现18B20温度传感器的单路温度采集,在1602显示和串口打印
*/

void DS18B20_Start()
{
	DQ = 1;
	_nop_();
	DQ = 0;
	DelayXus(80);
    DQ = 1;
	DelayXus(7);
	while(0 == DQ);
	DQ = 1;
}

void DS18B20_Wr_Onebyte(unsigned char dat)  //先写低位
{
	unsigned char i = 0,j=0;
	for(i=0;i < 8;i++)
	{
		DQ=0;
		_nop_();
		DQ = dat & 0x01;
		DelayXus(10);//error1采样器件器件采集自己的就行,主机什么也不用干。
		DQ = 1;
		dat >>= 1;
	}
}

unsigned char DS18B20_Rd_Onebytr(void)	   //先读低位
{
	unsigned char i,j,dat;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		_nop_();
		DQ = 1;
		j = DQ;
		_nop_();
		_nop_();;
		dat = (dat>>1)|(j<<7);
		DelayXus(5);
		DQ = 1;
	}
	return dat;
}

2、多路采集温度
1)、代码功能:实现通过单总线访问rom地址的方法实现18b20的多点温度采集(实验中是3点,只买了3个18B20),使用时候要先检测新加入的18b20的rom地址,然后加入新的数组中就可以了。
2)、程序效果:


3)、代码
Main.c

#include  //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义                        
#include "stdio.h"
#include "delay.h"
#include "intrins.h"
#include "18b20.h"
#include "LCD1602.h"

/*
作者:宫伟迪
时间:19.06.30
功能:实现18B20温度传感器的单路温度采集,在1602显示和串口打印
*/

typedef unsigned char uChar8;
typedef unsigned int uInt16;

void InitUART  (void)
{
    SCON  = 0x50;		        // SCON: 模式 1, 8-bit UART, 使能接收  
    TMOD |= 0x25;               // TMOD: timer 1, mode 2, 8-bit 重装								//       timer 0,16位计数
	TR0=0;
   	TL0 = 0;
   	TH0 = 0;
    TH1   = 0xF4;               // TH1:  重装值 9600 波特率 晶振 11.0592MHz  
    TR1   = 1;                  // TR1:  timer 1 打开                         
    EA    = 1;                  //打开总中断
    ES    = 1;                  //打开串口中断
	TI=1;
} 
                     
void main (void)
{
	unsigned char i,tem_h,tem_l,bai,shi,ge,shifen,baifen;
	int temp;
	char *p1 = "1:";
	char *p2 = "2:";
	char *p3 = "3:";
	char rom_1[8]={0x28,0xFF,0x2D,0x86,0x67,0x18,0x01,0x97};//第三个18B20
	char rom_2[8]={0X28,0X00,0X4E,0X45,0X92,0X17,0X02,0X6D};
	char rom_3[8]={0x28,0x30,0x5F,0x45,0x92,/*0x0D,*/0x0A,0x02,0x54};	 
	float j=0;
	InitUART( );
	LCD1602_Init( );
	while (1)                       
	{
		DS18B20_Start();//18b20开始信号
		DS18B20_Wr_Onebyte(0xcc);//发送跳过ROM的ROM命令
		DS18B20_Wr_Onebyte(0x44);
		DS18B20_Start();//18b20开始信号
		DS18B20_Wr_Onebyte(0x55);//发送匹配ROM命令
		for(i=0;i<8;i++)
		{
			DS18B20_Wr_Onebyte(rom_1[i]);
		}
		DS18B20_Wr_Onebyte(0xBE);
		tem_l = DS18B20_Rd_Onebytr();
		tem_h = DS18B20_Rd_Onebytr();
		temp = tem_h;
		temp <<= 8;
		temp |= tem_l;
		if( temp < 0 )
		{
			temp = temp - 1;
			temp = ~temp;
		}
			j = temp;
			temp = j * 0.0625 * 100 + 0.5;
			bai = (temp / 10000) + '0';
			shi = (temp % 10000/1000) + '0';
			ge  = (temp % 1000/100) + '0';
			shifen  = (temp % 100/10) + '0';
			baifen  = temp % 10 + '0';
		Display_StrOnLcd1602(0,0,p1);
		Display_CharOnLcd(2,0,shi);
		Display_CharOnLcd(3,0,ge);
		Display_CharOnLcd(4,0,'.');
		Display_CharOnLcd(5,0,shifen);
		Display_CharOnLcd(6,0,baifen);

		DS18B20_Start();//18b20开始信号
		DS18B20_Wr_Onebyte(0xcc);//发送跳过ROM的ROM命令
		DS18B20_Wr_Onebyte(0x44);
		DS18B20_Start();//18b20开始信号
		DS18B20_Wr_Onebyte(0x55);//发送匹配ROM命令
		for(i=0;i<8;i++)
		{
			DS18B20_Wr_Onebyte(rom_2[i]);
		}
		DS18B20_Wr_Onebyte(0xBE);
		tem_l = DS18B20_Rd_Onebytr();
		tem_h = DS18B20_Rd_Onebytr();
		temp = tem_h;
		temp <<= 8;
		temp |= tem_l;
		if( temp < 0 )
		{
			temp = temp - 1;
			temp = ~temp;
		}
			j = temp;
			temp = j * 0.0625 * 100 + 0.5;
			bai = (temp / 10000) + '0';
			shi = (temp % 10000/1000) + '0';
			ge  = (temp % 1000/100) + '0';
			shifen  = (temp % 100/10) + '0';
			baifen  = temp % 10 + '0';
		Display_StrOnLcd1602(0,1,p2);
		Display_CharOnLcd(2,1,shi);
		Display_CharOnLcd(3,1,ge);
		Display_CharOnLcd(4,1,'.');
		Display_CharOnLcd(5,1,shifen);
		Display_CharOnLcd(6,1,baifen);


        DS18B20_Start();//18b20开始信号
		DS18B20_Wr_Onebyte(0xcc);//发送跳过ROM的ROM命令
//		for(i=0;i<8;i++)
//		{
//			rom_3[i]  = DS18B20_Rd_Onebytr();
//		}
//		for(i=0;i<8;i++)
//		{
//		printf("%c",rom_3[i]);
//		} 
//		while(1);
		DS18B20_Wr_Onebyte(0x44);
		DS18B20_Start();//18b20开始信号
		DS18B20_Wr_Onebyte(0x55);//发送匹配ROM命令
		for(i=0;i<8;i++)
		{
			DS18B20_Wr_Onebyte(rom_3[i]);
		}
		DS18B20_Wr_Onebyte(0xBE);
		tem_l = DS18B20_Rd_Onebytr();
		tem_h = DS18B20_Rd_Onebytr();
		temp = tem_h;
		temp <<= 8;
		temp |= tem_l;
		if( temp < 0 )
		{
			temp = temp - 1;
			temp = ~temp;
		}
			j = temp;
			temp = j * 0.0625 * 100 + 0.5;
			bai = (temp / 10000) + '0';
			shi = (temp % 10000/1000) + '0';
			ge  = (temp % 1000/100) + '0';
			shifen  = (temp % 100/10) + '0';
			baifen  = temp % 10 + '0';
		Display_StrOnLcd1602(9,0,p3);
		Display_CharOnLcd(11,0,shi);
		Display_CharOnLcd(12,0,ge);
		Display_CharOnLcd(13,0,'.');
		Display_CharOnLcd(14,0,shifen);
		Display_CharOnLcd(15,0,baifen);
	}
}


代码下载地址:
链接:https://pan.baidu.com/s/1Knmk850_Sxmohf-Gkon2ow
提取码:wf1v

锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章