【C51入门笔记】单总线协议+DS18B20

DS18B20芯片:

简介:

vDS18B20DALLAS公司生产的一种“单总线”温度传感器,它采用独特的单线接口方式,仅需要一个端口引脚来发送或接收信息,在MCUDS18B20之间仅需一条数据线。

v每个DS18B20都有一个唯一的ROM序列号,所以可以将多只DS18B20同时连在一根单总线上,进行简单的多点分布应用。

vDS18B20极为小巧,大小和一个普通的三极管相当,所以在温度测量方面有着比较广泛的应用,包括温度控制,工业系统,消费电子,温度计已经其他的一下热感测系统。

vDS18B20内部有三个主要数字部件:64位激光ROM,温度传感器,非易失性温度报警触发器TH和TL。

vDS18B20可以采用寄生电源方式工作,从单总线(对线负载要求高)上汲取能量,在信号线处于高电平期间把能量储存在内部电容里,在信号线处于低电平期间小号电容上的电能工作,直到高电平到来再给寄生电源充电。(DS18B20也可以用外部电源35.5V电源供电。)

操作指令:

ROM指令(read-only-memory):

DS18B20依靠一个单总线端口通信,必须先建立ROM操作协议,才能进行存储器和控制操作。​​​​

因此主机(MCU)必须首先提供下面5个ROM操作命令之一:

v读出ROM,代码为33H,用于读出DS18B20的序列号,即64位激光ROM代码。

v匹配ROM,代码为55H,用于识别(或选中)某一特定的DS18B20进行操作。

v搜索ROM,代码为F0H,用于确定总线上的节点数以及所有节点的序列号。

v跳过ROM,代码为CCH,命令发出后系统将对所有DS18B20进行操作,通常用于启动所有DS18B20转换之前,或系统中仅有一个DS18B20时

v报警搜索,代码为ECH,主要用于鉴别和定位系统中超出程序设定的报警温度界限的节点。

存储器操作指令:

v温度转换,代码为44H,用于启动DS18B20进行温度测量,温度转换命令被执行后DS18B20保持等待状态。如果主机在这条命令之后跟着发出读时间隙,而DS18B20又忙于做温度转换的话,DS18B20将在总线上输出“0”,若温度转换完成,则输出“1”。

v读暂存器,代码为BEH,用于读取暂存器中的内容,从字节0开始最多可以读取9个字节,如果不想读完所有字节,主机可以在任何时间发出复位命令来终止读取。

v写暂存器,代码为4EH,  用于将数据写入到DS18B20暂存器的地址2和地址3THTL字节)。可以在任何时刻发出复位命令来终止写入。

v复制暂存器,代码为48H,用于将暂存器的内容复制到DS18B20的非易失性E2RAM,即把温度报警触发字节存入到非易失性存储器里。

v重读E2RAM,代码为B8H,用于将存储在非易失性E2RAM中的内容重新读入到暂存器中。

v读电源,代码为B4H,用于将DS18B20的供电方式信号发送到主机。若在这条命令发出之后发出读时间隙,DS18B20将返回它的供电方式:“0”=寄生电源,“1”=外部电源。

数据手册:

 

0:温度低

1:温度高

2:报警温度低(防止掉电)

3:报警温度高(防止掉电)

4:精度匹配(防止掉电)

5——7:保留

8:CRC校验

时序图:

初始化:判断是否有DS18B2

空闲(因为上拉电阻 所以VCC)——拉低一段时间——自己回到高电平(等待一段时间)——芯片拉低电平(此时采样)

读时序图:

写时序图:

 

读时隙与写时隙:

读时隙

v读时隙:从DS18B20读取数据时,主机生产读时间隙。当主机把数据线从逻辑高电平拉到逻辑低电平时,读时间隙开始。数据线必须保持至少1us;从DS18B20输出的数据在读时间隙的下降沿出现后15us内有效。因此,主机在读时间隙开始后必须停止把DQ引脚驱动为低电平15us,以读取I/O脚状态。在读时间隙的结尾,DQ引脚将被外部上拉电阻拉到高电平。所有读时间隙最少必须60us,包括两个读周期时间和至少1us的恢复时间。

写时隙:

v写时隙:当主机把数据线从逻辑高电平拉到逻辑低电平的时候,写时间隙开始。有两种写时间隙:写1的时间隙和写0时间隙。所有写时间隙必须最少持续60us,包括两个写周期间至少1us的恢复时间。DQ引脚上的电平变低后,DS18B20在一个15us60us的时间窗口内对DQ引脚采样。如果DQ引脚是高电平,就是写1,如果DQ引脚是低电平,就是写0。主机要生成一个写1时间隙,必须把数据线拉到低电平然后释放,在写时间隙开始后的15us内允许数据线拉到高电平。主机要生成一个写0时间隙,必须把数据线拉到低电平并保持60us

#include<reg52.h>
#define uchar unsigned char 
#define uint unsigned int 

sbit DQ=P2^2;

sbit smg1=P2^4;
sbit smg2=P2^5;
sbit smg3=P2^6;

uchar temp;
unsigned char code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};

//初始化
void init_ds18b20(void);
// 延时
void delay(uint t);
// 读写字节data
void write_byte(uchar dat);
uchar read_byte(void);
// 温度
uchar readtemperature(void);
// 显示
void display(void);

void delay_50us(uint t)
{
	uchar j;
	for(;t>0;t--)
        for(j=19;j>0;j--);
}
void delay(uint t)
{
	while(t--);	
}
void init_ds18b20(void)
{
	uchar n;
	DQ=1;
	delay(8);
	DQ=0;
	delay(80);
	DQ=1;
	delay(8);
	n=DQ;//采样,这里就不返回n判断了
	delay(4);

}
void write_byte(uchar dat)
{
	uchar i;
	for(i=0;i<8;i++)
	{
		DQ=0;
		DQ=dat&0x01;//从最低位写
		delay(4);
		DQ=1;
		dat>>=1;
	}
	delay(4);
}

uchar read_byte(void)
{
	uchar i,value;
	for(i=0;i<8;i++)
	{
		DQ=0;
		value>>=1;
		DQ=1;
		if(DQ)
		value|=0x80;
		delay(4);

	}
	return value;
}
uchar readtemperature(void)
{
	uchar a,b;
	
	init_ds18b20();
	write_byte(0xcc);	//跳过ROM
	write_byte(0x44);	//启动温度测量
	delay(300);

	init_ds18b20();
	write_byte(0xcc);
	write_byte(0xbe);
	a=read_byte();
	b=read_byte();
	
	b<<=4;
	b+=(a&0xf0)>>4;//跳过小数点
	return b;

}
void display(void)
{

	smg3=0;
	smg2=0;
	smg1=0;
	P1=smg_du[temp%10];
	delay_50us(20);
	smg2=0;
	smg1=1;
	P1=smg_du[temp/10];
	delay_50us(20);
			
}
void main(void)
{
	while(1){
		temp=readtemperature();
		display();
	}
}





 

 

没有更多推荐了,返回首页