I2C with External Eeprom


Closed Thread
Results 1 to 16 of 16
  1. #1

    Default I2C with External Eeprom

    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

  2. #2
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by ruijc View Post
    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?

  3. #3
    Join Date
    Sep 2007
    Location
    USA, CA
    Posts
    271


    Did you find this post helpful? Yes | No

    Default

    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.

  4. #4


    Did you find this post helpful? Yes | No

    Default

    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 :

    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

  5. #5
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    WP pin pulled high? Low? Floating?
    Address pins pulled high? Low? Floating?

  6. #6


    Did you find this post helpful? Yes | No

    Default

    WP is connected to ground. Same as all address pins of the eeprom.

  7. #7
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by ruijc View Post
    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.

  8. #8


    Did you find this post helpful? Yes | No

    Default

    Thanks skimask,

    Good idea. Will do that tonight and post the results

    .

  9. #9


    Did you find this post helpful? Yes | No

    Default

    Just finished assembling a small code and still cannot work with the eeprom

    this is the code i used :

    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   	'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
    Last edited by ruijc; - 20th February 2008 at 22:30.

  10. #10
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Code:
    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: ",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...

    Code:
    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
    Last edited by skimask; - 20th February 2008 at 23:42.

  11. #11


    Did you find this post helpful? Yes | No

    Default

    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.

    .

  12. #12
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Cool

    Quote Originally Posted by ruijc View Post
    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?

  13. #13


    Did you find this post helpful? Yes | No

    Default

    I guess i missed that one, sorry.

    But thanks anyway for your help

    .

  14. #14


    Did you find this post helpful? Yes | No

    Default

    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/show...hlight=24lc512

    http://www.picbasic.co.uk/forum/show...hlight=24lc512

    http://www.picbasic.co.uk/forum/show...hlight=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/show...hlight=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 :

    Code:
    '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

  15. #15
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by ruijc View Post
    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 :
    Code:
    '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...

  16. #16


    Did you find this post helpful? Yes | No

    Default

    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
    .

Similar Threads

  1. I2C Master/Slave 16F88/16F767 working code
    By DanPBP in forum Code Examples
    Replies: 2
    Last Post: - 23rd October 2012, 22:31
  2. Can't read sequential addresses in external EEPROM
    By tjkelly in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 18th February 2010, 14:46
  3. Replies: 1
    Last Post: - 28th January 2010, 22:15
  4. Problem with I2C EEPROM addressing
    By Atom058 in forum General
    Replies: 14
    Last Post: - 3rd November 2009, 03:17
  5. HARDWARE I2C SAMPLE CODE question
    By Michael Wakileh in forum Code Examples
    Replies: 2
    Last Post: - 16th June 2009, 21:07

Members who have read this thread : 0

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts