PDA

View Full Version : I2C with External Eeprom



ruijc
- 19th February 2008, 20:34
Hi all,

The reason for this post is that i'm trying to get my 24LC512 eeprom to work with my PIC16F88.

I was successful with this eeprom and a PIC12F675, but for some reason with the 16F88 i cant read nor write anything.

I've search the forum for an answer but nothing worked.

I've read the pic16F88 datasheet over and over and i came up with some doubts.

Please try to answer my questions so i can proceed in finding a solution :)

According to the pic 16F88's datasheet ( I2C )Pin RB1 is for SDA and pin RB4 is for SCL.

1st question:
Is it mandatory that i use these ports to communicate with the eeprom ?
( this may be a silly question but for 12F675 i can use almost any pin for them ).

In the datasheet i have found that we need to clear SSPEN bit and program the 2 I2C ports as inputs.

2nd question:
For that to happen i need to mess with the SSPSTAT and SSPCON ?
If yes, can you please show me how can these be set ( since i dont understand the meaning of their bits :( )

thanks

skimask
- 19th February 2008, 21:11
Hi all,
The reason for this post is that i'm trying to get my 24LC512 eeprom to work with my PIC16F88.
I was successful with this eeprom and a PIC12F675, but for some reason with the 16F88 i cant read nor write anything.
I've search the forum for an answer but nothing worked.
I've read the pic16F88 datasheet over and over and i came up with some doubts.
Please try to answer my questions so i can proceed in finding a solution :)
According to the pic 16F88's datasheet ( I2C )Pin RB1 is for SDA and pin RB4 is for SCL.
1st question:
Is it mandatory that i use these ports to communicate with the eeprom ?
( this may be a silly question but for 12F675 i can use almost any pin for them ).
In the datasheet i have found that we need to clear SSPEN bit and program the 2 I2C ports as inputs.
2nd question:
For that to happen i need to mess with the SSPSTAT and SSPCON ?
If yes, can you please show me how can these be set ( since i dont understand the meaning of their bits :( )
thanks

You seem to have a bit of a problem with a little bit of everything, but then, that's why you're here...
PBP's I2C commands pretty much take care of everything for you, no extra work needed, with most chips.
First off, do you have pull up resistors on SDA/SCL like the manual shows?
Second...where's the code?

tenaja
- 19th February 2008, 21:20
If you are trying to use the hardware i2c, the 16F88 can't do it--it does not have master i2c capability (only SPI). Therefore, the i2c pin selections are irrelevant--you can connect them anywhere you want, and you'll have to define where they are, and use i2c commands.

ruijc
- 19th February 2008, 21:22
Hello skimask and thanks for your help :)

Yes...i have the 4k7 pull ups ( also tryed other resistor values with no success.

here is the code :



*****

SSPCON.5 = 0 ; Disable SSP Module
TXSTA.5 = 0 ; Disable AUSART Tx
RCSTA.7 = 0 ; Disable Serial Port


OSCCON = %01111110 'Internal RC w/ I/Os

INTCON=0

PIE1 = 0
'PIE2 = 0

PIR1 = 0 'off

CMCON= 7
CVRCON= 0 'Vref Off
CCP1CON= 0

T1CON= 0
'T2CON = %00000100

'************************************************* ****************************
'DEFINEs
'************************************************* ****************************

@ DEVICE INTRC_OSC
@ DEVICE MCLR_OFF
@ DEVICE PROTECT_OFF

DEFINE osc 4

@ DEVICE CPD_OFF
@ DEVICE LVP_OFF
@ DEVICE BOD_OFF
@ DEVICE PWRT_OFF
@ DEVICE WDT_OFF

'************************************************* ****************************
'ADC

DEFINE ADC_BITS 10 ' Set number of bits in result ( 8 or 10 bits )
DEFINE ADC_CLOCK 3 ' Set clock source (3=rc)
DEFINE ADC_SAMPLEUS 50 ' Set sampling time in uS


'************************************************* ****************************
'ADC parameters

ADCON1 =%10000000 'right justify
ANSEL =%00000101
ADCON0 =%11000001

'************************************************* ****************************

INCLUDE "modedefs.bas"

'settings for serial comm

DEFINE debug_reg PORTA
DEFINE debug_bit 1
DEFINE debug_baud 9600
DEFINE debug_mode 1

'************************************************* ****************************
'I/O's

PORTA=0
PORTB=0

TRISA=%00100101
TRISB=%00000011

'************************************************* ****************************
'PINS

temp var PORTA.0
out var PORTA.1
volt var PORTA.2
a3 var PORTA.3
A4 var PORTA.4
but1 var PORTA.5
led2 var PORTA.6
led1 var PORTA.7

but2 var PORTB.0
but3 var PORTB.1
SCL var PORTB.2
SDA var PORTB.3

green var PORTB.4
red var PORTB.5
led4 var PORTB.6
led3 var PORTB.7

************************************************** ***************************
' variables

va var word
va2 var word
tempe var word
volte var word
mem var byte
p1a var word
p1b var word
p2a var word
p2b var word
p3a var word
p3b var word
p4a var word
p4b var word
state var byte
st var word
ed var word
ADDR var word
m1 var byte
m2 var byte
m3 var byte
m4 var byte
slot var bit
w var byte
CTW VAR BYTE
km var byte
ra var word
set1 VAR BYTE
set2 VAR BYTE
rm var byte
x var byte

CLEAR

'************************************************* ****************************

mem=1
state=1
p1a=$10
p1b=$1070
p2a=$1080
p2b=$2140
p3a=$2160
p3b=$3220
p4a=$3230
p4b=$4290

'************************************************* ****************************
start:

high out
debug $0D, $0A
PAUSE 50

CTW=$A0

'************************************************* ****************************

debug "start menu",13,10

startmenu:

I2CREAD SDA,SCL,CTW,1,[m1]
I2CREAD SDA,SCL,CTW,2,[m2]
I2CREAD SDA,SCL,CTW,3,[m3]
I2CREAD SDA,SCL,CTW,4,[m4]


if (mem=1) and (m1=0) then
led1=1
led2=0
led3=0
led4=0
slot=0
endif


if (mem=1) and (m1<>0) then
pause 300
toggle led1
led2=0
led3=0
led4=0
slot=1
endif


if (mem=2) and (m2=0) then
led1=0
led2=1
led3=0
led4=0
slot=0
endif


if (mem=2) and (m2<>0) then
led1=0
pause 300
toggle led2
led3=0
led4=0
slot=1
endif


if (mem=3) and (m3=0) then
led1=0
led2=0
led3=1
led4=0
slot=0
endif


if (mem=3) and (m3<>0) then
led1=0
pause 300
led2=0
toggle led3
led4=0
slot=1
endif


if (mem=4) and (m4=0) then
led1=0
led2=0
led3=0
led4=1
slot=0
endif


if (mem=4) and (m4<>0) then
led1=0
pause 300
led2=0
led3=0
toggle led4
slot=1
endif


if state=1 then
green=0
red=1
endif

if state=2 then
green=1
red=0
endif
if state=3 then
green=1
red=1
endif



if (but1=1) and (state=1) then
gosub readmenu
endif

if (but1=1) and (state=2) then
gosub recordmenu
endif

if (but1=1) and (state=3) then
gosub erasemenu
endif


if but3=1 then
gosub memorymenu
endif


if but2=1 then
gosub statemenu
endif


goto startmenu


'*****************
recordmenu:

debug "Record Menu",13,10

if slot=1 then
goto warningmenu
endif

if mem=1 then
st=p1a
ed=p1b
endif
if mem=2 then
st=p2a
ed=p2b
endif
if mem=3 then
st=p3a
ed=p3b
endif
if mem=4 then
st=p4a
ed=p4b
endif

'******************

recordmem:

debug "2s pause before start recording",13,10
PAUSE 2000


FOR ADDR= st TO ed

for w = 0 to 15
ADCIN temp, va
va2=va + (temp>>4)
NEXT

va = (va2 */ 5000 ) >> 2
va=va/10

toggle red
pause 824
debug " Saved value: ", dec va2," - ", dec va," In position ", dec ADDR, 13,10
debug " VA2 = ", dec va2,13,10
I2CWRITE SDA,SCL,CTW,ADDR,[VA.highbyte]
pause 10
ADDR=ADDR+1
I2CWRITE SDA,SCL,CTW,ADDR,[VA.lowbyte]
pause 10
ADDR=ADDR+1
I2CWRITE SDA,SCL,CTW,mem,[addr]
if but1=1 then 'stop recording
pause 600
goto startmenu
endif
toggle led1
toggle led4
NEXT
red=1
return

'******************

erasemenu:

'*****************

eraseblock:

debug "erasing block",dec mem,13,10
red=0
I2Cread SDA,SCL,CTW,mem,[x]
debug "before in position ",dec mem," - ",dec x,13,10
I2CWRITE SDA,SCL,CTW,mem,[0]
pause 500
red=1
return

'******************

memorymenu:
if mem < 4 then
mem=mem+1
else
mem=1
endif
debug DEC mem,13,10
pause 300
return

'******************

statemenu:

if state < 3 then
state=state+1
else
state=1
endif
debug "state change - ", DEC state,13,10
pause 300
return

'******************

end

skimask
- 19th February 2008, 21:51
WP pin pulled high? Low? Floating?
Address pins pulled high? Low? Floating?

ruijc
- 19th February 2008, 22:30
WP is connected to ground. Same as all address pins of the eeprom.

skimask
- 20th February 2008, 01:22
WP is connected to ground. Same as all address pins of the eeprom.

Then I'd suggest backing up a bit...
Get uncomplicated...
Write some code to just write a few values to the eeprom and read them back to verify what was written...THEN write the code you actually want to use...'cause I see a few flaws in your logic in the code written a few posts back.

ruijc
- 20th February 2008, 10:40
Thanks skimask,

Good idea. Will do that tonight and post the results ;)

.

ruijc
- 20th February 2008, 21:56
Just finished assembling a small code and still cannot work with the eeprom

this is the code i used :



'************************************************* ***************

'************************************************* ***************


SSPCON.5 = 0 ; Disable SSP Module
TXSTA.5 = 0 ; Disable AUSART Tx
RCSTA.7 = 0 ; Disable Serial Port


OSCCON = %01111110 'Internal RC w/ I/Os

INTCON=0

PIE1 = 0
'PIE2 = 0

PIR1 = 0 'off

CMCON= 7 'COMPARATOR OFF
CVRCON= 0 'Vref Off
CCP1CON= 0

T1CON= 0
'T2CON = %00000100

osctune=0

'************************************************* ****************************
'DEFINEs
'************************************************* ****************************

@ DEVICE INTRC_OSC
@ DEVICE MCLR_OFF
@ DEVICE PROTECT_OFF

DEFINE osc 8

@ DEVICE CPD_OFF
@ DEVICE LVP_OFF
@ DEVICE BOD_OFF
@ DEVICE PWRT_OFF
@ DEVICE WDT_OFF

'************************************************* ****************************


'************************************************* ****************************
'ADC parameters

ADCON1 =%10000000 'right justify
ANSEL =%00000001 'PORTA.0 ANALOG
ADCON0 =%11000001

'************************************************* ****************************

INCLUDE "modedefs.bas"

'settings for serial comm

DEFINE debug_reg PORTB
DEFINE debug_bit 7
DEFINE debug_baud 9600
DEFINE debug_mode 1

'************************************************* ****************************
'I/O's

PORTA=0
PORTB=0

TRISA=%00000001 'PORTA.0 AS INPUT
TRISB=%00000111 'SDA,SCL AND BUT1 AS INPUTS

'************************************************* ****************************
'PINS

A0 var PORTA.0
a1 var PORTA.1
A2 var PORTA.2
A3 var PORTA.3
A4 var PORTA.4
MCLR var PORTA.5
a6 var PORTA.6
a7 var PORTA.7

SDA var PORTB.0 'I2C DATA PIN
SCL var PORTB.1 'I2C CLOCK PIN
but1 var PORTB.2 'BUTTON FOR LOOP
b3 var PORTB.3

B4 var PORTB.4
B5 var PORTB.5
B6 var PORTB.6
out var PORTB.7

'************************************************* ****************************
' variables


mem var byte

ADDR var word
m1 var word
m2 var word
CTW VAR WORD

'************************************************* ****************************

CTW=$A0
m1=0
m2=0

'************************************************* ****************************

start:

I2CREAD SDA,SCL,CTW,$1,[m1]
pause 10

debug " value IN EEPROM address 1 = ",dec m1,13,10

I2CREAD SDA,SCL,CTW,$10,[m2]
pause 10

debug " value IN EEPROM address 10 = ",dec m2,13,10

I2CWRITE SDA,SCL,CTW,$1,[5]
PAUSE 10

debug " WROTE 5 at address 1 = ",13,10

I2CWRITE SDA,SCL,CTW,$10,[6]
PAUSE 10

debug " WROTE 6 at address 10 = ",13,10


loop:
if but1=1 then
goto start
else
goto loop
endif

end


The value returned for both addresses is 257

Just as a note, with the first code ( showned in post #4 ) the returned value was always 8 ( for any address ) and 0 when removing the pullups.

EDIT:
Changed the lines:

I2CWRITE SDA,SCL,CTW,$1,[5]

to

ADDR=$1
I2CWRITE SDA,SCL,CTW,ADDR,[5]

( as seen in Melanie's post about I2C )
http://www.picbasic.co.uk/forum/showthread.php?t=587

but the return value is the same :(

skimask
- 20th February 2008, 23:37
DEFINE OSC 8
INCLUDE "modedefs.bas"
@ DEVICE INTRC_OSC
@ DEVICE MCLR_OFF
@ DEVICE PROTECT_OFF
@ DEVICE CPD_OFF
@ DEVICE LVP_OFF
@ DEVICE BOD_OFF
@ DEVICE PWRT_OFF
@ DEVICE WDT_OFF
DEFINE DEBUG_REG PORTB
DEFINE DEBUG_BIT 7
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 1
osccon=$7e:cmcon=7:adcon1=$80:ansel=1:adcon0=$c1:p orta=0:portb=0:trisa=1
trisb=7:sda var portb.0:scl var portb.1:addr var word:dat var byte
dat2 var byte:ctw con $a0
start: dat=dat+1:addr=addr+1
i2cwrite sda,scl,ctw,addr.highbyte,addr.lowbyte,[dat]:pause 10
debug "Wrote: ",dec addr," with ",dec dat,13,10
i2cread sda,scl,ctw,addr.highbyte,addr.lowbyte,[dat2]
debug " Read: ",dec addr," val: ",dec dat2 , 13 , 10
if dat = dat2 then
debug "Write/Read Successful at ",dec5 addr," with ",dec3 dat,13,10
else
debug "Write/Read Error at ",dec5 addr,"-Wrote:",dec3 dat," - Read:",dec dat2,13,10
endif
pause 500:goto start
END


OR un-COLONized...



DEFINE OSC 8
INCLUDE "modedefs.bas"
@ DEVICE INTRC_OSC
@ DEVICE MCLR_OFF
@ DEVICE PROTECT_OFF
@ DEVICE CPD_OFF
@ DEVICE LVP_OFF
@ DEVICE BOD_OFF
@ DEVICE PWRT_OFF
@ DEVICE WDT_OFF
DEFINE DEBUG_REG PORTB
DEFINE DEBUG_BIT 7
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 1
osccon = $7e
cmcon = 7
adcon1 = $80
ansel = 1
adcon0 = $c1
porta = 0
portb = 0
trisa = 1
trisb = 7
sda var portb.0
scl var portb.1
addr var word
dat var byte
dat2 var byte
ctw con $a0

start:
dat = dat + 1
addr = addr + 1
i2cwrite sda , scl , ctw , addr.highbyte , addr.lowbyte , [ dat ]
pause 10
debug "Wrote: " , dec5 addr , " with " , dec3 dat , 13 , 10
i2cread sda , scl , ctw , addr.highbyte , addr.lowbyte , [ dat2 ]
debug " Read: " , dec5 addr , " val: " , dec3 dat2 , 13 , 10
if dat = dat2 then
debug "Write/Read Successful at " , dec5 addr , " with " , dec3 dat , 13 , 10
else
debug "Write/Read Error at " , dec5 addr , "-Wrote:" , dec3 dat , " - Read:" , dec dat2 , 13 , 10
endif
pause 500
goto start
END

ruijc
- 21st February 2008, 19:39
Hi skimask,

i'm pleased to say that your code worked. Thank you very much for your help ;)

Will re-write my entire code from scratch.

I have some notes here and i will see what happens.

.

skimask
- 21st February 2008, 19:43
Hi skimask,
i'm pleased to say that your code worked. Thank you very much for your help ;)
Will re-write my entire code from scratch.
I have some notes here and i will see what happens.
.

Really?
That's amazing...because I did a quick search a couple days ago for 24LC512 here on THESE forums and, except for COLON-izing the one listing, practically did a cut-and-paste.
Search engine must've been broken that day...huh?

ruijc
- 21st February 2008, 20:16
I guess i missed that one, sorry.

But thanks anyway for your help ;)

.

ruijc
- 22nd February 2008, 10:58
Greetings,

While reviewing my code i changed the I2C lines from :

I2Cread SDA,SCL,CTW,mem,[x]

to

I2Cread SDA,SCL,CTW,mem.highbyte,mem.lowbyte,[x]

to make it work.

Sorry if i'm a bit stubborn ( just trying to learn :) ), but i re-made ( yes... re-made ;) ) the search and as before almost every one mentions the I2C lines as follows :


I2cwrite SDA,SCL,CONTROL,ADDR,[DATA]

Posts like:
http://www.picbasic.co.uk/forum/showthread.php?t=6162&highlight=24lc512

http://www.picbasic.co.uk/forum/showthread.php?t=5639&highlight=24lc512

http://www.picbasic.co.uk/forum/showthread.php?t=2688&highlight=24lc512

Including melanie's post

http://www.picbasic.co.uk/forum/showthread.php?t=587

The only one that mentions to separate the address in high and low somehow did not worked in that case

http://www.picbasic.co.uk/forum/showthread.php?t=5976&highlight=24lc512


My question is just to try to understand

Why is that the i2c line ( I2cwrite SDA,SCL,CONTROL,ADDR,[DATA] ) works with other pics ( yes...all my programs with 12F675 work ) and with the 16F88 does not ? Why with this pic i need to have the address separated with high and low byte ?

Also ( question for skimask )
In post # 7 you mention :



'cause I see a few flaws in your logic in the code written a few posts back.


Can you please point where the flaws are so i can take a look at them ?

Thanks

skimask
- 22nd February 2008, 14:00
Why is that the i2c line ( I2cwrite SDA,SCL,CONTROL,ADDR,[DATA] ) works with other pics ( yes...all my programs with 12F675 work ) and with the 16F88 does not ? Why with this pic i need to have the address separated with high and low byte ?

Quite frankly, if it works, who cares? :)
Actually, I don't remember the answer to that at the moment. I'll remember eventually...



Also ( question for skimask )
In post # 7 you mention :


'cause I see a few flaws in your logic in the code written a few posts back.

Can you please point where the flaws are so i can take a look at them ?
Thanks
You'll figure it out... Suffice to say there's just MUCH better ways to do some things, more reliable, faster, longer, stronger, and so on...

ruijc
- 22nd February 2008, 14:13
I've had to make some changes in my logic to work with the new I2C lines ( low/high address ) but still maintained the generic structure.

This was my priority #1

After checking if it works will study on those flaws :).

I undestand your point of "if it works, who cares", but if we leave things like that we will never get to improve the codes to be more reliable, faster and shorter ;)

Dont you agree ?

In the mean time, if you remember please let me know ;)

Thanks again
.