一、概述
1-WireTM器件与单片机的接口是一项颇具挑战性的工作。为此,设计师们想出了很多办法,从采用一个VHDL 1-WireTM主控制器,到使用串行接口芯片诸如DS2480。本文即将介绍的软件方案摒弃了这些外部器件,是一种很简捷的方案。
本文的示范程序展示了如何将微控制器与DS18S20通过单线连接,并通过检索ROM确定出网络中的器件数目,读取临时存储器,以及读取器件温度。
二、硬件配置
从下面的方框图可以看出,1-Wire网络的硬件配置极为简单。作为主机的微控制器通过单条引线连接到所有DS18S20这样的1-Wire器件的DQ输入/输出引脚,仅此而已。由于每个器件具有唯一的64位ROM识别码,因此1-Wire网络中可以接入的器件数目几乎没有限制。典型应用中,可以用3.0V至5.0V电源,经由一个4.7k上拉电阻驱动总线。
三、接口定时
一个写时隙起始于主机将1-Wire总线由逻辑高无效拉低到逻辑低,写1时隙和写0时隙具有不同的特点。各种写时隙都必须在60 s到120
s内结束,各时隙间另有1 s的最小恢复时间。在写0时,主机要在整个时隙拉低总线。而在写1时,主机必须先拉低总线,随后释放,以便DS18S20在启动时隙后的15
s内取样到总线的高电平。
读时隙同样起始于主机拉低总线(有效),需保持总线为低1 s,然后释放,以便DS18S20获得对总线的控制并发送有效数据(高或低)。各种读时隙必须在60
s到120 s内结束,时隙间另有1 s的最小恢复时间。
各种操作均以一个复位脉冲为起始,随后才能开始读或写。接口定时如图2所示。
四、软件控制
1、延时:为了精确控制1-Wire接口所要求的特殊定时,必须首先建立一些基本的函数。第一个需要建立的函数是延时,它在所有读和写操作中都会用到。这项功能与微控制器的速度密切相关。在测试时,我们使用了运行于11.059MHz的DS5000微控制器(兼容于8051)。"DELAY"是用来产生一定延时的子程序(如程序1所示)。
2、复位:由于每种操作都始于复位,因此"复位"功能是另一个需要实现的基本函数("OW_RESET")。复位时隙为480
s。通过延时"3",随后再延时"25",就可有效地建立一个复位脉冲(低),然后由DS18S20拉低总线,表示器件已就绪。如果网络中有多个器件,每个器件都会响应一个应答信号(低有效)(如程序2所示)。
3、读、写操作:
"READ_BIT"、"WRITE_BIT"、"READ_BYTE"和"WRITE_BYTE"读、写函数可用于所有数据位或数据字节的读、写操作(如程序3所示)。
五、搜索ROM算法
为了充分发挥1-Wire的优势,用户必须能够与网络中的任何数量的器件通信。图3.0提供了用于读取器件的64位ROM识别号的命令代码。
在一次典型的数据传送中,微控制器需首先发送一个复位脉冲,以启动流程,然后发"跳过ROM"和"读ROM"命令。这种方式只能用于网络中仅有一个1-Wire器件的情况。如果连接了多个1-Wire器件,用户就必须执行"搜索ROM算法"查找1-Wire网中的所有器件,可在复位之后调用"器件查找"函数实现,"器件查找"函数发布在Maxim网站。一旦找到器件的ROM识别号后,就可通过"匹配
ROM"功能选择某一特定器件进行通信。
六、读取器件温度
如果网上只有单一器件,接着便可直接执行"READ_TEMPERATURE"函数。然而,如果网络中有多个器件,就必须利用"匹配
ROM"函数选出一个特定器件,并使其它器件脱离网络,以免数据冲突。由于篇幅有限,这些子函数均发布在Maxim网站上,此外,临时存储器可以为用户提供所有必要的数据,包括温度、可编程的TH和TL温度计设置,以及用于测量分数位温度值的Count
Remain和Count per C数据。CRC字节也保存于临时存储器内。读取临时存储器的程序同样可在Maxim网站获得。
程序1
//DELAY-with an 11.059MHz crystal
//Calling the routine takes about 24us,and then
//each count takes another 16us.
//
void delay(int useconds)
{
int s;
for(s=0;s<useconds;s++)
}
程序2
//OW_RESET-performs a reset on one-wire bus and
//returns the presence detect.Reset is 480us.so delay
//value is(480-24)/16=28.5-we use 29.Presence checked
//another 70us later,so delay is(70-24)/16=2.875-we use 3.
//
unsigned char ow_reset(void)
{
unsigned char presence:
DQ=0;//pull DQ line low
delay(29);//leave it low for 480us
DQ=1;//allow line to return high
delay(3);//wait for presence
presence=DQ;//get presence signal
delay(25);//wait for end of timeslot
return(presence);//presence signal returned
} //0=presence,1=no part
程序3
//READ_BIT-reads a bit from the one-wire bus.The delay
//required for a read is 15us,so the DELAY routine won't work
//We put our own delay function in this routine in the form of a
//for()loop
//
unsigned char read_bit(void)
{
unsigned char i;
DQ=0;//pull DQ low to start timeslot
DQ=1;//then return high
for=(i=0;i<3;i++);//delay 15us from start of timeslot
return(DQ);//return value of DQ line
}
///////////////////////////////////////////////
//WRITE_BIT-writes a bit to the one-wire bus,passed in bitval.
//
void write_bit(char bitval)
{
DQ=0;//pull DQ low to start timeslot
if(bitval==1)DQ=1;//return DQ high
if write 1
delay(5);//hold value for remainder of timeslot
DQ=1
}//Delay provides 16us per loop,plus 24us.
Therefore delay(5)=104us
///////////////////////////////////////////////
//READ_BYTE-reads a byte from the one-wire bus.
//
unsigned char read_byte(void)
{
unsigned char i;
unsigned char value=0;
for(i=0;i<8;i++)
{
if(read_bit())value|=0x01<<i;//reads
byte in,one byte at a time and then
//shifts
it left
delay(6);//wait for rest of timeslot
}
return(value);
}
///////////////////////////////////////////////
//WRITE_BYTE-writes a byte to the one-wire bus.
//
void write-byte(char val)
{
unsigned char i;
unsigned char temp;
for(i=0;i<8;i++)//writes byte,one bit at a time
{
temp=val>>i;//shifts val reght'i'
spaces
temp &=0x01;//copy that bit to temp
write_bit(temp);//write bit in temp
into
}
delay(5)
}
|