Dallas Semiconductor make a range of devices that communicate
on a network which may be only two wires. The devices take their
power from the data line when there is no communication taking place.
Below is code to talk to these devices. This assumes a PIC running at
10MHz and the 'Wire' is the open-collector pin RA4. The temperature
measurement shown here assumes a Vcc powered DS1820 and NOT
a parasitic powered device.
The code is mainly in assembler as this is necessary to get the best
speed. Forth is quite happy to have either.
REQUIRED FC! \ Used during debug
XASM MACRO: WIRE PORTA 4 MACRO; \ Define Wire drive
IN-META
| VARIABLE CHECKSUM
: INIT-WIRE $10 PORTA C! $0F TRISA C! ;
CODE RESET-WIRE ( - )
BCF WIRE \ Wire LO
N 2 DO \ Wait ~600uS
N 1+ 250 DO LOOP
LOOP
BSF WIRE \ Wire HI
N 20 DO LOOP
BEGIN WIRE -BIT UNTIL \ Wait for Presence to
BEGIN WIRE BIT UNTIL \ come and go
CLRF CHECKSUM \ Reset checksum
RETURN C;
CODE READ-WIRE ( - b )
DECF FSR
CLRF (FSR) \ Zero stack item
N 8 DO \ 8 Bits
BCF WIRE \ Pulse >1uS
NOP
NOP
BSF WIRE
N 1+ 13 DO LOOP \ ~ 10uS
BSF STATUS CY
BTFSS WIRE \ Read Wire
BCF STATUS CY
RRF (FSR) \ Add bit to stack
RLF (FSR) ,W \ Get it back
CLRW \ Checksum X8+X5+X4+1
BTFSC STATUS CY
MOVLW 1
XORWF CHECKSUM ,W
ANDLW 1
STATUS Z BIT
IF BCF STATUS CY
ELSE BSF STATUS CY
MOVLW $18
XORWF CHECKSUM
THEN RRF CHECKSUM
N 1+ 60 DO LOOP \ ~ 45 uS
LOOP
RETURN C;
CODE WRITE-WIRE ( b - )
N 8 DO \ 8 Bits
RRF (FSR) \ Get bit from stack
BCF WIRE \ Wire LO
STATUS CY BIT
IF NOP
NOP
BSF WIRE \ 1uS then Wire HI
N 1+ 75 DO LOOP \ Delay till end ~ 60uS
ELSE N 1+ 75 DO LOOP \ Delay till end
BSF WIRE \ Wire HI
THEN
NOP
NOP \ >1uS between bits
LOOP
INCF FSR \ DROP stack value
RETURN C;
: ?TEMP ( - n f ) \ Convert temp. read and calc to 0.01
RESET-WIRE
$CC WRITE-WIRE \ Skip ROM
$44 WRITE-WIRE \ Convert
BEGIN READ-WIRE UNTIL \ Convertion over
RESET-WIRE
$CC WRITE-WIRE
$BE WRITE-WIRE \ Read Scratchpad
READ-WIRE
READ-WIRE SWAP ABS 2/ 100 UM* 20 0 W-
3 FOR READ-WIRE DROP NEXT \ Not required
READ-WIRE
READ-WIRE DUP ROT - 100 UM* ROT UM/MOD NIP 0 W+
ROT IF || NEGATE | THEN
READ-WIRE DROP CHECKSUM C@ \ = 0 If correct
RESET-WIRE C;