개요: 마이크로프로세서는 전용 버스 마스터가 존재하지 않아도 손쉽게 1-Wire 타이밍 신호를 발생시킬 수 있다(예: DS2480B, DS2482). 이 애플리케이션 노트에서는 'C'로 작성된 기본적인 표준 속도 1-Wire 마스터 통신 루틴의 한 예를 제공하고 오버드라이브 통신 속도에 대해서도 설명한다. 1-Wire 버스의 4가지 기본 동작은 리셋, 1 비트 쓰기, 0 비트 쓰기 및 비트 읽기이다. 바이트 함수는 비트 동작을 여러 번 호출하여 파생될 수 있다. 제공되는 시간 값은 다양한 라인 조건에서 모든 1-Wire 소자와 통신할 수 있도록 가장 견고한 1-Wire 마스터를 생성한다.
머리말
마이크로프로세서는 전용 버스 마스터가 존재하지 않아도 손쉽게 1-Wire 타이밍 신호를 발생시킬 수 있다. 이 애플리케이션 노트에서는 'C'로 작성된 기본적인 표준 속도 1-Wire 마스터 통신 루틴의 한 예를 제공하고 오버드라이브 통신 속도에 대해서도 설명한다. 예로 제공되는 코드의 원활한 동작을 위한 몇 가지 시스템 요구사항은 다음과 같다.
시스템은 표준 속도의 경우 정확하고 반복 가능한 1µs 지연과 오버드라이브 속도의 경우 0.25µs 지연을 발생시킬 수 있어야 한다.
발생되는 동안 통신 동작이 방해를 받아서는 안 된다.
1-Wire 버스의 4가지 기본 동작은 리셋, 1비트 쓰기, 0비트 쓰기 및 비트 읽기이다. 소자 데이터 시트에서 1비트의 통신을 수행하는 데 걸리는 시간을 타임 슬롯이라 한다. 바이트 함수는 비트 동작을 여러 번 호출하여 파생될 수 있다. 각 동작에 대한 간단한 설명과 그것을 발생시키는 데 필요한 단계 목록은 표 1과 같다. 그림 1은 파형을 그래픽으로 나타낸 것이다. 표 2는 1-Wire 마스터가 가장 일반적인 라인 조건에서 1-Wire 소자와 통신하기 위한 권장 타이밍을 나타낸 것이다. 1-Wire 마스터를 특정 소자 셋과 라인 조건으로 제한할 경우 다른 값들이 사용될 수 있다. 시스템 및 소자 파라미터에 들어가 최소/최대값을 결정하려면 다운로드 가능한 워크시트를 참조한다.
표 1. 1-Wire 동작
Operation
Description
Implementation
Write 1 bit
Send a '1' bit to the 1-Wire slaves (Write 1 time slot)
Drive bus low, delay A Release bus, delay B
Write 0 bit
send a '0' bit to the 1-Wire slaves (Write 0 time slot)
Drive bus low, delay C Release bus, delay D
Read bit
Read 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
Reset
Reset the 1-Wire bus slave devices and ready them for a command
Delay G
Drive bus low, delay H
Release bus, delay I
Sample bus, 0 = device(s) present, 1 = no device present
Delay J
다음 코드 샘플들은 IO 포트 위치에 데이터 바이트를 읽고 쓰기 위해 2개의 일반적인 'C' 함수 outp와 inp에 의존한다. 이 함수들은 일반적으로 <conio.h> 표준 라이브러리에 위치하며 플랫폼 해당 함수로 대체될 수 있다.
// 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 슬레이브 소자에 의해 풀 다운된다.
코드에서 함수 tickDelay는 가변 수의 1/4 마이크로초를 기다리도록 사용자가 발생시킨 루틴이다. 이 함수는 실행되는 각각의 고유한 하드웨어 플랫폼에 따라 달라지므로 여기에서는 구현되지 않는다. 다음은 권장 표준 및 오버드라이브 속도 틱 값을 설정하기 위해 SetSpeed 함수와 함께 tickDelay 함수를 선언한 것이다.
예제 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 동작을 위한 코드 예를 나타낸 것이다.
예제 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 버스로부터 동시 쓰기 및 읽기이다. 이 함수는 한 블록의 쓰기와 읽기가 구축될 수 있도록 파생된 것으로, 일부 플랫폼에서 더 효율적이며 Maxim이 제공하는 API에서 일반적으로 사용된다. OWBlock 함수는 OWTouchByte 함수를 사용하여 1-Wire에 한 블록의 데이터를 송신하고 수신한다. OWTouchByte(0xFF)는 OWReadByte()와 같고 OWTouchByte(data)는 OWWriteByte(data)와 같다.
이러한 함수들과 tickDelay가 비트, 바이트 및 블록 레벨에서 1-Wire 버스의 기본적인 제어에 필요한 전부이다. 예제 4의 다음 예는 DS2432의 인증된 SHA-1 페이지를 읽기 위해 이러한 함수들을 함께 사용하는 방법을 보여준다.
예제 4. 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[i] = 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[i] = 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 슬레이브의 고유 ID를 찾아내기 위한 방법이다. 애플리케이션 노트 187, "1-Wire Search Algorithm"에서는 이 방법에 대해 자세히 설명하고 이 기본 1-Wire 함수와 함께 사용할 수 있는 'C' 코드를 제공한다.
마이크로프로세서의 주변기기로 사용될 수 있는 일부 1-Wire 마스터 칩이 있다. DS2480B 직렬 1-Wire 라인 드라이버는 표준 직렬 포트에 대한 손쉬운 연결을 제공한다. 또한 DS2482-100, DS2482-101 및 DS2482-800은 I²C 포트로 연결이 가능하다.
개정 정보
07/06/00: Version 1.0—Initial release.
05/28/02: Version 2.0—Correct 1-Wire reset sample time. Add wave figure, links, and more code examples.
02/02/04: Version 2.1—Add overdrive support, provided min/max on timings, and update example.
09/06/05: Version 2.2—Correct polarity of PIO in Code Examples description.
08/04/09: Version 2.3—Add AN4206 reference. Change recommended overdrive E value. Correct OWTouchReset sample. Move min/max calculated fields in 1-Wire master timing to worksheet. Add DS2482 reference.