• Serial EEPROM Part #1

    This is an effort to help users understand how the I2C command works by comparing it with SHIFTIN/SHIFTOUT. A serial EEPROM, 24FC1025 will be used in the example.


    A while back I was trying to help someone with a 24FC1025 and I was having problems with PBP I2C so I decided to work with the part the "old fashioned" way using SHIFTIN and SHIFTOUT. Turns out my problem was using an analog pin on the PIC without setting it to digital. Yes, a typical mistake, not always made by newbies.

    Many devices are interfaced via I2C, they can also be interfaced via SHIFTIN/SHIFTOUT. Either way an understanding of the part is needed. That is where the data sheet comes in.

    First, compare the two figures below. The fisrt one is from the PBP manual showing a time line of the SHIFT sequence. The second is from the EEPROM data sheet showing the data transfer sequence. Similar ???



    From the data sheet look at figure 6.1. This shows the sequence of events to write a BYTE of data to the EEPROM.

    The first thing we do is put the EEPROM in a START condition. This is done by holding the EEPROM clock pin HIGH and toggleing the data pin High to LOW. The I2C command does this for us.
    Code:
    HIGH CPIN:HIGH DPIN:LOW DPIN
    Next the control byte is sent. This has to be done when using I2C also.
    Bits 7-4 are the control code for this EEPROM. "1010"
    Bit 3 is is for selecting the memory block, this EEPROM is divided into to parts. This example is using the lower half. "0"
    Bits 2-1 are for addressing. Up to four EEPROM can be used on the same bus. In this example both pins A1 and A2 are pulled LOW. "00"
    Bit 0 selects Read or Write mode. "0" for Write, "1" for Read. PBP's I2C command will set this bit for us, leave as "0"

    When the EEPROM receives the control byte it will then send an ACKnowledge bit to the MCU. Then the High byte of the EEPROM address can be sent, this will be followed by another ACK from the EEPROM. The LOW byte of the address is sent next, with the EEPROM sending an ACK again.
    In the below code the above is all in the "INT_ROM:" routine. PBP I2C will take care of the ACKs.

    Now a BYTE of data can be sent to the EEPROM, when the data is received by the EEPROM it will send an ACK to the MCU. The MCU will then send a STOP condition to the EEPROM letting it know to start writing the data. Again, the I2C command does this for us.
    Code:
    HIGH CPIN:LOW  DPIN:HIGH DPIN
    Below are two programs, one using I2C and the other using the SHIFT method described above, both programs do the same thing. Hopefully by comparing the two along with the data sheet and the above text you will have a better understanding of how the I2C command works.

    Part #2 will talk about WORD and page writes to the EEPROM.

    Code:
    '  18F6680  24FC1025
    '912 BYTES
        DEFINE OSC 20
        @ __CONFIG    _CONFIG1H, _OSC_HS_1H
        @ __CONFIG    _CONFIG2H, _WDT_OFF_2H & _WDTPS_128_2H
        @ __CONFIG    _CONFIG4L, _LVP_OFF_4L
        DEFINE LCD_DREG     PORTG
        define LCD_DBIT     0
        DEFINE LCD_RSREG    PORTE
        DEFINE LCD_RSBIT    0
        DEFINE LCD_EREG     PORTE
        DEFINE LCD_EBIT     1
        DEFINE LCD_BITS     4
        DEFINE LCD_LINES    4
        DEFINE LCD_COMMANDUS    3000
        DEFINE LCD_DATAUS   150
        
        DPIN    VAR PORTB.2    'I2C DATA PIN
        CPIN    VAR PORTB.1    'I2C CLOCK PIN
        ADDR    VAR WORD
        DATI    VAR BYTE
        DATO    VAR BYTE
        
        START2:  ADDR = 0 : DATO = 0
        For ADDR = 0 To 15    
        DATO = DATO + 2            
        I2CWRITE DPIN,CPIN,$A0,ADDR,[DATO]  
        Pause 10                
        Next ADDR
        Pause 100   
                     
        ADDR = 0
        For ADDR = 0 To 15     
        I2CREAD DPIN,CPIN,$A0,ADDR,[DATI]       
        lcdout $FE,1,"DATI ",DEC DATI
        lcdout $FE,$C0,"ADDR ",DEC ADDR
        PAUSE 250
        Next ADDR
    
        GOTO START2
    Code:
    '  18F6680  24FC1025
    '1216 BYTES
        DEFINE OSC 20
        @ __CONFIG    _CONFIG1H, _OSC_HS_1H
        @ __CONFIG    _CONFIG2H, _WDT_OFF_2H & _WDTPS_128_2H
        @ __CONFIG    _CONFIG4L, _LVP_OFF_4L
        DEFINE LCD_DREG     PORTG
        define LCD_DBIT     0
        DEFINE LCD_RSREG    PORTE
        DEFINE LCD_RSBIT    0
        DEFINE LCD_EREG     PORTE
        DEFINE LCD_EBIT     1
        DEFINE LCD_BITS     4
        DEFINE LCD_LINES    4
        DEFINE LCD_COMMANDUS    3000
        DEFINE LCD_DATAUS   150
        
        DPIN    VAR PORTB.2    'I2C DATA PIN
        CPIN    VAR PORTB.1    'I2C CLOCK PIN
        ADDR_HB    VAR BYTE
        ADDR_LB    VAR BYTE
        ADDR_HB = 0
        ADDR_LB = 0
        CONT1   CON %10100001  'READ CONTROL
        CONT0   CON %10100000  'WRITE CONTROL
        ACK     VAR BIT
        DATI    VAR BYTE
        DATO    VAR BYTE
        
        START:     DATO = 0
        WRITE_DATA:
        For ADDR_LB = 1 To 15   
        DATO = DATO + 2         
        GOSUB INT_ROM
        SHIFTOUT DPIN,CPIN,1,[DATO\8,%1\1]      
        GOSUB STOP_ROM
        PAUSE 10
        NEXT ADDR_LB
    
        READ_DATA: 
        For ADDR_LB = 0 To 15 
        GOSUB INT_ROM
        GOSUB START_ROM
        SHIFTOUT DPIN,CPIN,1,[CONT1]
        SHIFTIN DPIN,CPIN,0,[ACK\1,DATI\8]
        SHIFTOUT DPIN,CPIN,1,[%1\1]
        GOSUB STOP_ROM
        lcdout $FE,1,"DATI ",DEC DATI
        lcdout $FE,$C0,"ADDR ",DEC ADDR_LB
        PAUSE 250
        NEXT ADDR_LB
        GOTO START
        
        INT_ROM:
        GOSUB START_ROM
        SHIFTOUT DPIN,CPIN,1,[CONT0]
        SHIFTIN DPIN,CPIN,0,[ACK\1]
        SHIFTOUT DPIN,CPIN,1,[ADDR_HB]
        SHIFTIN DPIN,CPIN,0,[ACK\1]
        SHIFTOUT DPIN,CPIN,1,[ADDR_LB]
        SHIFTIN DPIN,CPIN,0,[ACK\1]
        RETURN
        
        START_ROM:
        HIGH CPIN:HIGH DPIN:LOW DPIN:RETURN
       
        STOP_ROM:
        HIGH CPIN:LOW DPIN:HIGH DPIN:RETURN