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