PDA

View Full Version : I2C and 24LC65



afbecker
- 16th July 2009, 19:24
I have been unsuccessfully working with a MicroChip 24LC65 trying to get the example in the PBP Manual to work with a 16F628A. I have built the circuit exactly as shown in the book with 4.7K pullups on the data and clock lines. The example being that for the I2C command.

I am using a 4Mhz clock oscillator and the circuit is supplied with 5vdc. I have set the MClr pin as in the diagram and pulled it up also. I have grounded the various EPROM pins as the diagram shows.

I am using the hardware serial capability of the 16F628A to send program output to "Hyperterm" running on my notebook.

I have created the example coded as included below. The result returned from each of the three read statements is always "255." I don't think it is merely a coincidence that all the bits are 1's. I am not sure if this is a hardware problem, software problem or combination of both. I have read the 24LC65 data sheet and tried to understand what I can. It seems like there may be some hardware characteristics of this part that are not entirely compatible with the instructions given in the PBP manual, but I can't quite put my finger on that. Please look through the code below and see if you can spot an error. Perhaps I just destroyed the EPROM accidentally.

The code follows:

-----------------
' EP_Test.bas
' 16F628A- CPU Hardware Layout
' EPROM Hardware: MicroChip 24LC65
' ---------------------------
' RA0- Eprom data line (SDA), open drain, 4.7K pullup
' RA1- Eprom clock line (SCL), open drain, 4.7K pullup
' RA2- n.c.
' RA3- n.c.
' RA4- n.c.
' RA5- MasterClear is enabled just to match manual and jumpered high.
'
' RB0- n.c.
' RB1- n.c.
' RB2- HSER- Out to HyperTerm Display
' RB3- n.c.
' RB4- n.c.
' RB5- n.c.
' RB6- n.c.
' RB7- n.c.
'
@ __config _HS_OSC & _WDT_ON & _MCLRE_ON & _LVP_OFF & _CP_OFF & _PWRTE_OFF & _BOREN_OFF
'
CMCON=7
'
Define OSC 4
Define HSER_BAUD 2400
Define HSER_RCSTA 90h
Define HSER_TXSTA 20h
'
B0 var byte
B1 var byte
'
' Set the tri-state registers using bits
TRISA=%00000000
TRISB=%00000000
' Initialize the ports using bits
PortA=%00000000
PortB=%00000000
'
Pause 1500
' start the eprom stuff
'
B0 = 0
I2CWRITE PortA.0,PortA.1,$A0,B0,[B0]
Pause 700
B0 = 1
I2CWRITE PortA.0,PortA.1,$A0,B0,[B0]
Pause 700
B0 = 2
I2CWRITE PortA.0,PortA.1,$A0,B0,[B0]
Pause 1500
'
B0 = 0
I2CREAD PortA.0,PortA.1,$A0,B0,[B1]
Hserout [#B1,13,10]
Pause 700
B0 = 1
I2CREAD PortA.0,PortA.1,$A0,B0,[B1]
Hserout [#B1,13,10]
Pause 700
B0 = 2
I2CREAD PortA.0,PortA.1,$A0,B0,[B1]
Hserout [#B1,13,10]
'
End

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

aratti
- 16th July 2009, 20:22
Add the following two DEFINEs to your code



DEFINE I2C_SLOW 1
DEFINE I2C_HOLD 1


Declare and use the following constants as reading and writing control.



SDevW con %10100000 ' I2C eeprom write control
SDevR con %10100001 ' I2C eeprom read control


You should have all the address inputs grounded.

Al.

Archangel
- 16th July 2009, 20:28
Hello afbecker,
Here is an example which might be helpful:





' I2CREAD and I2WRITE Commands with External EEPROM on 12-bit core
'
' Write to the first 36 locations of External I2C EEPROM
' Read from eeprom and output sequentaly then as strings
' Tested on 12F675 using 24LC01B EEPROM
@ __config _INTRC_OSC_NOCLKOUT & _PWRTE_ON & _WDT_ON & _MCLRE_ON & _CP_OFF & _BODEN_OFF
DEFINE OSC 4

DEFINE DEBUG_REG GPIO
DEFINE DEBUG_BIT 2
DEFINE DEBUGIN_BIT 5
DEFINE DEBUG_BAUD 2400
DEFINE DEBUG_MODE 0
DEFINE SHIFT_PAUSEUS 1000

EECON1 = 7 'Probably not needed here, enables internal eeprom
CMCON = 7 'Disable comparators
ADCON0.0 = 0 'Disable A/D converters
ANSEL = 0 'Disables Analog Select
DPIN var GPIO.0 'Assign Data pin
CPIN var GPIO.1 'Assign Clock pin
' a nice place to store things
B0 var byte
B1 var byte
B2 var byte
B3 VAR BYTE

GPIO = 0 ' set port latches low
TRISIO = 0 ' set ports as outputs

pause 1000 ' Waste time while serial LCD initiailizes

For B2 = 0 To 35 ' counter for lookup table
lookup b2,["A","B","C","D","E","F","G","H","I","J","K","L","M",_
"N","O","P","Q","R","S","T","U","V","W","X","Y","Z","0","1","2",_
"3","4","5","6","7","8","9"],B0 ' store each char in b0 1 at a time

I2CWRITE DPIN,CPIN,$A0,B2,[ b0] 'write to 24C01 eeprom 1 character
Pause 20
Next B2 'next character write to eeprom
DEBUG 254,1 'clear LCD of any leftover data
loop:
DEBUG 254,1 'clears away the leftovers each loop

For B3 = 0 To 35 ' counter for reading 35 characters
I2CREAD DPIN,CPIN,$A0,b3,[B1] ' read each character 1 at a time
pause 500 ' time to see each character on the LCD


DEBUG 254,2,"CHAR ",B1," " ' display the characters 1 at a time
'
Next B3 ' get next character

I2CREAD DPIN,CPIN,$A0,0,[STR B1\20] ' read a string of 20 characters
DEBUG 254,2,STR B1\20 ' display those 20 characters
I2CREAD DPIN,CPIN,$A0,16,[STR B1\16]' get the last 16 characters
DEBUG 254,$C0,STR B1\16," " ' display those 16 characters
DEBUG 254,$94,"I2C EEPROM DEMO" ' display this program's purpose
DEBUG 254,$D4,"USING ARRAY & STRING"
PAUSE 1500 ' time to read the LCD
'NEXT B3 ' go do it all again
Goto loop
end
POKECODE @$3FF, $4C 'read your PIC before erasing and put the cal. data here

afbecker
- 16th July 2009, 21:29
Gentlemen,

Thanks for the quick reply, I can work on this tonight!

Aratti: For my future reference, can you tell me what the difference is between the control bytes, particularily the read control byte ending in 1? I wondered if that was the key to making my specific part work.

Joe S.: I appreciate the code example. Reading example code is a way I find that I can learn new concepts very easily.

aratti
- 16th July 2009, 22:42
I wondered if that was the key to making my specific part work.

Although in this forum, I have read in several posts that I2CRead set the LSB to 1 automatically, I have never been able to read successfully, from external memory, without setting LSB to 1 myself. Now I do it as a standard in all my codes using I2C commands.

Al.

Bill Legge
- 17th July 2009, 11:43
I think your problem is with the address for READ and WRITE.

The 24LC64 EEPROM needs a WORD size address - even if the actual address is 0.

Change your program to

DEFINE B0 WORD ; Must not be a BYTE size or CONSTANT

B0 = 0
I2CWRITE, DataPin,ClockPin,$A0,B0,[Value]

and so on....

Good luck. I stuffed around with EEPROM for ages and eventualy found that all my errors were due to using BYTES when the chips expected a WORD. The spec sheet for the chip will tell you what it expects. The example in the PBP book is for a smaller EEPROM that only needs a BYTE address.

Regards Bill Legge

afbecker
- 17th July 2009, 14:32
Bill,

You are absolutely correct.

It came to me last night in a flash (pun intended.) I was re-reading the docs. and I realized I had defined the address variable as a byte type and the address of this part is a word type.

After I had changed it everything works superbly!

As a quick reply to Arratti: I am embarassed that I asked the question about the control word difference. At the time I replied I hadn't looked at the EPROM docs. for about two weeks. I forgot the difference in control words was due to the read/write mode.

Rhetorical question: Isn't it amazing how elementary a problem suddenly becomes once you have figured out the solution?