PDA

View Full Version : Puzzling issue with I2CWRITE to 24LC512



aberco
- 22nd August 2008, 13:38
Hi everyone,
I am getting a srtange issue when using I2CWRITE on my project. I've searched quite a bit on the net and in this forum, but couldn't find any lead on the resolution of my problem. So there it is!

The project:
A "robot" controller that record actions controlled by buttons/knobs and that can playback the sequence later on

The Issue:
There's 3 main subroutines, one for erasing the EEPROM (writing $FF using page mode), one for writing the state of button and knobs to EEPROM (recorder mode), and one for reading the data in the EEPROM (play mode).

However, erasing the eeprom or writing data in it yields only $00 when read back...

Troubleshooting:
- I know that the read routine does work. I have written random data in the eeprom using an I2C programmer and could read it back perfectly
- Writing in eeprom does indeed write $00 in memory, as verified by my I2C programmer. However, I am displaying the data being written on an LCD display just before the "I2CWRITE" instruction, and it shouldn't be $00
- Checking with an oscilloscope, the SDA line actually contains the data I want to write.

Hardware:
- Based on a PIC16F877A running at 20Mhz.
- EEPROM used is a 24LC512, with SCL and SDA respectively on RC3 and RC4 (there's no analog function on these).
- EEPROM is wired correctly, with A0, A1, A2 and WP grounded. SDA and SDC are pulled up with 2,2k resistors, and wire lenght to the PIC is 1 cm.

The code:
Since code is quite long I will post only the bits that gives problem. I have used variables and not constants in each of my I2CREAD/WRITE as required.

-----------------------------------------------

DEFINE OSC 20
DEFINE LOADER_USED 1

'Définition des broches utilisés pour l'écran LCD
'Set LCD Data port
DEFINE LCD_DREG PORTB
'Set starting data bit (0 or 4) if 4-bit Bus
Define LCD_DBIT 0
'Set LCD Register select port
Define LCD_RSREG PORTB
'Set LCD Register select bit
Define LCD_RSBIT 5
'Set LCD Enable port
DEFINE LCD_EREG PORTB
'Set LCD Enable bit
DEFINE LCD_EBIT 4
'Set LCD Bus size
DEFINE LCD_BITS 4
'Set number of lines on LCD
DEFINE LCD_LINES 2
'Set command delay time in us
DEFINE LCD_COMMANDUS 2000
'Set data delay tome in us
DEFINE LCD_DATAUS 50

'Set ADC pins to digital operation
ADCON1 = %10000100 'AN0, AN1 and AN3 are analog input
CMCON = %00000111 'disabling the comparator module

'Define pin function
TRISA = %00001011 'RA2, RA4 et RA5 sont des sorties numériques
TRISB = %00000000 'Tout le PORTB est en sortie numérique
TRISC = %00100111 'RC7 et RC6 sont des sorties, RC5, RC2, RC1 et RC0 sont des entrées
TRISD = %11111111 'Tout le PORTD est en entrée numérique
TRISE = %00000000 'Tout le PORTE est en sortie numérique

' Define ADCIN parameters
Define ADC_BITS 8 ' Set number of bits in result
Define ADC_CLOCK 3 ' Set clock source (3=rc)
Define ADC_SAMPLEUS 50 ' Set sampling time in uS

'Définition du nom des broches d'I/O
IND0 VAR PORTD.0
IND1 VAR PORTD.1
IND2 VAR PORTD.2
IND3 VAR PORTD.3
IND4 VAR PORTD.4
IND5 VAR PORTD.5
IND6 VAR PORTD.6
IND7 VAR PORTD.7
INLATCH1 VAR PORTC.5
INLATCH2 VAR PORTC.1
INLATCH3 VAR PORTC.2
INLE VAR PORTC.0

OUTD0 VAR PORTA.4
OUTD1 VAR PORTA.5
OUTD2 VAR PORTE.0
OUTD3 VAR PORTE.1
OUTD4 VAR PORTE.2
OUTLE1 VAR PORTC.6
OUTLE2 VAR PORTA.2

SERVO1 VAR PORTB.7
SERVO2 VAR PORTB.6
SERVO3 VAR PORTB.5

SCL VAR PORTC.3
SDA VAR PORTC.4

'Autres variables
I2CADDRESS VAR WORD
SERVO1_VALUE VAR BYTE
SERVO2_VALUE VAR BYTE
SERVO3_VALUE VAR BYTE
SERVO1_VALUE_INV VAR BYTE
SERVO2_VALUE_INV VAR BYTE
SERVO3_VALUE_INV VAR BYTE
i VAR BYTE 'compteur de boucle
j VAR BYTE 'compteur de boucle
INLATCH1_VALUE VAR BYTE
INLATCH2_VALUE VAR BYTE
INLATCH3_VALUE VAR BYTE
OUTLATCH1_VALUE VAR BYTE
OUTLATCH2_VALUE VAR BYTE

'Alias des variables bit par bit
REMOTE VAR INLATCH1_VALUE.bit7
TEST VAR INLATCH1_VALUE.BIT6
RECORD VAR INLATCH1_VALUE.BIT5
START VAR INLATCH1_VALUE.BIT4
STOP_RAZ VAR INLATCH1_VALUE.BIT3
ERASE VAR INLATCH1_VALUE.BIT2
H1GIN VAR INLATCH1_VALUE.BIT1
H1LIN VAR INLATCH1_VALUE.BIT0

REL1IN VAR INLATCH1_VALUE.BIT7
REL2IN VAR INLATCH1_VALUE.BIT6
FET1IN VAR INLATCH1_VALUE.BIT5
FET2IN VAR INLATCH1_VALUE.BIT4
FET3IN VAR INLATCH1_VALUE.BIT3
FET4IN VAR INLATCH1_VALUE.BIT2
H2GIN VAR INLATCH1_VALUE.BIT1
H2LIN VAR INLATCH1_VALUE.BIT0

FC1IN VAR INLATCH1_VALUE.BIT7
FC2IN VAR INLATCH1_VALUE.BIT6
FC3IN VAR INLATCH1_VALUE.BIT5
FC4IN VAR INLATCH1_VALUE.Bit4

BLANK var Byte
BLANK = $FF
I2CDEVICE VAR BYTE
I2CDEVICE = $A0

'Subroutine d'effacement
erase_eeprom:

LCDOUT $FE,1,"Effaceme"
LCDOUT $FE,$C0, "nt..."

FOR I2CADDRESS = 0 to 65535 Step 128
I2CWRITE SDA,SCL,I2CDEVICE,I2CADDRESS,[BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,_
BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK,BLANK],eeprom_error 'Ecriture de FF dans la page de l'EEPROM
PAUSE 5
NEXT I2CADDRESS

LCDOUT $FE,1,"Memoire "
LCDOUT $FE,$C0, "effacee"
PAUSE 2000

RETURN

'Subroutine pour signaler une erreur de lecture ou d'écriture en mémoire
eeprom_error:

LCDOUT $FE,1,"Erreur m"
LCDOUT $FE,$C0, "emoire"
PAUSE 2000

RETURN

END

--------------------------------------------------
Now, notice that this code does actually work as it is written, but when I use this exact same subroutine (erase_eeprom) within my main code, instead of writing $FF, it does write $00!!!

Same think with my routine that write data.

If someone could get a lead on what's going on, this is driving me nuts!

sayzer
- 22nd August 2008, 15:35
You should post the code in which you read EEPROM back and display on LCD.

Also, write cycle time for 24LC512 is stated to be 5ms max. in datasheet but I would make it 10ms.

Also, if your circuit powered by less then 5V then you should slow down the lines to EEPROM.

------------------------

aberco
- 22nd August 2008, 16:12
Thanks for your reply!

"Also, write cycle time for 24LC512 is stated to be 5ms max. in datasheet but I would make it 10ms."

Yep I know, I actually used 10ms at first, even changing it to 500ms for test purposes. Doesn't make any difference: when I use the subroutine alone it always work, but not in my main program.

My circuit is powered by regulated 5V also...

I have attached the complete code where the I2CWRITE routines are not working. I'm still working on it so it may not be the cleanest and needs a bit of tweaking, but everything else work.

The part of the code where I read the eeprom is the subroutine "read_mode". This is also where I added lines to output the variables to LCD for debugging (they are now removed, but it worked as I could read correct values that I programmed manually with an I2C memory programmer).

Still investigating on my side...

aberco
- 22nd August 2008, 16:28
Haha!!! got it!!

Erratic operation lead me to think it was a software problem, but good think you takled about VCC!!

I actually put my ajustable regulated powersupply and checked again... VCC was 7.5V!!! but everything else was working fine!

I will have to check what's going on with my 7805, but in any case, when VCC = 5V, the EEPROM works, and i can retrieve the correct values :-)

Well, as always it is super simple when you find it out! (took me 3 days though!!!).

aberco
- 22nd August 2008, 17:47
Project is done and working perfectly!

It certainly have helped getting your opinion.
Many thanks!