개요: DS2482는 I²C-to-1-Wire 브리지이다. DS2482는 I²C 통신 기능이 있는 모든 호스트에서 적절한 타이밍의 슬루율 제어 1-Wire 파형을 발생시킬 수 있게 한다. 이 애플리케이션 노트는 DS2482 I²C 1-Wire 라인 드라이버 사용자 가이드로 일반적인 1-Wire Master 동작에 대한 세부 통신 세션을 제공한다.
머리말
1-Wire 네트워크는 단일 마스터와 1개 이상의 슬레이브 소자로 구성된다. 1-Wire Master는 마이크로프로세서의 IO 핀과 수동 생성 타이밍 펄스로 구성할 수 있다. DS2482 I²C-to-1-Wire 브리지를 사용할 경우 설계 엔지니어는 1-Wire 타이밍의 세부사항을 일일이 구현하지 않아도 된다. 그림 1에는 DS2482 구성을 간단하게 표시한 다이어그램이 나와 있다. 본문에서는 DS2482를 이용한 기본 및 확장된 1-Wire 동작의 효율적인 애플리케이션 프로그래밍 인터페이스 (API) 구현을 소개하고, 각 1-Wire 동작의 I²C 통신에 대해 설명한다. DS250x 시리즈와 같은 EPROM 기반 소자의 프로그래밍을 제외하면 이들 동작은 현재 및 향후 1-Wire 소자에 대한 모든 기능을 수행하는 완벽한 기초를 제공한다. 이러한 방식으로 1-Wire 동작을 일반화한다면 1-Wire Master 유형과 상관없이 모든 1-Wire 애플리케이션에 적용할 수 있을 것이다.
이 문서는 DS2482 데이터 시트를 보완하지만 대신하지는 않는다. DS2482는 단일 채널 1-Wire Master(DS2482-100), 저전력 슬립 모드가 있는 단일 채널 1-Wire Master(DS2482-101), 8채널 1-Wire Master(DS2482-800)의 세 가지 구성으로 제공된다.
그림 1. I²C 통신과 1-Wire 네트워크를 위한 브리지로서 DS2482 기능을 보여주는 간략한 다이어그램
1-Wire 인터페이스
모든 1-Wire 통신 세션을 수행하기 위해서는 애플리케이션에서 반드시 갖추어야 하는 원시 함수라고 하는 몇 가지 기본 1-Wire 함수가 있다. 첫 번째 함수(OWReset)는 네트워크상의 모든 1-Wire 슬레이브를 리셋하여 1-Wire Master의 명령에 준비할 수 있게 한다. 두 번째 함수(OWWriteBit)는 1-Wire Master로부터 슬레이브에 1비트를 쓰며 세 번째 함수(OWReadBit)는 1-Wire 슬레이브로부터 1비트를 읽는다. 1-Wire Master는 모든 1-Wire 비트 통신을 시작해야 하기 때문에 "읽기"는 샘플링된 결과를 갖는 단일 비트의 "쓰기"와 기술적으로 같다. 다른 거의 모든 1-Wire 동작은 이러한 세 가지 동작으로 구성할 수 있다. 예를 들어 1-Wire 네트워크에 쓰여진 1바이트는 8번의 단일 비트 쓰기와 같다.
1-Wire 검색 알고리즘도 이와 같은 동일한 3개의 원시 함수를 사용하여 구성할 수 있다. 그러나 DS2482에는 1-Wire 트리플렛이라고 부르는 검색 도움 함수가 포함되어 있어 검색에 요구되는 통신 오버헤드를 크게 줄여준다. 이와 유사하게 1바이트 1-Wire 통신 명령이 있으며, 이는 8번의 단일 비트 명령을 수행하는 것보다 효율적이다.
표 1은 3개의 기본 원시 함수(OWReset, OWWriteBit/OWReadBit, and OWWriteByte/OWReadByte)를 포함하여 다른 3개의 유용한 함수(OWBlock, OWSearch, msDelay)를 보여준다. 이들은 함께 기본 1-Wire 동작의 코어 세트를 구성한다. 이들 동작명은 이 글 전체에서 사용된다.
표 1. 기본 1-Wire 동작
동작
설명
OWReset
1-Wire 리셋 자극(stimulus)을 전송하고 1-Wire 슬레이브 소자의 존재 펄스를 확인한다.
OWWriteBit/OWReadBit
1-Wire 네트워크로부터 단일 비트 데이터를 송신 또는 수신한다.
OWWriteByte/OWReadByte
1-Wire 네트워크로부터 단일 바이트 데이터를 송신 또는 수신한다.
OWBlock
1-Wire 네트워크로부터 다중 바이트 데이터를 송신 또는 수신한다.
OWSearch
1-Wire 검색 알고리즘을 수행한다(애플리케이션 노트 187 참조).
msDelay
최소 지정된 밀리 초만큼 지연한다. 강한 풀 업 동작 타이밍에 사용된다.
대부분의 1-Wire 슬레이브 소자는 표준 및 오버드라이브의 두 가지 다른 통신 속도로 동작할 수 있다. 모든 소자는 표준 속도를 지원하며 오버드라이브는 표준 속도보다 약 10배 빠르다. DS2482는 두 가지 1-Wire 속도를 모두 지원한다.
1-Wire 소자는 1-Wire 네트워크로부터 동작 전력의 일부 또는 전부를 공급받는다. 그러나 일부 소자는 프로토콜의 특정 위치에서 추가적인 전력 공급을 필요로 한다. 예를 들어 어떤 소자는 온도 변환이나 보안 해시 알고리즘 (SHA-1) 해시 계산을 수행할 필요가 있다. 이러한 동작을 위한 전력은 1-Wire 네트워크에 강한 풀 업을 인에이블링하여 공급된다. 이러한 전력 공급 중에는 일반 통신이 발생할 수 없다. DS2482는 1-Wire 통신의 다음 바이트/비트 후에 강한 풀 업을 발생시키는 Strong Pullup (SPU) 플래그를 설정하여 전력을 공급한다. DS2482-100 및 DS2482-101은 또한 보충하는 대전류의 강한 풀 업을 제어하기 위해 외부 핀(PCTLZ)을 제공한다.
표 2에는 1-Wire 속도, 전력 공급 및 프로그래밍 펄스를 위한 확장된 1-Wire 동작이 나와 있다.
표 2. 확장된 1-Wire 동작
동작
설명
OWSpeed
1-Wire 통신 속도를 표준 또는 오버드라이브로 설정한다. 이 설정은 1-Wire Master의 통신 속도만 변경하므로 일반 속도에서 오버드라이브로 전환할 경우 1-Wire 슬레이브 소자에 스위칭 명령을 내려야한다. 1-Wire 슬레이브는 표준 속도 1-Wire 리셋이 발생하면 언제나 표준 속도로 되돌아간다.
OWLevel
1-Wire 전력 레벨(일반 또는 전력 공급)을 설정한다.
OWReadBitPower
1-Wire 네트워크로부터 단일 비트 데이터를 읽고 옵션으로 비트가 완료되는 즉시 전력 공급을 인가한다.
OWWriteBytePower
1-Wire 네트워크에 단일 바이트 데이터를 전송하고 바이트가 완료되는 즉시 전력 공급을 인가한다.
호스트 구성
DS2482 호스트에는 I²C 통신 포트가 있어야 한다. 호스트 구성에 대해서는 이 문서에서 다루지 않는다. 그러나 호스트는 표준 인터페이스 I²C 동작을 제공해야 한다. 이러한 일부 I²C 동작은 호스트 인터페이스에 의해 상위 레벨 기능으로 통합될 수 있다. 필수 동작은 표 3에 나와 있다.
표 3. 필수 I²C 호스트 동작
동작
설명
I2C_start
I²C 시작 명령
I2C_rep_start
I²C 시작 명령 반복
I2C_stop
I²C 정지 명령
I2C_write
1바이트를 I²C 버스에 쓴다. 쓰기 바이트가 함수에 전달된다.
I2C_read
1바이트를 I²C 버스로부터 읽는다. 바이트 읽기는 함수로부터 리턴된다.
DS2482 구성
모든 1-Wire 동작을 수행하기 전에 호스트가 구성되고 DS2482 I²C 1-Wire 라인 드라이버와 동기화되어야 한다. DS2482와 통신하기 위해서는 슬레이브 어드레스를 알아야 한다. 그림 2는 DS2482-100, DS2482-101, DS2482-800의 슬레이브 어드레스를 보여준다.
그림 2. DS2482 I²C 슬레이브 어드레스
DS2482 I²C 명령
다음의 범례는 DS2482 데이터 시트에서 가져온 것으로 소자와의 I²C 통신 시퀀스를 설명하는 간단한 기호를 나타낸다. 다음에서는 이러한 통신 시퀀스가 반복적으로 사용되며 기본 및 확장된 1-Wire 동작을 구현하기 위한 추가 설명과 C 코드 예제가 제공된다.
I²C 통신 시퀀스—범례
기호
설명
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
CHSL
Command 'Channel Select', C3h (DS2482-800 only)
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
데이터 방향 코드
Master-to-Slave
Slave-to-Master
이 문서의 많은 그림에 표시된 데이터 방향 코드는 마스터에서 슬레이브로 (회색) 또는 그 반대 방향인 슬레이브에서 마스터로(흰색)의 통신을 보여준다.
DS2482 구성 동작
다음 동작은 DS2482 설정 및 구성에 사용된다. 이들 동작 중 일부는 1-Wire 동작에 의해 서브루틴으로 호출된다.
DS2482검출
예제 1은 C로 작성된 검출 및 구성 시퀀스를 보여준다. DS2482에 쓰여진 디폴트 값은 1-Wire 속도(표준), 강한 풀 업(오프), 존재 펄스 마스킹 (오프) 및 액티브 풀 업(온)을 포함한다. 이 상태는 소자가 이 디폴트 상태로 다시 리셋할 필요가 있을 때 복구할 수 있도록 전체 변수로 유지된다. 다른 애플리케이션에서는 다른 디폴트 값이 선호될 수 있다.
// DS2482 state
unsigned char I2C_address;
int c1WS, cSPU, cPPM, cAPU;
int short_detected;
//--------------------------------------------------------------------------
// DS2428 Detect routine that sets the I2C address and then performs a
// device reset followed by writing the configuration byte to default values:
// 1-Wire speed (c1WS) = standard (0)
// Strong pullup (cSPU) = off (0)
// Presence pulse masking (cPPM) = off (0)
// Active pullup (cAPU) = on (CONFIG_APU = 0x01)
//
// Returns: TRUE if device was detected and written
// FALSE device not detected or failure to write configuration byte
//
int DS2482_detect(unsigned char addr)
{
// set global address
I2C_address = addr;
// reset the DS2482 ON selected address
if (!DS2482_reset())
return FALSE;
// default configuration
c1WS = FALSE;
cSPU = FALSE;
cPPM = FALSE;
cAPU = CONFIG_APU;
// write the default configuration setup
if (!DS2482_write_config(c1WS | cSPU | cPPM | cAPU))
return FALSE;
return TRUE;
}
예제 1. DS2482 검출
DS2482 소자 리셋
그림 3은 DS2482 소자 리셋 I²C 통신 시퀀스를 보여준다. 예제 2는 C로 작성된 DS2482 리셋 명령 시퀀스를 보여준다. 이 시퀀스는 소자의 스테이트 머신 로직의 전체 리셋을 수행하고 진행 중인 모든 1-Wire 통신을 종료한다. 소자 리셋의 명령 코드는 F0h이다.
그림 3. 파워 업 후 소자 리셋. 이 예에는 명령이 성공적으로 수행되었는지 확인하는 읽기 액세스 옵션이 포함되어 있다.
//--------------------------------------------------------------------------
// Perform a device reset on the DS2482
//
// Returns: TRUE if device was reset
// FALSE device not detected or failure to perform reset
//
int DS2482_reset()
{
unsigned char status;
// Device Reset
// S AD,0 [A] DRST [A] Sr AD,1 [A] [SS] A\ P
// [] indicates from slave
// SS status byte to read to verify state
I2C_start();
I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK);
I2C_write(CMD_DRST, EXPECT_ACK);
I2C_rep_start();
I2C_write(I2C_address | I2C_READ, EXPECT_ACK);
status = I2C_read(NACK);
I2C_stop();
// check for failure due to incorrect read back of status
return ((status & 0xF7) == 0x10);
}
예제 2. 소자 리셋 코드
DS2482 쓰기 구성
그림 4는 DS2482 쓰기 구성 I²C 통신의 예를 보여준다. 예제 3은 C로 작성된 DS2482 쓰기 구성 명령 시퀀스를 보여준다. 쓰기 구성의 명령 코드는 D2h이다.
그림 4. 쓰기 구성 레지스터. 이 예에는 명령이 성공적으로 수행되었는지 확인하는 읽기 옵션이 포함되어 있다.
//--------------------------------------------------------------------------
// Write the configuration register in the DS2482. The configuration
// options are provided in the lower nibble of the provided config byte.
// The uppper nibble in bitwise inverted when written to the DS2482.
//
// Returns: TRUE: config written and response correct
// FALSE: response incorrect
//
int DS2482_write_config(unsigned char config)
{
unsigned char read_config;
// Write configuration (Case A)
// S AD,0 [A] WCFG [A] CF [A] Sr AD,1 [A] [CF] A\ P
// [] indicates from slave
// CF configuration byte to write
I2C_start();
I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK);
I2C_write(CMD_WCFG, EXPECT_ACK);
I2C_write(config | (~config << 4), EXPECT_ACK);
I2C_rep_start();
I2C_write(I2C_address | I2C_READ, EXPECT_ACK);
read_config = I2C_read(NACK);
I2C_stop();
// check for failure due to incorrect read back
if (config != read_config)
{
// handle error
// ...
DS2482_reset();
return FALSE;
}
return TRUE;
}
예제 3. DS2482 쓰기 구성
DS2482 채널 선택
그림 5는 DS2482-800 채널 선택 I²C 통신의 예를 보여준다. 유효한 채널은 0 ~ 7이다. 이 동작은 DS2482-100 또는 DS2482-101에는 적용되지 않는다. 예제 4는 C로 작성된 DS2482-800 채널 선택 명령 시퀀스를 보여준다. 채널 선택의 명령 코드는 C3h이다. 채널이 선택된 후 모든 1-Wire 동작은 해당 채널에서 수행된다.
그림 5. 쓰기 채널 선택 레지스터. 이 예에는 명령이 성공적으로 수행되었는지 확인하는 읽기 옵션이 포함되어 있다.
//--------------------------------------------------------------------------
// Select the 1-Wire channel on a DS2482-800.
//
// Returns: TRUE if channel selected
// FALSE device not detected or failure to perform select
//
int DS2482_channel_select(int channel)
{
unsigned char ch, ch_read, check;
// Channel Select (Case A)
// S AD,0 [A] CHSL [A] CC [A] Sr AD,1 [A] [RR] A\ P
// [] indicates from slave
// CC channel value
// RR channel read back
I2C_start();
I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK);
I2C_write(CMD_CHSL, EXPECT_ACK);
switch (channel)
{
default: case 0: ch = 0xF0; ch_read = 0xB8; break;
case 1: ch = 0xE1; ch_read = 0xB1; break;
case 2: ch = 0xD2; ch_read = 0xAA; break;
case 3: ch = 0xC3; ch_read = 0xA3; break;
case 4: ch = 0xB4; ch_read = 0x9C; break;
case 5: ch = 0xA5; ch_read = 0x95; break;
case 6: ch = 0x96; ch_read = 0x8E; break;
case 7: ch = 0x87; ch_read = 0x87; break;
};
I2C_write(ch, EXPECT_ACK);
I2C_rep_start();
I2C_write(I2C_address | I2C_READ, EXPECT_ACK);
check = I2C_read(NACK);
I2C_stop();
// check for failure due to incorrect read back of channel
return (check == ch_read);
}
예제 4. DS2482-800 채널 선택
DS2482 1-Wire 동작
OWReset
1-Wire 리셋 명령(B4h)은 1-Wire 네트워크에 1-Wire 리셋을 발생시키고 1-Wire 소자의 존재 펄스에 대해 샘플링한다. 샘플의 상태는 상태 레지스터에 있는 존재 펄스 검출 (PPD) 및 짧은 검출 (SD) 필드를 통해 보고된다. 그림 6은 1-Wire 리셋 명령을 위한 I²C 통신을 보여준다. 예제 5는 C로 작성된 존재 펄스를 확인하기 위해 전송된 명령과 상태 레지스터를 보여준다.
그림 6. 1-Wire 리셋. 1-Wire 통신을 시작 또는 종료한다. 1-Wire 명령이 완료될 때까지 아이들(1WB = 0) busy polling되며, 그런 다음 결과를 읽는다.
//--------------------------------------------------------------------------
// Reset all of the devices on the 1-Wire Net and return the result.
//
// Returns: TRUE(1): presence pulse(s) detected, device(s) reset
// FALSE(0): no presence pulses detected
//
int OWReset(void)
{
unsigned char status;
int poll_count = 0;
// 1-Wire reset (Case B)
// S AD,0 [A] 1WRS [A] Sr AD,1 [A] [Status] A [Status] A\ P
// \--------/
// Repeat until 1WB bit has changed to 0
// [] indicates from slave
I2C_start();
I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK);
I2C_write(CMD_1WRS, EXPECT_ACK);
I2C_rep_start();
I2C_write(I2C_address | I2C_READ, EXPECT_ACK);
// loop checking 1WB bit for completion of 1-Wire operation
// abort if poll limit reached
status = I2C_read(ACK);
do
{
status = I2C_read(status & STATUS_1WB);
}
while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT));
I2C_stop();
// check for failure due to poll limit reached
if (poll_count >= POLL_LIMIT)
{
// handle error
// ...
DS2482_reset();
return FALSE;
}
// check for short condition
if (status & STATUS_SD)
short_detected = TRUE;
else
short_detected = FALSE;
// check for presence detect
if (status & STATUS_PPD)
return TRUE;
else
return FALSE;
}
예제 5. OWReset 코드
OWWriteBit/OWReadBit
1-Wire 비트 명령(0x87)은 단일 1-Wire 비트 타임 슬롯을 발생시킨다. 그림 7은 1-Wire 단일 비트 명령의 경우를 위한 I²C 통신 코드를 보여준다. 그림 8은 비트 할당 바이트이며 여기서 V는 전송할 비트이다. 예제 6은 OWWriteBit, OWReadBit, OWTouchBit 코드를 보여준다.
그림 7. 1-Wire 단일 비트. 1-Wire 라인에 단일 타임 슬롯을 발생시킨다. 1WB가 1에서 0으로 변경되면 상태 레지스터는 1-Wire 단일 비트 명령의 유효한 결과를 유지한다.
그림 8. 1-Wire 단일 데이터 바이트
//--------------------------------------------------------------------------
// Send 1 bit of communication to the 1-Wire Net.
// The parameter 'sendbit' least significant bit is used.
//
// 'sendbit' - 1 bit to send (least significant byte)
//
void OWWriteBit(unsigned char sendbit)
{
OWTouchBit(sendbit);
}
//--------------------------------------------------------------------------
// Reads 1 bit of communication from the 1-Wire Net and returns the
// result
//
// Returns: 1 bit read from 1-Wire Net
//
unsigned char OWReadBit(void)
{
return OWTouchBit(0x01);
}
//--------------------------------------------------------------------------
// Send 1 bit of communication to the 1-Wire Net and return the
// result 1 bit read from the 1-Wire Net. The parameter 'sendbit'
// least significant bit is used and the least significant bit
// of the result is the return bit.
//
// 'sendbit' - the least significant bit is the bit to send
//
// Returns: 0: 0 bit read from sendbit
// 1: 1 bit read from sendbit
//
unsigned char OWTouchBit(unsigned char sendbit)
{
unsigned char status;
int poll_count = 0;
// 1-Wire bit (Case B)
// S AD,0 [A] 1WSB [A] BB [A] Sr AD,1 [A] [Status] A [Status] A\ P
// \--------/
// Repeat until 1WB bit has changed to 0
// [] indicates from slave
// BB indicates byte containing bit value in msbit
I2C_start();
I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK);
I2C_write(CMD_1WSB, EXPECT_ACK);
I2C_write(sendbit ? 0x80 : 0x00, EXPECT_ACK);
I2C_rep_start();
I2C_write(I2C_address | I2C_READ, EXPECT_ACK);
// loop checking 1WB bit for completion of 1-Wire operation
// abort if poll limit reached
status = I2C_read(ACK);
do
{
status = I2C_read(status & STATUS_1WB);
}
while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT));
I2C_stop();
// check for failure due to poll limit reached
if (poll_count >= POLL_LIMIT)
{
// handle error
// ...
DS2482_reset();
return 0;
}
// return bit state
if (status & STATUS_SBR)
return 1;
else
return 0;
}
예제 6. 1-Wire 단일 비트 코드
OWWriteByte
1-Wire 쓰기 바이트 명령(A5h)은 1-Wire 버스에 단일 데이터 바이트를 쓴다. 1-Wire 활동이 먼저 종료되어야 DS2482가 이 명령을 처리할 수 있다. 그림 9는 I²C 쓰기 1-Wire 바이트 시퀀스를 보여준다. 코드 예제 7은 이러한 동작으로부터 리턴하기 전에 1-Wire 활동이 완료되었는지 확인한다.
그림 9. 1-Wire 쓰기 바이트. 1-Wire 라인에 명령 코드를 전송한다. 1WB가 1에서 0으로 변경되면 1-Wire 쓰기 바이트 명령이 완료된다.
//--------------------------------------------------------------------------
// Send 8 bits of communication to the 1-Wire Net and verify that the
// 8 bits read from the 1-Wire Net are the same (write operation).
// The parameter 'sendbyte' least significant 8 bits are used.
//
// 'sendbyte' - 8 bits to send (least significant byte)
//
// Returns: TRUE: bytes written and echo was the same
// FALSE: echo was not the same
//
void OWWriteByte(unsigned char sendbyte)
{
unsigned char status;
int poll_count = 0;
// 1-Wire Write Byte (Case B)
// S AD,0 [A] 1WWB [A] DD [A] Sr AD,1 [A] [Status] A [Status] A\ P
// \--------/
// Repeat until 1WB bit has changed to 0
// [] indicates from slave
// DD data to write
I2C_start();
I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK);
I2C_write(CMD_1WWB, EXPECT_ACK);
I2C_write(sendbyte, EXPECT_ACK);
I2C_rep_start();
I2C_write(I2C_address | I2C_READ, EXPECT_ACK);
// loop checking 1WB bit for completion of 1-Wire operation
// abort if poll limit reached
status = I2C_read(ACK);
do
{
status = I2C_read(status & STATUS_1WB);
}
while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT));
I2C_stop();
// check for failure due to poll limit reached
if (poll_count >= POLL_LIMIT)
{
// handle error
// ...
DS2482_reset();
}
}
예제 7. OWWriteByte 코드
OWReadByte
1-Wire 읽기 바이트 명령(96h)은 1-Wire 네트워크로부터 단일 바이트를 읽는다. 1-Wire 활동이 먼저 종료되어야 DS2482가 이 명령을 처리할 수 있다. 그림 10은 I²C 시퀀스를 보여준다. 1-Wire 읽기 바이트 명령을 위한 코드는 코드 예제 8에서 볼 수 있다. 읽기 바이트 명령을 발생시킨 후 1-Wire 활동이 완료되었는지 확인한 다음 결과가 리턴된다.
그림 10. 1-Wire 읽기 바이트. 1-Wire 네트워크로부터 1바이트를 읽는다. 1WB 비트가 1에서 0으로 변경될 때까지 상태 레지스터를 폴링한다. 그런 다음 읽기 포인터를 데이터 읽기 레지스터(코드 E1h)로 설정하고 소자에 다시 액세스하여 1-Wire 네트워크에서 가져온 데이터 바이트를 읽는다.
//--------------------------------------------------------------------------
// Send 8 bits of read communication to the 1-Wire Net and return the
// result 8 bits read from the 1-Wire Net.
//
// Returns: 8 bits read from 1-Wire Net
//
unsigned char OWReadByte(void)
{
unsigned char data, status;
int poll_count = 0;
// 1-Wire Read Bytes (Case C)
// S AD,0 [A] 1WRB [A] Sr AD,1 [A] [Status] A [Status] A\
// \--------/
// Repeat until 1WB bit has changed to 0
// Sr AD,0 [A] SRP [A] E1 [A] Sr AD,1 [A] DD A\ P
//
// [] indicates from slave
// DD data read
I2C_start();
I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK);
I2C_write(CMD_1WRB, EXPECT_ACK);
I2C_rep_start();
I2C_write(I2C_address | I2C_READ, EXPECT_ACK);
// loop checking 1WB bit for completion of 1-Wire operation
// abort if poll limit reached
status = I2C_read(ACK);
do
{
status = I2C_read(status & STATUS_1WB);
}
while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT));
// check for failure due to poll limit reached
if (poll_count >= POLL_LIMIT)
{
// handle error
// ...
DS2482_reset();
return 0;
}
I2C_rep_start();
I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK);
I2C_write(CMD_SRP, EXPECT_ACK);
I2C_write(0xE1, EXPECT_ACK);
I2C_rep_start();
I2C_write(I2C_address | I2C_READ, EXPECT_ACK);
data = I2C_read(NACK);
I2C_stop();
return data;
}
예제 8. OWReadByte 코드
OWBlock
OWBlock 동작은 한 그룹의 1-Wire 바이트 동작을 수행한다. 이 동작은 1-Wire 네트워크에서 데이터 블록을 전송할 때 유용하다. 예제 9는 OWBlock의 코드 예제를 보여준다.
//--------------------------------------------------------------------------
// The 'OWBlock' transfers a block of data to and from the
// 1-Wire Net. The result is returned in the same buffer.
//
// 'tran_buf' - pointer to a block of unsigned
// chars of length 'tran_len' that will be sent
// to the 1-Wire Net
// 'tran_len' - length in bytes to transfer
//
void OWBlock(unsigned char *tran_buf, int tran_len)
{
int i;
for (i = 0; i < tran_len; i++)
tran_buf[i] = OWTouchByte(tran_buf[i]);
}
//--------------------------------------------------------------------------
// Send 8 bits of communication to the 1-Wire Net and return the
// result 8 bits read from the 1-Wire Net. The parameter 'sendbyte'
// least significant 8 bits are used and the least significant 8 bits
// of the result are the return byte.
//
// 'sendbyte' - 8 bits to send (least significant byte)
//
// Returns: 8 bits read from sendbyte
//
unsigned char OWTouchByte(unsigned char sendbyte)
{
if (sendbyte == 0xFF)
return OWReadByte();
else
{
OWWriteByte(sendbyte);
return sendbyte;
}
}
예제 9. OWBlock 코드
OWSearch/1-Wire 트리플렛 명령
1-Wire 검색은 1-Wire 네트워크에 존재하는 소자의 64비트 고유 등록 번호를 알아내는 데 사용된다. 고유 등록 번호는 ROM(Read-Only Memory)에 있기 때문에 1-Wire 데이터 시트에서는 ROM 번호로 언급되기도 한다. 검색은 1-Wire 리셋으로 시작하여 검색 명령이 이어진다. 모든 1-Wire 소자가 응답하는 검색 명령은 F0h이다. 검색 명령 후 1-Wire Master는 2진 검색을 수행하여 1개 소자를 찾는다. 2진 검색은 먼저 비트를 읽고, 비트의 보수를 읽은 다음 1비트를 써서 검색에 남아 있는 소자를 표시하여 64비트를 하나씩 찾는다. 이들 3개의 단일 비트 시퀀스를 트리플렛이라고 부른다. DS2482는 이 트리플렛을 수행함으로써 보다 효율적으로 1-Wire 검색을 수행하는 단축 명령을 제공한다.
트리플렛 명령(78h)은 1-Wire 네트워크에 3개의 타임 슬롯, 2개의 읽기 슬롯, 그리고 1개의 쓰기 타임 슬롯을 발생시킨다. 상태 레지스터의 방향 바이트(DIR)는 쓰기 타임 슬롯의 유형을 결정한다(그림 11). 예제 10은 1-Wire 트리플렛 명령을 사용하는 완벽한 1-Wire 검색을 보여준다. 예제는 또한 첫 번째와 다음 소자를 찾을 수 있도록 검색을 설정하는 기능을 갖고 있다. OWFirst를 호출하고 이어 OWNext를 반복 호출하면 1-Wire 네트워크상의 모든 소자를 찾을 수 있다. 1-Wire 검색 알고리즘에 대한 자세한 내용은 애플리케이션 노트 187, "1-Wire Search Algorithm"을 참조한다.
그림 11. 1-Wire 트리플렛. 1-Wire 네트워크에서 ROM 검색 기능을 수행한다. 1-Wire 기능 완료에는 아이들 시간이 필요하다. 그런 다음 읽기 모드에서 소자에 액세스하여 1-Wire 트리플렛 명령으로부터 결과를 가져온다.
// Search state
unsigned char ROM_NO[8];
int LastDiscrepancy;
int LastFamilyDiscrepancy;
int LastDeviceFlag;
unsigned char crc8;
//--------------------------------------------------------------------------
// Find the 'first' devices on the 1-Wire network
// Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : no device present
//
int OWFirst()
{
// reset the search state
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
return OWSearch();
}
//--------------------------------------------------------------------------
// Find the 'next' devices on the 1-Wire network
// Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : device not found, end of search
//
int OWNext()
{
// leave the search state alone
return OWSearch();
}
//--------------------------------------------------------------------------
// The 'OWSearch' function does a general search. This function
// continues from the previous search state. The search state
// can be reset by using the 'OWFirst' function.
// This function contains one parameter 'alarm_only'.
// When 'alarm_only' is TRUE (1) the find alarm command
// 0xEC is sent instead of the normal search command 0xF0.
// Using the find alarm command 0xEC will limit the search to only
// 1-Wire devices that are in an 'alarm' state.
//
// Returns: TRUE (1) : when a 1-Wire device was found and its
// Serial Number placed in the global ROM
// FALSE (0): when no new device was found. Either the
// last search was the last device or there
// are no devices on the 1-Wire Net.
//
int OWSearch()
{
int id_bit_number;
int last_zero, rom_byte_number, search_result;
int id_bit, cmp_id_bit;
unsigned char rom_byte_mask, search_direction, status;
// initialize for search
id_bit_number = 1;
last_zero = 0;
rom_byte_number = 0;
rom_byte_mask = 1;
search_result = FALSE;
crc8 = 0;
// if the last call was not the last one
if (!LastDeviceFlag)
{
// 1-Wire reset
if (!OWReset())
{
// reset the search
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
return FALSE;
}
// issue the search command
OWWriteByte(0xF0);
// loop to do the search
do
{
// if this discrepancy if before the Last Discrepancy
// on a previous next then pick the same as last time
if (id_bit_number < LastDiscrepancy)
{
if ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0)
search_direction = 1;
else
search_direction = 0;
}
else
{
// if equal to last pick 1, if not then pick 0
if (id_bit_number == LastDiscrepancy)
search_direction = 1;
else
search_direction = 0;
}
// Perform a triple operation on the DS2482 which will perform
// 2 read bits and 1 write bit
status = DS2482_search_triplet(search_direction);
// check bit results in status byte
id_bit = ((status & STATUS_SBR) == STATUS_SBR);
cmp_id_bit = ((status & STATUS_TSB) == STATUS_TSB);
search_direction =
((status & STATUS_DIR) == STATUS_DIR) ? (byte)1 : (byte)0;
// check for no devices on 1-Wire
if ((id_bit) && (cmp_id_bit))
break;
else
{
if ((!id_bit) && (!cmp_id_bit) && (search_direction == 0))
{
last_zero = id_bit_number;
// check for Last discrepancy in family
if (last_zero < 9)
LastFamilyDiscrepancy = last_zero;
}
// set or clear the bit in the ROM byte rom_byte_number
// with mask rom_byte_mask
if (search_direction == 1)
ROM_NO[rom_byte_number] |= rom_byte_mask;
else
ROM_NO[rom_byte_number] &= (byte)~rom_byte_mask;
// increment the byte counter id_bit_number
// and shift the mask rom_byte_mask
id_bit_number++;
rom_byte_mask <<= 1;
// if the mask is 0 then go to new SerialNum byte rom_byte_number
// and reset mask
if (rom_byte_mask == 0)
{
calc_crc8(ROM_NO[rom_byte_number]); // accumulate the CRC
rom_byte_number++;
rom_byte_mask = 1;
}
}
}
while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
// if the search was successful then
if (!((id_bit_number < 65) || (crc8 != 0)))
{
// search successful so set LastDiscrepancy,LastDeviceFlag
// search_result
LastDiscrepancy = last_zero;
// check for last device
if (LastDiscrepancy == 0)
LastDeviceFlag = TRUE;
search_result = TRUE;
}
}
// if no device found then reset counters so next
// 'search' will be like a first
if (!search_result || (ROM_NO[0] == 0))
{
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
search_result = FALSE;
}
return search_result;
}
//--------------------------------------------------------------------------
// Use the DS2482 help command '1-Wire triplet' to perform one bit of a
//1-Wire search.
//This command does two read bits and one write bit. The write bit
// is either the default direction (all device have same bit) or in case of
// a discrepancy, the 'search_direction' parameter is used.
//
// Returns – The DS2482 status byte result from the triplet command
//
unsigned char DS2482_search_triplet(int search_direction)
{
unsigned char status;
int poll_count = 0;
// 1-Wire Triplet (Case B)
// S AD,0 [A] 1WT [A] SS [A] Sr AD,1 [A] [Status] A [Status] A\ P
// \--------/
// Repeat until 1WB bit has changed to 0
// [] indicates from slave
// SS indicates byte containing search direction bit value in msbit
I2C_start();
I2C_write(I2C_address | I2C_WRITE, EXPECT_ACK);
I2C_write(CMD_1WT, EXPECT_ACK);
I2C_write(search_direction ? 0x80 : 0x00, EXPECT_ACK);
I2C_rep_start();
I2C_write(I2C_address | I2C_READ, EXPECT_ACK);
// loop checking 1WB bit for completion of 1-Wire operation
// abort if poll limit reached
status = I2C_read(ACK);
do
{
status = I2C_read(status & STATUS_1WB);
}
while ((status & STATUS_1WB) && (poll_count++ < POLL_LIMIT));
I2C_stop();
// check for failure due to poll limit reached
if (poll_count >= POLL_LIMIT)
{
// handle error
// ...
DS2482_reset();
return 0;
}
// return status byte
return status;
}
예제 10. OWSearch 코드
확장된 1-WIRE 동작
OWSpeed
예제 11은 DS2482를 사용하여 1-Wire 네트워크의 속도를 변경하는 방법을 보여준다. 모든 1-Wire 소자의 디폴트 구성은 표준 통신 속도이다. 일부 소자는 이후에 소자의 Overdrive-Match-ROM 또는 Overdrive-Skip-ROM 명령을 사용하여 오버드라이브 속도로 전환할 수 있다. 일단 소자가 오버드라이브 속도에 있으면 모든 1-Wire 통신을 오버드라이브 속도로 처리할 수 있다. 표준 속도 1-Wire 리셋은 소자를 표준 속도로 되돌린다.
//--------------------------------------------------------------------------
// Set the 1-Wire Net communication speed.
//
// 'new_speed' - new speed defined as
// MODE_STANDARD 0x00
// MODE_OVERDRIVE 0x01
//
// Returns: current 1-Wire Net speed
//
int OWSpeed(int new_speed)
{
// set the speed
if (new_speed == MODE_OVERDRIVE)
c1WS = CONFIG_1WS;
else
c1WS = FALSE;
// write the new config
DS2482_write_config(c1WS | cSPU | cPPM | cAPU);
return new_speed;
}
예제 11. OWSpeed 코드
OWLevel
예제 12는 DS2482를 사용하여 1-Wire 네트워크의 레벨을 변경하는 방법을 보여준다. DS2482는 1-Wire 통신 비트 또는 바이트 후에만 강한 풀 업을 인에이블한다. 따라서 OWLevel 코드는 1-Wire 네트워크를 표준 풀 업으로만 리턴할 수 있다. 강한 풀 업을 인에이블하려면 OWWriteBytePower 또는 OWReadBitPower 동작을 사용한다.
//--------------------------------------------------------------------------
// Set the 1-Wire Net line level pullup to normal. The DS2482 only
// allows enabling strong pullup on a bit or byte event. Consequently this
// function only allows the MODE_STANDARD argument. To enable strong pullup
// use OWWriteBytePower or OWReadBitPower.
//
// 'new_level' - new level defined as
// MODE_STANDARD 0x00
//
// Returns: current 1-Wire Net level
//
int OWLevel(int new_level)
{
// function only will turn back to non-strong pullup
if (new_level != MODE_STANDARD)
return MODE_STRONG;
// clear the strong pullup bit in the global config state
cSPU = FALSE;
// write the new config
DS2482_write_config(c1WS | cSPU | cPPM | cAPU);
return MODE_STANDARD;
}
예제 12. OWLevel 코드
OWReadBitPower
예제 13은 1-Wire 비트를 읽고 전력 공급을 구현하는 OWReadBitPower에 사용되는 코드를 보여준다. 구성 레지스터에서 Strong Pullup (SPU) 비트를 인에이블하면 DS2482는 다음 비트 또는 바이트 통신 후 능동적으로 1-Wire 네트워크를 하이로 구동한다. 이 동작은 비트 읽기가 예상된 응답인지를 확인한다. 만약 응답이 올바르지 않으면 1-Wire 레벨은 표준 풀 업 상태로 리턴한다.
//--------------------------------------------------------------------------
// Send 1 bit of communication to the 1-Wire Net and verify that the
// response matches the 'applyPowerResponse' bit and apply power delivery
// to the 1-Wire net. Note that some implementations may apply the power
// first and then turn it off if the response is incorrect.
//
// 'applyPowerResponse' - 1 bit response to check, if correct then start
// power delivery
//
// Returns: TRUE: bit written and response correct, strong pullup now on
// FALSE: response incorrect
//
int OWReadBitPower(int applyPowerResponse)
{
unsigned char rdbit;
// set strong pullup enable
cSPU = CONFIG_SPU;
// write the new config
if (!DS2482_write_config(c1WS | cSPU | cPPM | cAPU))
return FALSE;
// perform read bit
rdbit = OWReadBit();
// check if response was correct, if not then turn off strong pullup
if (rdbit != applyPowerResponse)
{
OWLevel(MODE_STANDARD);
return FALSE;
}
return TRUE;
}
예제 13. OWReadBitPower 코드
OWWriteBytePower
예제 14는 1-Wire 바이트를 쓰고 강한 풀 업 전력 공급을 구현하는 OWWriteBytePower에 사용되는 코드를 보여준다. 구성 레지스터에서 Strong Pullup (SPU) 비트가 인에이블되면 DS2482는 다음 비트 또는 바이트 통신 후 능동적으로 1-Wire 네트워크를 하이로 구동한다. 다음에 OWLevel 함수를 호출하면 1-Wire 네트워크는 표준 풀 업으로 리턴된다.
//--------------------------------------------------------------------------
// Send 8 bits of communication to the 1-Wire Net and verify that the
// 8 bits read from the 1-Wire Net are the same (write operation).
// The parameter 'sendbyte' least significant 8 bits are used. After the
// 8 bits are sent change the level of the 1-Wire net.
//
// 'sendbyte' - 8 bits to send (least significant bit)
//
// Returns: TRUE: bytes written and echo was the same, strong pullup now on
// FALSE: echo was not the same
//
int OWWriteBytePower(int sendbyte)
{
// set strong pullup enable
cSPU = CONFIG_SPU;
// write the new config
if (!DS2482_write_config(c1WS | cSPU | cPPM | cAPU))
return FALSE;
// perform write byte
OWWriteByte(sendbyte);
return TRUE;
}
예제 14. OWWriteBytePower 코드
결론
DS2482는 I²C 버스를 1-Wire 네트워크에 성공적으로 연결한다. 이 글에서는 DS2482 I²C 1-Wire 라인 드라이버 제품군을 사용하여 구현하는 완벽한 1-Wire 애플리케이션 인터페이스 솔루션을 선보였다. 코드 예제는 I²C 통신 포트가 있는 모든 호스트 시스템에서 간편하게 구현할 수 있으며, 완벽한 C 구현도 다운로드할 수 있다. 이 코드의 테스트 플랫폼으로는 CMAXQUSB EV 킷이 사용되었다.
개정 정보
2005년 11월 Version 1.0–최초 릴리스
2008년 9월 Version 2.0–하위 레벨 I²C 통신 호출을 사용하는 코드 예제 변경에 따른 텍스트 개정