摘要:DS2482是I²C到1-Wire网络协议的桥接器件。桥接器DS2482可以使任何具备I²C通信功能的主机产生正确定时和具有摆率控制的1-Wire波形。本应用笔记是DS2482 I²C至1-Wire线驱动器的用户指南,详细介绍了通用1-Wire主控制器操作的通信过程。
1. 引言
1-Wire通信协议可利用DS2482产生,DS2482是I²C至1-Wire网络的桥接器件。该桥接器件可使带有I²C接口的主机产生正确定时的1-Wire波形。图1所示为DS2482配置的简化框图。执行该协议并浏览所有DS2482指令相当费时并容易混淆。为此,本应用笔记介绍了采用DS2482有效实现基本的与扩展的1-Wire操作的方法。详细介绍了处理1-Wire通信的I²C输入数据包结构。这些操作为执行当前和未来1-Wire器件的所有功能打下了全面的基础。以这种方式概要介绍1-Wire操作,使1-Wire应用可独立于1-Wire主机类型。
本文仅作为DS2482数据资料的补充,并不能替代数据资料。DS2482可提供两种配置,单通道1-Wire主控制器(DS2482-100)和8通道1-Wire主控制器(DS2482-800)。
 图1. 与1-Wire网络进行I²C通信的DS2482桥接器功能简图。
2. 1-Wire接口
下面给出几个基本的1-Wire函数,称之为原函数,也就是为了执行所有1-Wire操作,应用中必须具备的函数。第一个函数是使总线上所有1-Wire从器件复位,使其为接收来自1-Wire主控制器的指令做好准备。第二个函数完成1-Wire主控制器向从器件写入一位的操作,而第三个函数完成从1-Wire从器件中读取一位的操作。由于必须由1-Wire主控制器启动所有的1-Wire位通信,所以“读取”实际上是在“写入”一位后采样得到的结果。几乎所有其他1-Wire操作都可以由这三个操作构成。例如,向1-Wire总线写1个字节相当于8次写一位操作。
1-Wire搜索算法也可以利用这三个原始函数构成。通过1-Wire的triplet命令,DS2482可以执行搜索功能,这大大降低了搜索操作所需的通信量。
表1所示是三个基本原函数(OWReset,OWWriteBit/OWReadBit和OWWriteByte/OWReadByte)以及其他三个非常有用的函数(OWBlock,OWSearch和msDelay),它们构成了一系列主要的基本1-Wire操作。这些操作名称将在下文中使用。
表1. 基本的1-Wire操作
| Operation |
Description |
| OWReset |
Sends the 1-Wire reset stimulus and check for pulses of 1-Wire slave devices. |
| OWWriteBit/OWReadBit |
Sends or receives a single bit of data to the 1-Wire bus. |
| OWWriteByte/OWReadByte |
Sends or receives a single byte of data to the 1-Wire bus. |
| OWBlock |
Sends and receives multiple bytes of data to and from the 1-Wire bus. |
| OWSearch |
Performs the 1-Wire Search Algorithm (see Application Note 187 mentioned above). |
| msDelay |
Delays at least the specified number of milliseconds. |
扩展的1-Wire函数(如高速通信函数)并没有包括在上表的基本操作中。一些1-Wire从器件可以工作在两种不同的通信速率下:标准速率和高速模式。所有器件都支持标准速率模式。高速速率大约是标准速率的10倍。DS2482同时支持这两种1-Wire速率。
1-Wire器件通常从1-Wire总线上获取部分或全部工作电源。不过有些器件在
协议的特定位置需要额外供电。例如,某个器件可能需要进行温度转换或计算SHA-1散列。这种操作的电源是通过使能1-Wire总线的强上拉来提供的。在该供电期间,不能进行正常通信。DS2482通过设置强上拉标志(SPU)位来供电,这将在1-Wire的下一个字节/位通信完成后启动强上拉。DS2482-100具有一个外部引脚(PCTLZ),可控制大电流强上拉。
表2列出了用于1-Wire速率设定、供电和编程脉冲的扩展1-Wire操作。
表2. 扩展的1-Wire操作
| Operation |
Description |
| OWSpeed |
Sets the 1-Wire communication speed, either standard or overdrive. Note that this only changes the communication speed of the 1-Wire master; the 1-Wire slave device must be instructed to make the switch when going from normal to overdrive. The 1-Wire slave will always revert to standard speed when it encounters a standard-speed 1-Wire reset. |
| OWLevel |
Sets the 1-Wire power level (normal or power delivery). |
| OWReadBitPower |
Reads a single bit of data from the 1-Wire bus and optionally applies power delivery immediately after the bit is complete. |
| OWWriteBytePower |
Sends a single byte of data to the 1-Wire bus and applies power delivery immediately after the byte is complete. |
3. 主机配置
DS2482的主机应具有一个I²C通信端口。本文并没有讲述主机的配置。然而,主机必须提供标准I²C接口操作。所需的操作请参阅表3。
表3. 所需的I²C主机操作
| Operation |
Description |
| InitI2C |
Sets the I²C communication speed and selects the DS2482 device. The I2C_clock_delay is the time between clock pulses for I²C communication. The DS2482_slave_address is the I²C address for the DS2482. |
| I2CBus_write |
Writes an I²C byte to the selected DS2482. The byte is passed to the function to write. |
| I2CBus_write_packet |
Writes a packet of I²C bytes to the selected DS2482. The buffer of bytes along with the length of the buffer is passed to the function. |
| I2CBus_read |
Reads an I²C byte from the DS2482. The byte that was read is returned. |
3.1. 配置DS2482
在尝试1-Wire操作之前,主机必须设置I²C至1-Wire线驱动器DS2482,并与其同步。要与DS2482通信,主机必须知道其从地址。图2所示为DS2482-100和DS2482-800的从地址。
 图2. DS2482的I²C从地址
3.2. DS2482的I²C命令
下列符号说明来自于DS2482数据资料,以简写符号表示,用来说明器件的I²C通信过程。接下来,我们会重复这些通信过程,并为实现基本和扩展1-Wire操作提供附加注释和C语言代码实例。
I²C通信过程—符号说明
| SYMBOL |
DESCRIPTION |
| S |
START Condition |
| AD, 0 |
Select DS2482 for Write Access |
| AD, 1 |
Select DS2482 for Read Access |
| Sr |
Repeated START Condition |
| P |
STOP Condition |
| A |
Acknowledged |
| A\ |
Not acknowledged |
| (Idle) |
Bus not busy |
| <byte> |
Transfer of one byte |
| DRST |
Command 'Device Reset', F0h |
| WCFG |
Command 'Write Configuration', D2h |
| SRP |
Command 'Set Read Pointer', E1h |
| 1WRS |
Command '1-Wire Reset', B4h |
| 1WWB |
Command '1-Wire Write Byte', A5h |
| 1WRB |
Command '1-Wire Read Byte', 96h |
| 1WSB |
Command '1-Wire Single Bit', 87h |
| 1WT |
Command '1-Wire Triplet', 78h |
3.3. 数据方向表示法
| Master-to-Slave |
Slave-to-Master |
本文中许多图中的数据方向表示方法指出了通信方向是主机到从机(灰色),还是从机到主机(白色)。可通过每个符号的底色来确定通信方向。
4. 器件复位
图3是实现器件复位的I²C通信实例。复位实例1给出了DS2482复位命令,可实现器件状态机逻辑的完全复位,并终止所有正在进行的1-Wire通信。器件的复位命令代码是0xF0。
 图3. 上电后进行器件复位。该实例包括可选的读访问,以检验命令是否成功执行。
// initialize the I2C port
if(!InitI2C(I2C_clock_delay,DS2482_slave_address))
{
// Report an error that occurred
}
// reset the DS2482
// DRST is 0xF0
if(!I2CBus_write(DRST))
{
// Report an error that occurred
}
实例1. 复位器件代码
5. DS2482的1-Wire操作
以下是向DS2482发送的命令,可影响1-Wire通信。
5.1. OWReset
Reset命令(0xB4)在1-Wire总线上执行1-Wire复位/在线应答检测。通过状态寄存器中的在线应答脉冲检测(PPD)和短路检测(SD)域,可以采样和报告1-Wire总线的状态。图4所示为1-Wire复位命令的I²C通信过程。实例2为发送的命令,将检查状态寄存器以确定在线应答脉冲状态。
 图4. 1-Wire复位。开始或终止1-Wire通信。轮询1-Wire的忙状态,直到1-Wire命令完成为止,等到1-Wire空闲(1WB = 0)时,然后读取结果。
// OWReset
//
// Resets the 1-Wire using I2C through the DS2482.
//
// returns Success or Failure
//
uchar OWReset()
{
uchar buffer;
uchar test;
// reset the 1-Wire line
// resetOneWireCommand is 0xB4
if(!I2CBus_write(resetOneWireCommand))
{
// Report an error that occurred
}
for(;;)// checking if 1-Wire busy
{
// checking LSB of status register
// to see if 1-Wire is busy.
test = I2CBus_read()| 0xFE;
if(test == 0xFE)
{break;}
}
// checking for presence pulse detect
test = I2CBus_read() | 0xFC;
if(test == 0xFE)
{
return Success; // Presence Pulse found
}
else
{
return Failure; // No presence pulse
}
}
实例2. OWReset代码
5.2. OWWriteBit/OWReadBit
1-Wire位命令(0x87)生成一个1-Wire位时隙。图5所示是1-Wire位命令的I²C通信代码。图6是包含该位位置的字节。其中,如果V是1b,则生成写1时隙,如果V是0b,则生成写0时隙。实例3为OWWriteBit代码,实例4为OWReadBit代码。
 图5. 1-Wire位命令。在1-Wire总线上生成一个时隙,当1WB从1变为0时,状态寄存器保持1-Wire位命令的有效结果。
 图6. 1-Wire位命令。在1-Wire总线上产生单个时隙。
// OWWriteBit - Writes a single bit to 1-Wire using the DS2482.
//
// value - bit to be written to the 1-Wire (0 or 1)
//
// Return Success or Failure
//
uchar OWWriteBit(uchar value)
{
uchar buff[3];
uchar test;
buff[0] = onewireBitCommand; // 1-Wire bit command
if(value)
{
buff[1] = 0xFF;
}
else
{
buff[1] = 0x7F;
}
if(!I2CBus_write(&buff[0],2))
{
return FAILURE;
}
// checking if 1-Wire busy
// Check here to make sure the 1-Wire isn’t
// busy so other commands don’t have to check
// before proceeding.
for(;;)
{
if(!I2CBus_read(&buff[0],1))
{
return FAILURE;
}
test = buff[0] | 0xFE;
if(test == 0xFE)
{
break;
}
}
return SUCCESS;
}
Example 3. OWWriteBit code.
// OWReadBit
//
// Returns 0 or 1 for the bit read.
uchar OWReadBit()
{
uchar buff[3];
OWWriteBit(1);
buff[0] = setReadPointerCommand;
buff[1] = statusRegister;
if(!I2CBus_write(&buff[0],2))
{
// Report an error that occurred
}
else if(!I2CBus_read(&buff[2],1))
{
// Report an error that occurred
}
if(buff[2] & 0x20)
{
return 1;
}
else
{
return 0;
}
}
实例4. OWReadBit代码
5.3. OWWriteByte
1-Wire写字节命令(0xA5)向1-Wire总线写入单个数据字节。在DS2482执行该命令之前,必须结束1-Wire的工作状态。图7所示为通过I²C写1-Wire字节的情况。代码实例5在发送写字节命令之前,先检查1-Wire是否忙。
 图7. 1-Wire写字节。向1-Wire总线发送命令代码。当1WB从1变为0时,完成1-Wire写字节命令。
// OWWriteByte
//
// Writes a 1-Wire byte using I2C commands sent to the DS2482.
//
// wrByte - The byte to be written to the 1-Wire.
//
void OWWriteByte(uchar wrByte)
{
uchar buffer[2];
uchar test;
// set the read pointer to the status
// register to check 1-Wire busy
buffer[0] = setReadPointerCommand; // 0xE1
buffer[1] = statusRegister; // 0xF0
if(!I2CBus_write(buffer,2))
{
// Report an error that occurred
}
// checking if 1-Wire busy
for(;;)
{
test = I2CBus_read() | 0xFE;
if(test == 0xFE)
{
break;
}
}
buffer[0] = writeByteCommand; // 0xA5
buffer[1] = wrByte;
if(!I2CBus_write_packet(buffer,2))
{
// Report an error that occurred
}
// checking if 1-Wire busy
for(;;)
{
test = I2CBus_read() | 0xFE;
if(test == 0xFE)
{
break;
}
}
}
实例5. OWWriteByte代码
5.4. OWReadByte
1-Wire读字节命令(0x96)从1-Wire总线读取单个数据字节。在DS2482执行该命令之前,必须等1-Wire的工作状态结束。图8所示为I²C通信情况。1-Wire读字节命令见代码实例6。在发送读字节命令之前,必须检查1-Wire的工作状态是否结束。
 图8. 1-Wire读字节。从1-Wire总线上读取一个字节。轮询状态寄存器直到1WB位从1变为0。然后设置读指针指向读数据寄存器(代码E1h),并再次访问该器件,读取从1-Wire总线上得到的数据字节。
// OWReadByte
//
// Reads a 1-Wire byte using I2C commands to the DS2482.
//
// returns the byte read
//
uchar OWReadByte
{
uchar buffer[2];
uchar test;
// set the read pointer to the status
// register to check 1-Wire busy
buffer[0] = setReadPointerCommand; // 0xE1
buffer[1] = statusRegister; // 0xF0
if(!I2CBus_write_packet(buffer,2))
{
// Report an error that occurred
}
// checking if 1-Wire busy
for(;;)
{
test = I2CBus_read() | 0xFE;
if(test == 0xFE)
{
break;
}
}
// readByteCommand is 0x96
if(!I2CBus_write(readByteCommand))
{
// Report an error that occurred
}
buffer[0] = setReadPointerCommand; // 0xE1
buffer[1] = readDataRegister; // 0xE1
if(!I2CBus_write_packet(buffer,2))
{
// Report an error that occurred
}
// gets the byte that was read
else
{
buffer[2] = I2CBus_read();
}
return buffer[2];
}
实例6. OWReadByte代码
5.5. OWBlock
由于不通过字节命令就不能传输数据块,因此,OWBlock操作只是调用字节操作。实例7为OWBlock代码实例。
// OWBlock – writes/reads a block of data
// block – block of data
// return – Success or failure of the operation.
uchar OWBlock (uchar *block, uchar len)
{
uchar buffer[2];
int i;
for(i=0;i<len;i++)
{
owWriteByte(block[i]);
buffer[0] = setReadPointerCommand; // The read pointer value is 0xE1
buffer[1] = readDataRegister; // The read data register value is 0xE1
if(!I2CBus_write(&buffer[0],2))
{
return FAILURE;
}
else
block[i] = I2CBus_read();
}
return SUCCESS;
}
实例7. OWBlock代码
5.6 OWSearch/1-Wire Triplet命令
Triplet命令(0x78)可在1-Wire总线上产生3个时隙,其中包括两个读时隙和一个写时隙。方向字节(DIR)决定了写时隙的类型(图9)。实例8示出了仅挂接一个器件情况下使用搜索命令的1-Wire Triplet命令代码。有关1-Wire搜索算法的解释参见应用笔记187,该应用笔记给出了1-Wire Triplet命令的I²C设置。
 图9. 1-Wire Triplet。在1-Wire总线上实现搜索ROM功能。完成该1-Wire功能需要一段空闲时间。然后在读取模式下访问器件,通过1-Wire Triplet命令得到结果。
// Global value for the current serial number
uchar SearchSerialNum[8];
// oneWireSearch
//
// Does a 1-Wire search using the 1-Wire Triplet command.
//
// resetSearch – Reset the search(1) or not(0).
// lastDevice - If the last device has been found(1) or not(0).
// deviceAddress – The returned serial number.
//
// returns SUCCES or FAILURE
//
uchar OWSearch(uchar resetSearch, uchar *lastDevice, uchar *deviceAddress)
{
uchar retVal = FAILURE;
uchar bit_number = 1;
uchar last_zero = 0;
uchar serial_byte_number = 0;
uchar serial_byte_mask = 1;
uchar firstBit, secondBit, dir;
uchar i = 0;
if(resetSearch)
{
lastDevice = 0;
LastDiscrepancy = 0;
}
// if the last call was not the last one
if (!(*lastDevice))
{
// reset the 1-wire
// if there are no parts on 1-wire, return FALSE
if(!OWReset())
{
// reset the search
lastDevice = 0;
LastDiscrepancy = 0;
return FAILURE;
}
// Issue the Search ROM command
OWWireByte(0xF0);
// loop to do the search
do
{
if (bit_number < LastDiscrepancy)
{
if(SearchSerialNum[serial_byte_number] & serial_byte_mask)
dir = 1;
else
dir = 0;
}
else
{
// if equal to last pick 1, if not then pick 0
if(bit_number==LastDiscrepancy)
dir = 1;
else
dir = 0;
}
if(!owTriplet(&dir, &firstBit, &secondBit))
{
return FAILURE;
}
// if 0 was picked then record its position in LastZero
if (firstBit==0 && secondBit==0 && dir == 0)
{
last_zero = bit_number;
}
// check for no devices on 1-wire
if (firstBit==1 && secondBit==1)
break;
// set or clear the bit in the SerialNum byte serial_byte_number
// with mask serial_byte_mask
if (dir == 1)
SearchSerialNum[serial_byte_number] |= serial_byte_mask;
else
SearchSerialNum[serial_byte_number] &= ~serial_byte_mask;
// increment the byte counter bit_number
// and shift the mask serial_byte_mask
bit_number++;
serial_byte_mask <<= 1;
// if the mask is 0 then go to new SerialNum[portnum] byte serial_byte_number
// and reset mask
if (serial_byte_mask == 0)
{
serial_byte_number++;
serial_byte_mask = 1;
}
}
while(serial_byte_number < 8); // loop until through all SerialNum[portnum]
retVal = FAILURE;
// if the search was successful then
if (bit_number == 65)//|| crcl))
{
// search successful so set LastDiscrepancy,LastDevice
LastDiscrepancy = last_zero;
if(LastDiscrepancy==0)
*lastDevice = SUCCESS;
else
*lastDevice = FAILURE;
for(i=0; i<8; i++)
{
deviceAddress[i] = SearchSerialNum[i];
}
return SUCCESS;
}
}
// if no device found then reset counters so next 'next' will be
// like a first
if (!retVal || !SearchSerialNum[0])
{
LastDiscrepancy = 0;
*lastDevice = FAILURE;
retVal = FAILURE;
}
return retVal;
}
// oneTriplet
//
// Uses the 1-Wire Triplet command.
//
// dir – Returns the direction that was chosen (1) or (0).
// firstBit - Returns the first bit of the search (1) or (0).
// secondBit – Returns the complement of the first bit (1) or (0).
//
// returns SUCCES or FAILURE
//
uchar owTriplet(uchar *dir, uchar *firstBit, uchar *secondBit)
{
uchar buff[3];
uchar test;
buff[0] = 0x78;
if(*dir>0)
*dir = (uchar)0xFF;
buff[1] = *dir;
if(!I2CBus_write(&buff[0],2))
{
lcd_putchar('f');
}
if(!I2CBus_read(&buff[2],1))
{
return FAILURE;
}
else
{
test = buff[2] & 0x20;
if(test == 0x20)
*firstBit = 1;
else
*firstBit = 0;
test = buff[2] & 0x40;
if(test == 0x40)
*secondBit = 1;
else
*secondBit = 0;
test = buff[2] & 0x80;
if(test == 0x80)
*dir = 1;
else
*dir = 0;
return SUCCESS;
}
return FAILURE;
}
实例8. OWSearch代码
6. 扩展的1-Wire工作模式
6.1. OWSpeed
实例9给出了如何用DS2482改变1-Wire总线速率,提供高速或标准两种速率。
// OWSpeed – changes the 1-Wire speed to normal or overdrive.
// A Overdrive match rom or overdrive skip rom will be needed.
//
// speed – overdrive (Overdrive) or standard (Standard) speed.
// state_config – The current configuration byte settings.
//
// return – success or failure of the operation.
//
uchar OWSpeed(uchar speed, uchar state_config)
{
uchar buffer[2];
buffer[0] = writeConfigCommand;
if(speed == Overdrive)
buffer[1] = (state_config | 0x08) & 0x7F;
else
buffer[1] = (state_config | 0x80) & 0xF7;
if(!I2CBus_write_packet(buffer,2))
{
return FAILURE;
}
return SUCCESS;
}
实例9. OWSpeed代码
6.2. OWLevel
实例10给出了如何用DS2482改变1-Wire总线的电平。提供正常和供电两种模式。
// OWLevel
//
// level – Normal or Power Delivery mode
// state_config – The current configuration settings
//
// Returns if the operation was Successful or not.
//
uchar OWLevel(uchar level, uchar state_config)
{
uchar buffer[2];
buffer[0] = writeConfigCommand;
// NORMAL = 0, POWER_DELIV = 1
if(level == NORMAL)
buffer[1] = (state_config | 0x01) & 0xEF;
else
buffer[1] = (state_config | 0x10) & 0xFE;
if(!I2CBus_write_packet(buffer,2))
{
return FAILURE;
}
return SUCCESS;
}
实例10. OWLevel代码
6.3. OWReadBitPower
实例11是OWReadBitPower所使用的代码。OWReadBitPower读取一个1-Wire位并执行供电功能。当配置寄存器中的强上拉(SPU)位使能时,在下一位或字节通信完成后,DS2482将拉高1-Wire总线。
// OWReadBitPower
//
// config_byte – current configuration settings
// delay – ms delay used before disabling active pullup
//
// Returns the bit information read.
//
uchar OWReadBitPower(uchar config_byte)
{
uchar buffer[2];
uchar return_bit;
buffer[0] = writeConfigCommand;
buffer[1] = (config_byte | 0x04) & 0xBF;
// Sets strong pullup active so after the next byte or bit
// strong pullup will be active
if(!I2CBus_write_packet(buffer,2))
{
Error;
}
return OWReadBit();
}
实例11. OWReadBitPower代码
6.4. OWWriteBytePower
实例12为OWWriteBytePower所采用的代码,OWWriteBytePower写入1-Wire字节并执行供电功能。当配置寄存器中的强上拉(SPU)位使能时,在下一位或字节通信完成后,DS2482将拉高1-Wire总线。
// OWWriteBytePower
//
// config_byte – current configuration settings.
// wrbyte – byte to be written before the strong pullup is active
// delay – ms delay used before disabling active pullup
//
// Returns failure or success of the operation.
//
uchar OWWriteBytePower(uchar config_byte, uchar wrbyte)
{
uchar buffer[2];
buffer[0] = writeConfigCommand;
buffer[1] = (config_byte | 0x04) & 0xBF;
// Sets strong pullup active so after the next byte or bit
// strong pullup will be active
if(!I2CBus_write_packet(buffer,2))
{
return FAILURE;
}
OWWriteByte(wrbyte);
return SUCCESS;
}
实例12. OWWriteBytePower代码
结束语
DS2482已经过测试,可成功完成I²C接口至1-Wire的转换。本文给出了基于I²C至1-Wire线驱动器DS2482的完整1-Wire接口方案。所提供的代码实例可以在任何一个具有I²C通信端口的主机系统中轻松实现。另外还提供完整的C语言执行代码,可以点击下载。
1-Wire是Maxim Integrated Products, Inc.的注册商标。
我们期待您的反馈! 喜欢?不喜欢?有待改善?或为我们提供建议?请与我们联系 — 我们将根据您的意见或建议改善我们的工作。
网页评价或提供建议
自动更新
需要自动接收最新发布的应用笔记吗?请订阅EE-Mail™ (English only)。
| 更多信息 | |
APP 3684: Jul 07, 2006
|
|
|
|
下载,PDF格式 (102kB)
AN3684,
AN 3684,
APP3684,
Appnote3684,
Appnote 3684
|
|