1-Wire程序

DS18B20程序-超详细注释

#include

#include

#define uchar unsigned char

#define uint unsigned int

sbit DQ = P2^2; //数据口define interface

sbit dula = P2^6; //数码管段选

sbit wela = P2^7; //数码管位选

uint temp; //温度值 variable of temperature

//不带小数点

unsigned char code table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,

0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

//带小数点

unsigned char code table1[] =

{0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};

/*************精确延时函数*****************/

void delay(unsigned char i)

{

while(--i);

}

/******************************************

此延时函数针对的是12Mhz的晶振

delay(0):延时518us 误差:518-2*256=6

delay(1):延时7us (原帖写"5us"是错的)

delay(10):延时25us 误差:25-20=5

delay(20):延时45us 误差:45-40=5

delay(100):延时205us 误差:205-200=5

delay(200):延时405us 误差:405-400=5

*******************************************/

/*****************DS18B20******************/

void Init_Ds18b20(void) //DS18B20初始化send reset and initialization command

{

DQ = 1; //DQ复位,不要也可行。

delay(1); //稍做延时

DQ = 0; //单片机拉低总线

delay(250); //精确延时,维持至少480us

DQ = 1; //释放总线,即拉高了总线

delay(100); //此处延时有足够,确保能让DS18B20发出存在脉冲。

}

uchar Read_One_Byte() //读取一个字节的数据read a byte date

//读数据时,数据以字节的最低有效位先从总线移出

{

uchar i = 0;

uchar dat = 0;

for(i=8;i>0;i--)

{

DQ = 0; //将总线拉低,要在1us之后释放总线

//单片机要在此下降沿后的15us内读数据才会有效。

_nop_(); //至少维持了1us,表示读时序开始

dat >>= 1; //让从总线上读到的位数据,依次从高位移动到低位。

DQ = 1; //释放总线,此后DS18B20会控制总线,把数据传输到总线上

delay(1); //延时7us,此处参照推荐的读时序图,尽量把控制器采样时间放到读时序后的15us内的最后部分

if(DQ) //控制器进行采样

{

dat |= 0x80; //若总线为1,即DQ为1,那就把dat的最高位置1;若为0,则不进行处理,保持为0

}

delay(10); //此延时不能少,确保读时序的长度60us。

}

return (dat);

}

void Write_One_Byte(uchar dat)

{

uchar i = 0;

for(i=8;i>0;i--)

{

DQ = 0; //拉低总线

_nop_(); //至少维持了1us,表示写时序(包括写0时序或写1时序)开始

DQ = dat&0x01; //从字节的最低位开始传输

//指令dat的最低位赋予给总线,必须在拉低总线后的15us内,

//因为15us后DS18B20会对总线采样。

delay(10); //必须让写时序持续至少60us

DQ = 1; //写完后,必须释放总线,

dat >>= 1;

delay(1);

}

}

uint Get_Tmp() //获取温度get the temperature

{

float tt;

uchar a,b;

Init_Ds18b20(); //初始化

Write_One_Byte(0xcc); //忽略ROM指令

Write_One_Byte(0x44); //温度转换指令

Init_Ds18b20(); //初始化

Write_One_Byte(0xcc); //忽略ROM指令

Write_One_Byte(0xbe); //读暂存器指令

a = Read_One_Byte(); //读取到的第一个字节为温度LSB

b = Read_One_Byte(); //读取到的第一个字节为温度MSB

temp = b; //先把高八位有效数据赋于temp

temp <<= 8; //把以上8位数据从temp低八位移到高八位temp = temp|a; //两字节合成一个整型变量

tt = temp*0.0625; //得到真实十进制温度值

//因为DS18B20可以精确到0.0625度

//所以读回数据的最低位代表的是0.0625度temp = tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位也转换为可显示数字

//同时进行一个四舍五入操作。

return temp;

}

/****************数码码动态显示函数**************/

void Display(uint temp) //显示程序

{

uchar A1,A2,A3;

A1 = temp/100; //百位

A2 = temp%100/10; //十位

A3 = temp%10; //个位

dula = 0;

P0 = table[A1]; //显示百位

dula = 1; //打开段选,对应74573的锁存位,高电平不锁存

dula = 0;

wela = 0;

P0 = 0x7e;

wela = 1; //打开位选

wela = 0;

delay(0);

dula = 0;

P0 = table1[A2]; //显示十位,使用的是有小数点的数组(因为temp值扩大了10倍,虽然是十位,实际为个位)

dula = 1;

dula = 0;

wela = 0;

P0 = 0x7d;

wela = 1;

wela = 0;

delay(0);

P0 = table[A3]; //显示个位

dula = 1;

dula = 0;

P0 = 0x7b;

wela = 1;

wela = 0;

delay(0);

}

void main()

{

while(1)

{

Display(Get_Tmp());

}

}

1-Wire总线协议应用(转载)

作为一种单主机多从机的总线系统,在一条1-Wire总线上可挂接的从器件数量几乎不受限制。为了不引起逻辑上的冲突,所有从器件的1-Wire总线接口都是漏极开路的,因此在使用时必须对总线外加上拉电阻(一般取5kΩ左右)。主机对1-Wire总线的基本操作分为复位、读和写三种,其中所有的读写操作均为低位在前高位在后。复位、读和写是1-Wire总

(程序中DQ代表1-Wire 线通信的基础,下面通过具体程序详细介绍这3种操作的时序要求。

总线,定义为P1.0,uchar定义为unsigned char)

1 1-Wire总线的复位

复位是1-Wire总线通信中最为重要的一种操作,在每次总线通信之前主机必须首先发送复位信号。如程序1.1所示,产生复位信号时主机首先将总线拉低480~960μs然后释放,由于上拉电阻的存在,此时总线变为高电平。1-Wire总线器件在接收到有效跳变的15~60μs 内会将总线拉低60~240μs,在此期间主机可以通过对DQ采样来判断是否有从器件挂接在当前总线上。函数Reset()的返回值为0表示有器件挂接在总线上,返回值为1表示没有器件挂接在总线上。

程序1.1 总线复位

uchar Reset(void)

{

uchar tdq;

DQ=0; //主机拉低总线

delay480μs(); //等待480μs

DQ=1; //主机释放总线

delay60μs(); //等待60μs

tdq=DQ; //主机对总线采样

delay480μs(); //等待复位结束

return tdq; //返回采样值

}

2 1-Wire总线的写操作

由于只有一条I/O线,主机1-Wire总线的写操作只能逐位进行,连续写8次即可写入总线一个字节。如程序1.2所示,当MCS-51单片机的时钟频率为12MHz时,程序中的语句_nop_();可以产生1μs的延时,调用此函数时需包含头文件“intrins.h”。向1-Wire总线写1bit 至少需要60μs,同时还要保证两次连续的写操作有1μs以上的间隔。若待写位wbit为0则

主机拉低总线60μs然后释放,写0操作完成。若待写位wbit为1,则主机拉低总线并在1~15μs内释放,然后等待60μs,写1操作完成。

程序1.2 向总线写1bit

void Writebit(uchar wbit)

{

_nop_();

//保证两次写操作间隔1μs以上

DQ=0;

_nop_();

//保证主机拉低总线1μs以上

if(wbit)

{

//向总线写1

DQ=1;

delay60μs();

}

else

{

//向总线写0

d elay60μs();

DQ=1;

}

}

3 1-Wire总线的读操作

与写操作类似,主机对1-Wire总线的读操作也只能逐位进行,连续读8次,即可读入主机一个字节。从1-Wire总线读取1bit同样至少需要60μs,同时也要保证两次连续的读操作间隔1μs以上。如程序1.3所示,从总线读数据时,主机首先拉低总线1μs以上然后释放,在释放总线后的1~15μs内主机对总线的采样值即为读取到的数据。

程序1.3 从总线读1bit

uchar Readbit()

{

uchar tdq;

_nop_();

//保证两次连续写操作间隔1μs以上

DQ=0;

_nop_();

//保证拉低总线的时间不少于1μs

DQ=1;

_nop_();

tdq=DQ;

//主机对总线采样

delay60μs();

//等待读操作结束

return tdq;

//返回读取到的数据

}

数字温度传感器DS18B20

1 DS18B20的基本特性

● 采用1-Wire总线接口,可以方便实现多点测温。

● 与主机连接方便,除5kΩ的总线上拉电阻外无须其他额外器件。

● 电源电压范围为3.0~5.5V,与3.3V和5V数字系统均可很好地兼容。

● 测量范围为-55~+125℃,分辨率为9~12位可编程。

● 通过编程可设置温度报警上下限,设置值掉电不丢失。

● 内部集成了用于器件寻址的64bit光刻ROM编码。

2 DS18B20中的存储器

在DS18B20中共有三种存储器,分别是ROM、RAM、EEPROM,每种存储器都有其特定的功能,可查阅相关资料。

3 1-Wire总线ROM功能命令

在DS18B20内部光刻了一个长度为64bit的ROM编码,这个编码是器件的身份识别标志。当总线上挂接着多个DS18B20时可以通过ROM编码对特定器件进行操作。ROM功能命令是针对器件的ROM编码进行操作的命令,共有5个,长度均为8bit(1Byte)。

①读ROM(33H)

当挂接在总线上的1-Wire总线器件接收到此命令时,会在主机读操作的配合下将自身的ROM编码按由低位到高位的顺序依次发送给主机。总线上挂接有多个DS18B20时,此命令会使所有器件同时向主机传送自身的ROM编码,这将导致数据的冲突。

②匹配ROM(55H)

主机在发送完此命令后,必须紧接着发送一个64bit的ROM编码,与此ROM编码匹配的从器件会响应主机的后续命令,而其他从器件则处于等待状态。该命令主要用于选择总线上的特定器件进行访问。

③跳过ROM(CCH)

发送此命令后,主机不必提供ROM编码即可对从器件进行访问。与读ROM命令类似,该命令同样只适用于单节点的1-Wire总线系统,当总线上有多个器件挂接时会引起数据的冲突。

④查找ROM(F0H)

当主机不知道总线上器件的ROM编码时,可以使用此命令并配合特定的算法查找出总线上从器件的数量和各个从器件的ROM编码。

⑤报警查找(ECH)

此命令用于查找总线上满足报警条件的DS18B20,通过报警查找命令并配合特定的查找算法,可以查找出总线上满足报警条件的器件数目和各个器件的ROM编码。

4 DS18B20器件功能命令

与1-Wire总线相关的命令分为ROM功能命令和器件功能命令两种,ROM功能命令具有通用性,不仅适用于DS18B20也适用于其他具有1-Wire总线接口的器件,主要用于器件的识别与寻址;器件功能命令具有专用性,它们与器件的具体功能紧密相关。下面是DS18B20的器件功能命令。

①启动温度转换(44H)

该命令发送完成后,主机可以通过调用Readbit()函数判断温度转换是否完成,若Readbit()的返回值为0则表示转换正在进行,若Readbit()的返回值为1则表示转换完成。

②读RAM(BEH)

该命令发送完成后,主机可以通过调用Readbit()函数将DS18B20中RAM的内容从低位到高位依次读出。

③写RAM(4EH)

该命令发出后,主机随后写入1-Wire总线的3字节将依次被存储到DS18B20的报警上限、报警下限和配置寄存器中。

④复制RAM(48H)

该命令会将DS18B20的报警上限、报警下限和配置寄存器中的内容复制到EEPROM中。该命令发出后,主机可以通过调用Readbit()函数判断复制操作是否完成,若Readbit()的返回值为1,则表示复制操作完成。

⑤回读EEPROM(B8H)

该命令会将存储在EEPROM中的报警上限、报警下限和配置寄器的内容回读到RAM中,主机可以通过调用Readbit()函数判断回读操作是否完成,若Readbit()的返回值为1则表示回读操作完成。DS18B20在上电时会自动进行一次回读操作。

相关文档
最新文档