Interfacing with the Dallas DS2401 Silicon Serial Number

copyright Peter H. Anderson, Baltimore, MD, Sept, '98


Introduction.

This discussion deals with the DS2401 Silicon Serial Number. The device is available from Newark and we sell it as a convenience to hobbyists in a TO92 transistor package. A data sheet is available from http://www.dalsemi.com.

It's function appears at first glance to be somewhat trivial. It simply provides a unique 48-bit serial number. However, it is an extremely inexpensive technique to uniquely identify a specific product.

A simple example. We are currently using this in a data logger. When the data is uploaded to a PC, the unique serial number is first sent followed by the data. This avoids the need for a human to read a locally assigned number off the unit and then manually enter it in the data file.

An alternative would of course be to store a unique serial number in a PIC which is equipped with EEPROM such as the 12CE518 or 16F84. I assume a creative person could automate the device burning process by automatically generating a new hex file for each programmed PIC, but for less than $2.00 the DS2401 appears a whole lot more straight forward.

The DS2401 is a member of the Dallas 1-W family which requires only the signal lead and ground. An input logic one is supplied via a 4.7 K pullup resistor to the positive supply and may be as low as 2.1 V with an input leakage as high as 5 uA. Thus, the device may be safely operated with supplies as low as 2.5 V. Five uA is small, but in our design we are striving to conserve power and are thus using a spare PIC output to apply the positive voltage to the 4.7K resistor only for that brief moment when the serial number is fetched.

Operation is simply a matter of intializing the device and sending the "read ROM" command (33H). Eight bytes are then read; first a one byte device code, followed by a six byte serial number and finally an 8-bit CRC byte. For the DS2401, the device code is 01.

It is worthy of note that any device in the Dallas 1-W family may perform a similar function. For example, if the nature of the design dictated the use of a DS2430A EEPROM or a DS1820 temperature sensor, the device could double as the "silicon serial number". In our case, we didn't need these additional capabilities and there is no point in using a $5.00 DS1820 when a $2.00 DS2401 will do the job.

Program 2401_1.ASM.

The following program reads the serial number and writes the eight bytes to a data buffer beginning at RAM location 38H. This is then displayed on a serial LCD.

Note that the low level 1-wire routines are the same as those discussed in other pieces on the DS2430A EEPROM and DS1820 and DS1821. They have been prefaced with "_1W"; for example, "_1W_OUT_BYTE" as this discussion was developed as a part of an event logger which includes interfacing with a Microchip 24LC256 (Philips I2C protocol) and a DS1602 (3-wire protocol). The use of the _1W_ prefix allows us to distinguish between functionally similar routines for the two and three wire protocols.

Note that the functions LCD_RESET, LCD_VAL, LCD_CHAR and LCD_DELAY are part of a general purpose library we developd to interface with our PIC-an-LCD module. This is discussed elsewhere on this web page.

; Program 2401_1.ASM
;
; Illustrates use of DS2401 Silicon Serial Number.  
;
; Reads 64 bit serial number, saves in 8-bit data buffer and displays
; on serial PIC-an-LCD in the form XXXX YYYY
;
; Uses LCD_F84.ASM.  Serial is RA.0 (terminal 17).
;
;	PIC16F84			DS2401	
;
; PWR_ON (RB.1, term 7) ------
;			      |
;			     4.7K	
;			      |	
; ID_DQ (RB.0, term 6) -------------------- DQ 
; 
; copyright, P. H. Anderson, Sept, 98
	
	LIST p=16F84		
#include <p16f84.inc>		
	__CONFIG 11H		

	CONSTANT PWR_ON		; RB.1
	CONSTANT ID_DQ=0	; RB.0

	CONSTANT BASE_VAR=0CH	

	CONSTANT DATA_BUFF=38H
	

N		EQU BASE_VAR+0	; general index

INDEX	   	EQU BASE_VAR+1	; these vars used by the 
O_BYTE	   	EQU BASE_VAR+2	; common 1-wire routines
I_BYTE	   	EQU BASE_VAR+3

LOOP_10US	EQU BASE_VAR+4	; used for 10 usec timing
PORTB_MIRROR   	EQU BASE_VAR+5


	ORG 000H	        

	GOTO MAIN

MAIN:
	; I/Os are all inputs
	; set up option	

	CALL LCD_RESET
TOP:
        CALL READ_ID		; read 8 byte ID and save in DATA_BUFF
	CALL SEND_8		; display DATA_BUFF
	GOTO $			; loop indefinitely
	
READ_ID:
	BSF	PORTB, PWR_ON	; turn on power
	BSF	STATUS, RP0
	BCF	TRISB, PWR_ON
	BCF 	STATUS, RP0

	MOVLW 	.250		; wait for 500 ms to be sure the device  
	CALL	LCD_DELAY	; has stabilized.
	CALL	LCD_DELAY
	
 	CALL	_1W_INIT	; intitialize DS2401
	
        MOVLW	33H		; read ROM
        MOVWF	O_BYTE
        CALL	_1W_OUT_BYTE

        MOVLW	.8		; number of bytes of data
	MOVWF	N

	MOVLW	DATA_BUFF	; beginning of data buffer
	MOVWF	FSR   

READ_ID_1:			; fetch each of 8 bytes
	CALL	_1W_IN_BYTE
	MOVF	I_BYTE, W
	MOVWF	INDF
	
	INCF	FSR, F
	DECFSZ	N, F
	GOTO	READ_ID_1

	BSF	STATUS, RP0	; turn power off
	BSF	TRISB, PWR_ON
	BCF 	STATUS, RP0

	RETURN	

SEND_8:	; sends first 8 bytes of data buff
	; to serial LCD in form XXXX YYYY followed by a new line

	MOVLW 	DATA_BUFF
	MOVWF	FSR

	MOVLW	.4		; four bytes at a time
	MOVWF	N

SEND_8_1:
	MOVF 	INDF, W		; fetch the byte and display
	CALL 	LCD_VAL	
	INCF 	FSR, F
	DECFSZ	N, F
	GOTO 	SEND_8_1

	MOVLW 	" "		; send a space
	CALL	LCD_CHAR

	MOVLW	.4		; second 4 bytes 
	MOVWF	N

SEND_8_2:
	MOVF 	INDF, W		; fetch the byte and display
	CALL 	LCD_VAL	
	INCF 	FSR, F
	DECFSZ	N, F
	GOTO 	SEND_8_2
	CALL	SEND_CR
	RETURN
;;;;;

SEND_CR:			
	MOVLW	0AH
	CALL	LCD_CHAR
	MOVLW	0DH
	CALL	LCD_CHAR
	RETURN

; The following are standard 1-Wire routines.

_1W_INIT:
        CALL	_1W_PIN_HI
        CALL	_1W_PIN_LO

	MOVLW	.50              ; 500 us delay
	CALL 	DELAY_10USEC

	CALL	_1W_PIN_HI		  
        MOVLW 	.50		; 500 usec delay
        CALL 	DELAY_10USEC

        RETURN

;;;;;

_1W_IN_BYTE:    		; returns byte in I_BYTE
	MOVLW	.8
	MOVWF	INDEX
        CLRF	I_BYTE
_1W_IN_BYTE_1:
	CALL _1W_PIN_LO		; momentary low on DATA_PIN
        CLRWDT
	CALL _1W_PIN_HI
	NOP
	NOP
	NOP
	NOP
	NOP
        NOP
        MOVF	PORTB, W	; 7 usecs later, read data state
	MOVWF	PORTB_MIRROR                                                        
	BTFSS	PORTB_MIRROR, ID_DQ
	BCF 	STATUS, C	; its a zero
	BTFSC	PORTB_MIRROR, ID_DQ
	BSF 	STATUS, C	; its a one

        RRF	I_BYTE, F

	MOVLW 	.6		; now delay 60 usecs
        CALL	DELAY_10USEC
        DECFSZ	INDEX, F
        GOTO	_1W_IN_BYTE_1
        
        RETURN

;;;;;

_1W_OUT_BYTE:			; sends O_BYTE to 2401
	MOVLW	.8
        MOVWF	INDEX
_1W_OUT_BYTE_1:
	RRF	O_BYTE, F
        BTFSS	STATUS, C
	GOTO	_1W_OUT_0
	GOTO	_1W_OUT_1	
_1W_OUT_BYTE_2:
	DECFSZ	INDEX, F
        GOTO	_1W_OUT_BYTE_1
        RETURN

_1W_OUT_0:
	CALL	_1W_PIN_LO	; bring DATA_PIN low
	MOVLW	.6		; for 60 usecs
	CALL 	DELAY_10USEC
        CALL	_1W_PIN_HI
        GOTO	_1W_OUT_BYTE_2

_1W_OUT_1:
	CALL	_1W_PIN_LO	; momentary low
        CALL	_1W_PIN_HI
        MOVLW 	.6		; 60 usec delay
	CALL 	DELAY_10USEC
        GOTO	_1W_OUT_BYTE_2

;;;;;;

_1W_PIN_HI:
	BSF	STATUS, RP0
        BSF	PORTB, ID_DQ	; high impedance state
        BCF	STATUS, RP0
        
        RETURN

_1W_PIN_LO:
	BCF	PORTB,  ID_DQ
	BSF	STATUS, RP0
        BCF	PORTB, ID_DQ	; output zero
        BCF	STATUS, RP0
        
        RETURN

;;;;;

DELAY_10USEC:	; provides a delay equal to W * 10 usecs
	MOVWF LOOP_10US
DELAY_10USEC_1:
	CLRWDT
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	DECFSZ LOOP_10US, F
	GOTO DELAY_10USEC_1
	RETURN

;;;;;

#include <lcd_f84.asm>
	END