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