PDA

View Full Version : EEPROM automatic identification routine



aberco
- 21st September 2010, 20:10
Here is my final version of the EEPROM automatic identification routine. The problem: I2C EEPROM don't have embedded ID code and it is not possible to detect which type of EEPROM is connected to a PIC. Since different size EEPROMs require different variables to be used, the code can only accommodates for a single type of EEPROM size. The topic was previously discussed here: Auto-Dectect EEProm Size (http://www.picbasic.co.uk/forum/showthread.php?t=1908). However I found out that melanie's routine does not work as expected. I got a hand on smaller EEPROMs and especially a 24C01 and found out that small EEPROMs wrap the memory space in a strange way, and the last byte of a non-existing byte reads $01 regardless of the value programmed in what would be it's mirror in existing memory space. This may be due to the change in address space, because wrapping does work as expected on 24C16 through 24C512 (should also work with 24C08 but not tested).

Let me do a modest contribution by wrapping it all into a single routine that identify everything from 24LC00 to 24LC512. This is provided that pins A0, A1, and A2 of the I2C memory = 0 (grounded). A later evolution would be to add address detection as well.

http://aberco.free.fr/imagesdivers/eepromid.png
<<< DOWNLOAD THE FILE HERE: EEPROM_detect.pbp (http://aberco.free.fr/EEPROM_detect.pbp) >>>

SOURCE CODE:


'************************************************* **************************
'* Name : EEPROM_detect.pbp *
'* Author : Antoine Bercovici *
'* Date : 10/21/2010 iEMMMt *
'* Version : 1.0 ......UMMMMMMMMMM. *
'* .,:i,:.. . .;AMMMMMMS *
'* :i:.. .WMMMM@ *
'* .i;. . YMMMMMMMWv YMMMMMi *
'* i:;. ..... @M#UU0MMMMMU ... 0MMMMMZ *
'* :EMMM, ......... oMMM0 .,.,.. oMMMMMMM *
'* i@MMMMMM ........... . MMMM ii;i;:, MMMMMMMM *
'* #MMMMMMMMS ..........,.,. .iBMMMM:.:iiiii,.7MMMMMMMM# *
'* MMMMMMMMMA .......,,iii,iMMMMMMM0 .:ii;iiii.oMMMMM@SM# *
'* .MMMMMMMMMM ...,.i:;ii:.7MMMAv. ,:ii;i;ii,,MMMMM2 vM. *
'* CM6AMMMMMMMU .,,ii;ii:: .; .,,ii;i;;;i;:i,MM#i ,M#@$ *
'* #M: 0MMMMMM@. ..iiiiii::MMMMM.ii;;;;;i;ii,iviQB MM0@ *
'* WM vMMMMMM0. ..,iii,,MMMMM::;i;i;i;i;vb@@#@I XQ@Mi *
'* :MMMMMMMS. ..,. :ci.,i::,,.:v7icM@bb@# MM1 *
'* @MMMMMMMM097;,..:i;ii;Yn$@n7;.MM#W0. BM$ *
'* 0MMMMMMMMMzzMM7XvQMMMMMM.i,. .#MY tMM *
'* CMMMMM@C2WMM .. MM$W@o nM# @E *
'* .6i WMBBS ,o$@v .MM. *
'* ,@U#0 bMb @M, *
'* M@S iM@ . *
'* BMn MM. *
'* 7M$ ib *
'* .MM *
'* C6 *
'* *
'* USAGE 1. Place INCLUDE EEPROM_detect.pbp within your program and *
'* modify the user defined variable below to suit your program *
'* 2. Call first ReadMemoryIDTag routine to identify the EEPROM by *
'* its ID tag. If no ID tag is present the program will perform *
'* data destructive identification on the EEPROM followed by a *
'* complete erase. Result of identification is given by *
'* variables MemType, MemSize and PageSize *
'* 3. Call MemoryErase when you need to perform full erase *
'* 4. Call MemoryRead when you need to read data at MemAddressLong *
'* address. Data is retrieved in DataValue *
'* 5. Call MemoryRead to write DataValue at MemAddressLong *
'************************************************* **************************

'************************************************* ******
'Variable declaration for controlling the EEPROM
'************************************************* ******
MemAddressLong VAR WORD '16 bit address variable for memory from 24C32 to 24C512
MemAddress VAR BYTE '8 bit address variable for memory up to 24C16
Control VAR BYTE 'Control byte for EEPROM test
MemType VAR BYTE 'Type of memory after size control: 11=24C00, 10=24C01, 9=24C02, 8=24C04, 7=24C08, 6=24C16, 5=24C32, 4=24C64, 3=24C128, 2=24C256, 1=24C512
PageSize VAR BYTE 'Size of memory pages in bytes
PageSizeBis VAR BYTE 'For internal use
MemSize VAR WORD 'Size of EEPROM in bytes
Blank VAR BYTE [16] 'Define EEPROM blanking array
WriteDelay VAR WORD 'Delay after writing to EEPROM
TagAddress VAR BYTE 'EEPROM ID tag
DataValue VAR BYTE 'Data to be written in EEPROM
InternalCounter VAR BYTE 'For internal use

'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%
'MODIFY THESE VARIABLES TO SUIT YOUR APPLICATION
'%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%
SCLpin VAR PORTB.6 'SCL Pin
SDApin VAR PORTB.4 'SDA Pin

Writedelay = 5 'Use a 5ms delay between write operations, Increase to 10 if needed by your EEPROM
TagAddress = 12 'EEPROM address where you want to record your ID tag

'************************************************* ******
'EEPROM Size detection for 24C16 and smaller (8bit Address)
'************************************************* ******
MemorySizeCheck:

FOR InternalCounter = 6 to 11
MemAddress = 255
Control = %10100000
If InternalCounter = 6 then Control = %10101110
If InternalCounter = 7 then Control = %10100110
If InternalCounter = 8 then Control = %10100010
IF InternalCounter = 10 THEN MemAddress = 127
IF InternalCounter = 11 THEN MemAddress = 15
I2CWRITE SDApin, SCLpin, Control, MemAddress, [InternalCounter]
PAUSE WriteDelay
NEXT InternalCounter

I2CRead SDApin, SCLpin, %10101110, 255, [MemType]
IF MemType = 6 THEN GOTO DoneChecking
I2CRead SDApin, SCLpin, %10100110, 255, [MemType]
IF MemType = 7 THEN GOTO DoneChecking
I2CRead SDApin, SCLpin, %10100010, 255, [MemType]
IF MemType = 8 THEN GOTO DoneChecking
I2CRead SDApin, SCLpin, %10100000, 255, [MemType]
IF MemType = 9 THEN GOTO DoneChecking
I2CRead SDApin, SCLpin, %10100000, 127, [MemType]
IF MemType = 10 THEN GOTO DoneChecking
I2CRead SDApin, SCLpin, %10100000, 15, [MemType]
IF MemType = 11 THEN GOTO DoneChecking

IF MemType < 6 OR MemType > 11 THEN
GOSUB BigMemorySizeCheck
ENDIF

DoneChecking:

SELECT CASE MemType
CASE 11
MemSize = 15
CASE 10
MemSize = 127
CASE 9
MemSize = 255
CASE 8
MemSize = 511
CASE 7
MemSize = 1023
CASE 6
MemSize = 2047
CASE 5
MemSize = 4095
CASE 4
MemSize = 8191
CASE 3
MemSize = 16383
CASE 2
MemSize = 32767
CASE 1
MemSize = 65535
CASE ELSE
MemSize = 0
END SELECT

SELECT CASE MemType
CASE 10, 9
PageSize = 8
CASE 8, 7, 6
PageSize = 16
CASE 5, 4
PageSize = 32
CASE 3, 2
PageSize = 64
CASE 1
PageSize = 128
CASE ELSE
PageSize = 0
END SELECT

RETURN

'************************************************* ******
'EEPROM Size detection for 24C32 to 24C512 (16bit Address)
'************************************************* ******
BigMemorySizeCheck:

FOR InternalCounter = 1 TO 5
MemAddressLong = 65535
Control = %10100000
IF InternalCounter = 2 THEN MemAddressLong = 32767
IF InternalCounter = 3 THEN MemAddressLong = 16383
IF InternalCounter = 4 THEN MemAddressLong = 8191
IF InternalCounter = 5 THEN MemAddressLong = 4095
I2CWRITE SDApin, SCLpin, Control, MemAddressLong, [InternalCounter]
PAUSE WriteDelay
NEXT InternalCounter

MemAddressLong = 65535

I2CRead SDApin, SCLpin, Control, MemAddressLong, [MemType]

RETURN


'************************************************* ******
'Read EEPROM
'************************************************* ******
MemoryRead:

Control = 160
SELECT CASE MemType
CASE 11, 10, 9, 8, 7, 6
MemAddress = MemAddressLong.byte0
IF MemAddressLong.8 = 1 THEN Control = Control + 2
IF MemAddressLong.9 = 1 THEN Control = Control + 4
IF MemAddressLong.10 = 1 THEN Control = Control + 8
I2CREAD SDApin, SCLpin, Control, MemAddress, [DataValue]
CASE 5, 4, 3, 2, 1
I2CREAD SDApin, SCLpin, Control, MemAddressLong, [DataValue]
END SELECT

RETURN

'************************************************* ******
'Write EEPROM
'************************************************* ******
MemoryWrite:

Control = 160
SELECT CASE MemType
CASE 11, 10, 9, 8, 7, 6
IF MemAddressLong.8 = 1 THEN Control = Control + 2
IF MemAddressLong.9 = 1 THEN Control = Control + 4
IF MemAddressLong.10 = 1 THEN Control = Control + 8
MemAddress = MemAddressLong.byte0
I2CWRITE SDApin, SCLpin, Control, MemAddress, [DataValue]
CASE 5, 4, 3, 2, 1
I2CWRITE SDApin, SCLpin, Control, MemAddressLong, [DataValue]
END SELECT

PAUSE WriteDelay

RETURN

'************************************************* ******
'Erase EEPROM
'************************************************* ******
MemoryErase:

GOSUB MemorySizeCheck

For InternalCounter = 0 to 15 'Fill Blank array with blank data for EEPROM
Blank[InternalCounter] = $FF
Next InternalCounter

SELECT CASE MemType
CASE 11
Control = 160
For MemAddress = 0 TO MemSize
I2CWRITE SDApin, SCLpin, Control, MemAddress, [$FF]
Pause WriteDelay
NEXT MemAddress
CASE 10, 9, 8, 7, 6
PageSizeBis = PageSize / 2
For Control = 160 TO 174 STEP 2
FOR MemAddress = 0 to MemSize Step PageSize
I2CWRITE SDApin, SCLpin, Control, MemAddress, [STR Blank\PageSizeBis, STR Blank\PageSizeBis]
Pause WriteDelay
NEXT MemAddress
IF MemType = 1 OR MemType = 2 THEN GOTO WriteMemoryIDTag
IF MemType = 3 AND Control = 162 THEN GOTO WriteMemoryIDTag
IF MemType = 4 AND Control = 166 THEN GOTO WriteMemoryIDTag
NEXT Control
CASE 5, 4, 3, 2, 1
PageSizeBis = PageSize / 8
FOR MemAddressLong = 0 to MemSize Step PageSize
I2CWRITE SDApin, SCLpin, 160, MemAddressLong, [STR Blank\PageSizeBis, STR Blank\PageSizeBis,_
STR Blank\PageSizeBis, STR Blank\PageSizeBis,_
STR Blank\PageSizeBis, STR Blank\PageSizeBis,_
STR Blank\PageSizeBis, STR Blank\PageSizeBis]
Pause WriteDelay
NEXT MemAddressLong
END SELECT

WriteMemoryIDTag:
MemAddressLong = TagAddress
DataValue = MemType
GOSUB MemoryWrite

RETURN

'************************************************* ******
'Retrieve preprogrammed EEPROM ID tag at address TagAddress
'************************************************* ******
ReadMemoryIDTag:
MemAddress = TagAddress

I2CREAD SDApin, SCLpin, %10100000, MemAddress, [MemType]
IF MemType = 0 OR MemType > 12 THEN
MemAddressLong = TagAddress
I2CREAD SDApin, SCLpin, %10100000, MemAddressLong, [MemType]
IF MemType = 0 OR MemType > 12 THEN
GOSUB MemoryErase
ENDIF
ENDIF
GOSUB DoneChecking

RETURN


USAGE:

Note that the EEPROM detection routine does erase part of the data, and should not be used on a memory that contain code. To perform a "data safe" identification, a location in EEPROM is chosen for subsequent ID.


Place EEPROM_detect.pbp within your project file and call INCLUDE EEPROM_detect.pbp within your program. Some declarations needs to be modified within EEPROM_detect.pbp: change SDApin and SCLpin to match your I/O ports, and declare an EEPROM address where you'd like the ID tag to be stored (provided it exists in the smallest memory, the 24C00).


Call first ReadMemoryIDTag routine in your program initialization to identify the EEPROM by its ID tag. If no ID tag is present the program will perform data destructive identification on the EEPROM followed by a complete erase. Result of identification is given by the following variables:

MemType (11=24C00, 10=24C01, 9=24C02, 8=24C04, 7=24C08, 6=24C16, 5=24C32, 4=24C64, 3=24C128, 2=24C256, 1=24C512)

MemSize (15, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535, 0=detection failed) in bits

PageSize (0, 8, 16, 32, 64, 128) in bytes per pages


Call MemoryErase routine when you need to perform full memory erase within your program. A 24C512 takes about 5 seconds to be erased with page-write mode.


Call MemoryRead routine when you need to read data. Use MemAddressLong variable (WORD) as your address pointer, data will be dumped in DataValue.


Call MemoryWrite routine when you need to write data. Use MemAddressLong variable (WORD) as your address pointer, place data in DataValue.


SAMPLE CODE:

Below is a little example that identify an EEPROM and display results on LCD (add all the defines for your LCD).



'************************************************* ******
'Display EEPROM size on LCD
'************************************************* ******
INCLUDE EEPROM_detect.pbp

GOSUB ReadMemoryIDTag

LCDOUT $FE,1, "Memory type:"
Select CASE MemType
CASE 11
LCDOUT $FE,$C0, "24LC00, 16o"
CASE 10
LCDOUT $FE,$C0, "24LC01, 128o"
CASE 9
LCDOUT $FE,$C0, "24LC02, 256o"
CASE 8
LCDOUT $FE,$C0, "24LC04, 512o"
CASE 7
LCDOUT $FE,$C0, "24LC08, 1ko"
CASE 6
LCDOUT $FE,$C0, "24LC16, 2ko"
CASE 5
LCDOUT $FE,$C0, "24LC32, 4ko"
CASE 4
LCDOUT $FE,$C0, "24LC64, 8ko"
CASE 3
LCDOUT $FE,$C0, "24LC128, 16ko"
CASE 2
LCDOUT $FE,$C0, "24LC256, 32ko"
CASE 1
LCDOUT $FE,$C0, "24LC512, 64ko"
CASE ELSE
LCDOUT $FE,$C0, "Not recognized"
END SELECT

aberco
- 9th October 2010, 01:04
Please go to the WIKI page for up to date code ;)