原创 用软件实现1-Wire通信

2008-8-6 00:10 4232 6 4 分类: MCU/ 嵌入式
在没有专用总线主机(如DS2480B、DS2490)的情况下,微处理器可以轻松地产生1-Wire时序信号。本应用笔记给出了一个采用‘C’语言编写、支持标准速率的1-Wire主机通信基本子程序实例。1-Wire总线的四个基本操作是:复位、写“1”、写“0”和读数据位。字节操作可以通过反复调用位操作实现,本文提供了通过各种传输线与1-Wire器件进行可靠通信的时间参数。

在没有专用总线主机的情况下,微处理器可以轻松地产生1-Wire?时序信号。本应用笔记给出了一个采用‘C’语言编写、支持标准速率的1-Wire主机通信基本子程序实例。此外,本文也讨论了高速通信模式。要使该实例中的代码正常运行,系统必须满足以下几点要求:


1.微处理器的通信端口必须是双向的,其输出为漏极开路,且线上具有弱上拉。这也是所有1-Wire总线的基本要求。
2.微处理器必须能产生标准速度1-Wire通信所需的精确1μs延时和高速通信所需要的0.25μs延时。
3.通信过程不能被中断。


1-Wire总线有四种基本操作:复位、写1位、写0位和读位操作。在产品资料中,将完成一位传输的时间称为一个时隙。于是字节传输可以通过多次调用位操作来实现,下表1是各个位操作的简要说明以及实现这些操作所必须的步骤列表。图1为其时序波形图。表2给出了通常线路条件下1-Wire主机与1-Wire器件通信的最短、最长和推荐时间。如果与1-Wire主机相连的器件比较特殊或者线路条件比较特殊,则可以采用最小值或最大值。

表1.1-Wire操作

OperationDescriptionImplementation
Write 1 bitSend a '1' bit to the 1-Wire slaves (Write 1 time slot)Drive bus low, delay A
Release bus, delay B
Write 0 bitsend a '0' bit to the 1-Wire slaves (Write 0 time slot)Drive bus low, delay C
Release bus, delay D
Read bitRead a bit from the 1-Wire slaves (Read time slot)Drive bus low, delay A
Release bus, delay E
Sample bus to read bit from slave
Delay F
ResetReset the 1-Wire bus slave devices and ready them for a commandDelay G
Drive bus low, delay H
Release bus, delay I
Sample bus, 0 = device(s) present, 1 = no device present
Delay J

点击看大图


 

表2.1-Wire主机时序

ParameterSpeedMin (μs)Recommended (μs)Max (μs)Notes
AStandard56151, 2
Overdrive11.51.851, 3
BStandard5964N/A2, 4
Overdrive7.57.5N/A3, 4
CStandard60601202, 5
Overdrive77.5143, 5
DStandard810N/A2, 6
Overdrive2.52.5N/A3, 6
EStandard59122, 7, 8
Overdrive0.50.750.853, 7, 8
FStandard5055N/A2, 9
Overdrive6.757N/A3, 9
GStandard000
Overdrive2.52.5N/A3, 14
HStandard4804806402, 10, 15
Overdrive6870803, 10
IStandard6370782, 11
Overdrive7.28.58.83, 11
JStandard410410N/A2, 12, 13
Overdrive39.540N/A3, 12

 


 


 


 


 


 


 


 


 


 


 


 



有关表中这些值的详细计算,可参考:http://files.dalsemi.com/auto_id/public/an126.zip


注释:
在产品数据资料中,表示为tW1L (写1低)减去 (上升至VTH的时间)加上tF (下降至VTL的时间)。
假定网络为标准速度的中等距离网络,且上升和下降时间不超过3μs。
假定网络为高速的小型网络,且上升和下降时间不超过0.5μs。
数据资料中,表示为tSLOT (时隙时间)减去‘A’所代表的时间。
数据资料中,表示为tW0L (写0低)减去 (上升至VIHMASTER的时间)加上tF (下降至VTL的时间)。
数据资料中,表示为tREC (恢复时间)加上 (上升至VIHMASTER的时间)。
数据资料中,表示为tMSR (主机采样读时间)加上tF (下降至VTL的时间),再减去‘A’。
在该范围内,采样要尽可能晚,以便获得最长的恢复时间。
数据资料中,表示为tSLOT (时隙时间)减去‘A’,再减去‘E’。
数据资料中,表示为tRSTL (复位为低的时间)减去 (上升至VTH的时间)加上tF (下降至VTL的时间)。
数据资料中,表示为tMSP (主机采样应答时间)加上 (上升至VTH的时间)。
数据资料中,其最小值表示为tRSTL (复位低电平时间)减去‘I’所用的时间。
这里所提到的1-Wire复位操作没有把DS2404和DS1994使用的扩展应答(报警)脉冲序列考虑进去,关于这种特殊情况,请查看产品的数据资料。在1-Wire复位序列的未尾进行采样,可以验证1-Wire总线是否已返回到上拉电平。如果电平仍为0,则可能是1-Wire总线与地之间短路,或DS2404/DS1994发出了报警信号。
表示为tREC (恢复时间)减去‘D’所用的时间。在高速应用时,一些器件在tRSTL (低电平复位时间)之前要求额外的延时,以保证器件的寄生电源被完全充满。
对于低电压工作方式,有些器件可能需要更长的延时。关于合适的参数值,请参阅器件数据资料。


代码实例


下面代码实例都依赖于两个通用的‘C’函数outp 和inp,从IO端口读写字节数据。他们通常位于标准库中。当应用于其它平台时,可以采用合适的函数来替代它们。


// send 'databyte' to 'port'
int outp(unsigned port, int databyte);

// read byte from 'port'
int inp(unsigned port);
代码中的常量PORTADDRESS (图3)用来定义通信端口的地址。这里我们假定使用通信端口的第0位控制1-Wire总线。设定该位为1,将使1-Wire总线变为低电平;设定该位为0,1-Wire总线将被释放,此时1-Wire总线被电阻上拉,或被1-Wire从器件下拉。

代码中的tickDelay函数是一个用户编制的子程序,此函数用于产生一个1/4μs整数倍的延时。在不同的平台下,该函数的实现也是不同的,故在此不做具体描述。以下是tickDelay函数声明代码,以及一个SetSpeed函数,用于设定标准速度和高速模式的延时时间。

实例1. 1-Wire时序的生成
// Pause for exactly 'tick' number of ticks = 0.25us
void tickDelay(int tick); // Implementation is platform specific

// 'tick' values
int A,B,C,D,E,F,G,H,I,J;


//-----------------------------------------------------------------------------
// Set the 1-Wire timing to 'standard' (standard=1) or 'overdrive' (standard=0).
//
void SetSpeed(int standard)
{
// Adjust tick values depending on speed
if (standard)
{
// Standard Speed
A = 6 * 4;
B = 64 * 4;
C = 60 * 4;
D = 10 * 4;
E = 9 * 4;
F = 55 * 4;
G = 0;
H = 480 * 4;
I = 70 * 4;
J = 410 * 4;
}
else
{
// Overdrive Speed
A = 1.5 * 4;
B = 7.5 * 4;
C = 7.5 * 4;
D = 2.5 * 4;
E = 0.75 * 4;
F = 7 * 4;
G = 2.5 * 4;
H = 70 * 4;
I = 8.5 * 4;
J = 40 * 4;
}
}


实例2. 基本的1-Wire函数

//-----------------------------------------------------------------------------
// Generate a 1-Wire reset, return 1 if no presence detect was found,
// return 0 otherwise.
// (NOTE: Does not handle alarm presence from DS2404/DS1994)
//
int OWTouchReset(void)
{
int result;

tickDelay(G);
outp(PORTADDRESS,0x00); // Drives DQ low
tickDelay(H);
outp(PORTADDRESS,0x01); // Releases the bus
tickDelay(I);
result = inp(PORTADDRESS) & 0x01; // Sample for presence pulse from slave
tickDelay(J); // Complete the reset sequence recovery
return result; // Return sample presence pulse result
}

//-----------------------------------------------------------------------------
// Send a 1-Wire write bit. Provide 10us recovery time.
//
void OWWriteBit(int bit)
{
if (bit)
{
// Write '1' bit
outp(PORTADDRESS,0x00); // Drives DQ low
tickDelay(A);
outp(PORTADDRESS,0x01); // Releases the bus
tickDelay(B); // Complete the time slot and 10us recovery
}
else
{
// Write '0' bit
outp(PORTADDRESS,0x00); // Drives DQ low
tickDelay(C);
outp(PORTADDRESS,0x01); // Releases the bus
tickDelay(D);
}
}

//-----------------------------------------------------------------------------
// Read a bit from the 1-Wire bus and return it. Provide 10us recovery time.
//
int OWReadBit(void)
{
int result;

outp(PORTADDRESS,0x00); // Drives DQ low
tickDelay(A);
outp(PORTADDRESS,0x01); // Releases the bus
tickDelay(E);
result = inp(PORTADDRESS) & 0x01; // Sample the bit value from the slave
tickDelay(F); // Complete the time slot and 10us recovery

return result;
}
该程序包括了1-Wire总线的所有位操作,通过调用该程序可以构成以字节为处理对象的函数,见实例3。

实例3. 派生的1-Wire函数

//-----------------------------------------------------------------------------
// Write 1-Wire data byte
//
void OWWriteByte(int data)
{
int loop;

// Loop to write each bit in the byte, LS-bit first
for (loop = 0; loop < 8; loop++)
{
OWWriteBit(data & 0x01);

// shift the data byte for the next bit
data >>= 1;
}
}

//-----------------------------------------------------------------------------
// Read 1-Wire data byte and return it
//
int OWReadByte(void)
{
int loop, result="0";

for (loop = 0; loop < 8; loop++)
{
// shift the result to get it ready for the next bit
result >>= 1;

// if result is one, then set MS bit
if (OWReadBit())
result |= 0x80;
}
return result;
}

//-----------------------------------------------------------------------------
// Write a 1-Wire data byte and return the sampled result.
//
int OWTouchByte(int data)
{
int loop, result="0";

for (loop = 0; loop < 8; loop++)
{
// shift the result to get it ready for the next bit
result >>= 1;

// If sending a '1' then read a bit else write a '0'
if (data & 0x01)
{
if (OWReadBit())
result |= 0x80;
}
else
OWWriteBit(0);

// shift the data byte for the next bit
data >>= 1;
}
return result;
}

//-----------------------------------------------------------------------------
// Write a block 1-Wire data bytes and return the sampled result in the same
// buffer.
//
void OWBlock(unsigned char *data, int data_len)
{
int loop;

for (loop = 0; loop < data_len; loop++)
{
data[loop] = OWTouchByte(data[loop]);
}
}

//-----------------------------------------------------------------------------
// Set all devices on 1-Wire to overdrive speed. Return '1' if at least one
// overdrive capable device is detected.
//
int OWOverdriveSkip(unsigned char *data, int data_len)
{
// set the speed to 'standard'
SetSpeed(1);

// reset all devices
if (OWTouchReset()) // Reset the 1-Wire bus
return 0; // Return if no devices found

// overdrive skip command
OWWriteByte(0x3C);

// set the speed to 'overdrive'
SetSpeed(0);

// do a 1-Wire reset in 'overdrive' and return presence result
return OWTouchReset();
}
OWTouchByte函数可以同时完成读写1-Wire总线数据,通过该函数可以实现数据块的读写。在一些平台上执行效率更高, Dallas Semiconductor提供的API就采用了这种函数。通过OWTouchByte函数,OWBlock函数简化了1-Wire总线的数据块发送和接收。注意:OWTouchByte(0xFF)与OWReadByte()等效, OWTouchByte(data)与 OWWriteByte(data)等效。

这些函数和tickDelay函数一起构成了1-Wire总线进行位、字节和块操作时所必需的全部函数。实例4给出了利用这些函数读取DS2432的SHA-1认证页的实例。

读DS2432实例


//-----------------------------------------------------------------------------
// Read and return the page data and SHA-1 message authentication code (MAC)
// from a DS2432.
//
int ReadPageMAC(int page, unsigned char *page_data, unsigned char *mac)
{
int i;
unsigned short data_crc16, mac_crc16;

// set the speed to 'standard'
SetSpeed(1);


// select the device
if (OWTouchReset()) // Reset the 1-Wire bus
return 0; // Return if no devices found


OWWriteByte(0xCC); // Send Skip ROM command to select single device


// read the page
OWWriteByte(0xA5); // Read Authentication command
OWWriteByte((page << 5) & 0xFF); // TA1
OWWriteByte(0); // TA2 (always zero for DS2432)


// read the page data
for (i = 0; i < 32; i++)
page_data = OWReadByte();
OWWriteByte(0xFF);


// read the CRC16 of command, address, and data
data_crc16 = OWReadByte();
data_crc16 |= (OWReadByte() << 8);


// delay 2ms for the device MAC computation
// read the MAC
for (i = 0; i < 20; i++)
mac = OWReadByte();


// read CRC16 of the MAC
mac_crc16 = OWReadByte();
mac_crc16 |= (OWReadByte() << 8);


// check CRC16...
return 1;
}


附言
本应用笔记给出了1-Wire总线操作的基本函数,这些基本函数都是构建复杂的1-Wire应用的基础。本文忽略的一个重要操作是1-Wire搜索。通过1-Wire搜索可以搜索到挂接在总线上的多个1-Wire从机器件的唯一ID号。详见《1-Wire搜索算法》一文。

文章评论1条评论)

登录后参与讨论

用户387625 2008-11-21 13:55

心跳功能的意思是指DTU每隔一定时间,发一个数据包到数据中心。主要功能: 1.防止掉线,因为现在网络运营商为了防止一些终端挂在网上,而不传数据(因为GPRS或CDMA都是按流量收费的),所以当发现终端一定时间内没有传输数据时(约 分钟),就会把终端踢下线。 2.实现远程在线监测,数据中心可实现监测各终端是否在线。 由于无线终端访问Internet时,都必须依靠GGSN,GGSN则利用NAT 为所有无线终端进行映射,产生的映射均有一个TTL生存时间,一般为3分钟以内,如果超过3分钟,映射将会自动消失,此时在数据中心将无法主动与DTU通信。所以必须DTU定时发一些心跳数据来维持与数据中心的链路。在申请APN/VPDN后,可去掉心跳包。因为此时DTU不需要通过GGSN与Internet进行通信,所以也不需要NAT。此时GGSN在为APN域内SIM卡直接静态路由,所以可去心跳包。

用户222124 2008-8-8 08:15

也来顶一个
相关推荐阅读
用户461316 2009-08-17 17:57
Zigbee星型网络组网程序段
最近一直在做Zigbee的星型网络的组网试验,由于时间的原因,现在只是在最高的应用层上来编写程序。即协议栈的程序是2430的开发商(无限龙)编写的,我只是调用相应的函数来完成组网的,星型网络组网部分的...
用户461316 2009-08-17 17:14
VB6的标题栏使用上真彩色图标
模块 ModIcon.Bas 代码: Option Explicit Private Declare Function DrawIcon Lib "user32" (ByVal hdc As Long...
用户461316 2009-08-17 16:58
AppendToLog一个API方式存取日志文件的模块
'**************************************' 模块名称: AppendToLog' 功能描述:一个很不错的日志文件写入模块,不同于'     open/print/...
用户461316 2009-08-17 16:57
(VB自定义函数)去除字符串中的空格
'去除字符串中的空格(方法一)Public Function DelBlank(SearchString As String)   DelBlank = Replace(SearchString, C...
用户461316 2009-08-17 16:56
(VB自定义函数)对任意输入的汉字,可以得到它的拼音的第一个字母
调用方法:Command1.Caption = getHzPy("你")'//函数入口为汉字串,返回值为该汉字的第一个字母Public Function getHzPy(hzStr As String...
用户461316 2009-08-17 16:54
VB_代码执行速度测试
'**************************************'Windows API/Global Declarations for :[ '     A Simple] code ...
我要评论
1
6
关闭 站长推荐上一条 /2 下一条