I want to start a serie of brief articles describing the components that I usually used in my electronic designs.The first one is the DS28CM00 I2C serial number. This device is an electronic registration number that gives you an unique 64-bit serial number over I2C or SMBUS interface. This 64-bit serial number is factory lasered, so there aren’t two devices with the same number.
I use this component in a railway application, to identify the PCB’s mounted in the system. The pinout and the typical connection of this device is shown here:
The serial number has the following structure:
– 1 byte that identifies the family code (0x70)
– 6 bytes with the unique serial number
– 1 byte corresponiding the 8 bit CRC of the above bytes.
Also, the device has a contro register, where you can select the type of communication: I2C or SMBus. In the next figure, you can see the address of these registers:
As an I2C device, the DS20CM00 must have a bus address to access it. The address for read is 0xA1, and the address for write is 0xA0. Unfortunately, this address cannot be configurated, so you must be carefully if you use in the bus with other devices, to avoid conflicts on it.
- Software example
Here you can see an example of how to access and communicate with this device. I use an AT89C51RE2 microcontroller from Atmel, and with two pins I do a bit-banging I2C software bus. The code I use is here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
/*************************************************************************/ /* FUNCTION : Lectura_ID (void) */ /* AUTHOR : Jesus Echavarria Navarro */ /* www.jechavarria.com */ /* */ /* DESCRIPTION: Function that reads the serial number from a DS28CM00 */ /* device. This device provides a 48-bit unique serial number, a family */ /* code and a CRC-8 of the read bytes. The structure of the data is the */ /* following one. */ /* */ /* - Byte 0: Family Code: 0x70 */ /* - Byte 1: Serial Number (bits 0 - 7) */ /* - Byte 2: Serial Number (bits 8 - 15) */ /* - Byte 3: Serial Number (bits 16 - 23) */ /* - Byte 4: Serial Number (bits 24 - 31) */ /* - Byte 5: Serial Number (bits 32 - 39) */ /* - Byte 6: Serial Number (bits 40 - 47) */ /* - Byte 7: CRC 8 bits: Family Code + Serial Number */ /* */ /* The result is stored on the global variable */ /* ID_Hardware [8]. */ /* */ /* If the calculated CRC-8 is different from the read one */ /* (error on the read), then the global variable */ /* ID_Hardware [8] resets to 0x00. */ /* */ /* INPUT PARAMETERS: None */ /* */ /* OUTPUT PARAMETERS: None */ /* */ /* RETURN VALUES: None */ /* */ /* GLOBAL VARS READ: None */ /* */ /* GLOBAL VARS MODIFIED: unsigned char ID_Hardware [8] */ /* */ /* REVIEWS: */ /* DATE DESCRIPTION */ /* */ /* 04/02/2013 Function Creation */ /* */ /*************************************************************************/ void Lectura_ID (void) { //------------------------------------------------------------------------ // Local Variables //------------------------------------------------------------------------ unsigned char i; unsigned char num_serie [8]; for (i=0; i<8; i++) num_serie [i] = 0x00; //------------------------------------------------------------------------ // Writes in the DS28CM00 control register to activate I2C mode //------------------------------------------------------------------------ I2C3_Start (); // Start condition I2C3_Write (ID_WR); // Write command I2C3_Write (0x08); // Register 0x08: Control register I2C3_Write (0x00); // Writes 0x00: I2C mode I2C3_Stop (); // End of communication I2C3_Delay (100); // Delay //------------------------------------------------------------------------ // Read 8 bytes from the DS28CM00 : // 1 byte family code + 6 bytes serial number + 1 byte CRC8 //------------------------------------------------------------------------ I2C3_Start (); // Start condition I2C3_Write (ID_WR); // Write command I2C3_Write (0x00); // Pointer at position 0 I2C3_Start (); // Start condition I2C3_Write (ID_RD); // Read command //----- Read 7 bytes from the DS28CM00. Stores in the variable 'num_serie [i]' for (i=0;i<7;i++) { num_serie [i] = I2C3_Read (); I2C3_txACK (); } num_serie [7] = I2C3_Read (); // Reads the eight byte: (CRC) I2C3_txNACK (); // Sends NACK: I2C3_Stop (); // End of read I2C3_Delay (100); // Delay //------------------------------------------------------------------------ // CRC8 from the read data //------------------------------------------------------------------------ CRC8 = 0; for (i=0; i<7; i++) Calculo_CRC8 (num_serie [i]); //------------------------------------------------------------------------ // If calculated CRC8 is equal to the read one, then the serial number // stores in the global variable ID_Hardware [8]. If both CRC are not // equal, then this global variable resets to 0x00. //------------------------------------------------------------------------ if (CRC8 == num_serie [7]) { for (i=0; i<8; i++) { ID_Hardware [i] = num_serie [i]; } } else { for (i=0; i<8; i++) { ID_Hardware [i] = 0x00; } } } |
- Calculating CRC-8
In the datasheet, you can find a reference to an application note (AN27) that describes how to calculate the CRC-8. I use it to make my own routine in C code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
/*************************************************************************/ /* FUNCTION : Calculo_CRC8 */ /* AUTHOR : Jesus Echavarria Navarro */ /* www.jechavarria.com */ /* */ /* DESCRIPTION: Function that calculates the CRC-8 of the data that is */ /* passed by argument. The used polynomial is: x8 + x5 + x4 + 1. */ /* The result is stored in the global variable 'CRC8'. */ /* */ /* INPUT PARAMETERS: unsigned char dato: Data upon which the CRC is */ /* calculated. */ /* */ /* OUTPUT PARAMETERS: None */ /* */ /* RETURN VALUES: None */ /* */ /* GLOBAL VARS READ: None */ /* */ /* GLOBAL VARS MODIFIED: unsigned char CRC8: Variable that stores the */ /* result of the CRC calculation. */ / /* REVIEWS: */ /* DATE DESCRIPTION */ /* */ /* 04/02/2013 Function Creation */ /* */ /*************************************************************************/ void Calculo_CRC8 (unsigned char dato) { //------------------------------------------------------------------------ // Local variables //------------------------------------------------------------------------ unsigned char i; unsigned char fb; //------------------------------------------------------------------------ // CRC8 algorithm //------------------------------------------------------------------------ for (i=0; i<8; i++) { fb = (CRC8 ^ dato) & 0x01; dato >>= 1; CRC8 >>= 1; if (fb) { CRC8 ^=0x8C; } } } |
Finally, two tips to use this function:
– The variable CRC-8 must be a global variable.
– Before call the function for the first time, you must initialize this variable to 0x00.
Hi,
Please help,
I want to run this in my WIndows machine
Where Do I get “I2C3_xxxx()” functions/library available?
Thanks & Regards,
Satya
Hi Satya:
Thanks for read the blog! Note that the functions you mentione are for I2C communications. If you want to use this piece with a PC, you need a converter for the USB port of the PC (or serial RS232) to I2C, in order to connect this device. The functions you show in the code are for a microcontroller where is connected the DS28CM00.
Best regards from Spain!