Connect with us

External I2C EEPROM Interfacing with PIC18F4550

Discussion in 'Microcontrollers, Programming and IoT' started by Nandish, Jun 30, 2014.

Scroll to continue with content
  1. Nandish

    Nandish

    1
    0
    Jun 30, 2014
    i'm using AT24C04 I2C EEPROM ,i want to write 48 bytes into EEPROM but internally EEPROM organized to max 16bytes of each page write.
    i can possible to write 16bytes in first...My doubt is ...How to write 16bytes into another page...
    My code is here...
    MAIN.C
    #include <p18f4550.h>
    #include "I2C_EEPROM.h"
    #include <i2c.h>

    // CONFIG1L
    #pragma config PLLDIV = 5 // PLL Prescaler Selection bits (Divide by 5 (20 MHz oscillator input))
    #pragma config CPUDIV = OSC1_PLL2// System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
    // CONFIG1H
    #pragma config FOSC = HS // Oscillator Selection bits (HS oscillator, PLL enabled (HSPLL))
    #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
    #pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
    // CONFIG2L
    #pragma config BOR = ON // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
    // CONFIG2H
    #pragma config WDT = OFF // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
    // CONFIG3H
    #pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
    #pragma config MCLRE = OFF // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
    // CONFIG4L
    #pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
    #pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)
    #pragma config ICPRT = OFF // Dedicated In-Circuit Debug/Programming Port (ICPORT) Enable bit (ICPORT disabled)
    // CONFIG5L
    #pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM is not code-protected)
    //#pragma config DUBUG = ON
    #define PAGESIZE 16

    void InitI2C(void);
    void I2CEeprom(void);
    void PollI2CEeprom (void);
    void Error(void);

    unsigned int PageSize = 16;
    unsigned char eeprom_address = 0xA0;
    unsigned int EepAdd = 0x01; // address

    unsigned char WrData[] = {0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};
    unsigned char RdData[PAGESIZE] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};


    void main(void)
    {
    unsigned char delay;

    InitI2C();

    I2CEeprom();

    // incase of successful operation control reach here..
    TRISDbits.TRISD2= 0;
    while (1)
    {
    LATDbits.LATD2= ~(LATDbits.LATD2);// toggle RD2
    delay = 0x50;
    while(delay--);
    }
    }

    void InitI2C(void)
    {
    TRISBbits.TRISB1 = 1; // SCL dir input
    TRISBbits.TRISB0 = 1; // SDA dir input

    PIR1bits.SSPIF = 0; // clear interrupt flag
    SSPSTAT = 0x00;
    SSPADD = 0x31; // I2C baud = 100KHz @ Fosc = 20MHz
    SSPCON2 = 0x00;
    SSPCON1 = 0x28; // Master mode I2C
    }

    void I2CEeprom(void)
    {
    unsigned char i;
    unsigned char length;

    length = 16;
    ForWrite(eeprom_address, EepAdd, WrData);
    PollI2CEeprom();
    ForRead(eeprom_address, EepAdd, RdData, length);
    for(i=0; i<length; i++)
    {
    if(RdData != WrData)
    {
    Error();
    }
    }
    }

    void PollI2CEeprom (void)
    {
    while (1)
    {
    StartI2C();
    IdleI2C();
    WriteI2C( eeprom_address );
    IdleI2C();

    if (SSPCON2bits.ACKSTAT == 0)
    {
    StopI2C();
    IdleI2C();
    break;
    }

    StopI2C();
    IdleI2C();
    }
    }

    void Error(void)
    {
    unsigned char delay;

    TRISDbits.TRISD1 = 0;

    while (1)
    {
    LATDbits.LATD3= ~(LATDbits.LATD3);// toggle RD3
    delay = 0x50;
    while(delay--);
    }
    }
    EEPROM.C

    #include <p18f4550.h>
    #include <i2c.h>
    #include "I2C_EEPROM.h"


    unsigned char ForWrite( unsigned char ControlByte, unsigned char LowAdd, unsigned char *wrptr )
    {
    IdleI2C(); // ensure module is idle
    StartI2C(); // initiate START condition
    while ( SSPCON2bits.SEN ); // wait until start condition is over
    WriteI2C( ControlByte ); // write 1 byte - R/W bit should be 0
    IdleI2C(); // ensure module is idle
    WriteI2C( LowAdd ); // write LowAdd byte to EEPROM
    IdleI2C(); // ensure module is idle
    putstringI2C ( wrptr ); // pointer to data for page write
    IdleI2C(); // ensure module is idle
    StopI2C(); // send STOP condition
    while ( SSPCON2bits.PEN ); // wait until stop condition is over
    return ( 0 ); // return with no error
    }


    unsigned char ForRead( unsigned char ControlByte, unsigned char address, unsigned char *rdptr, unsigned char length )
    {
    IdleI2C(); // ensure module is idle
    StartI2C(); // initiate START condition
    while ( SSPCON2bits.SEN ); // wait until start condition is over
    WriteI2C( ControlByte ); // write 1 byte
    IdleI2C(); // ensure module is idle
    WriteI2C( address ); // WRITE word address to EEPROM
    IdleI2C(); // ensure module is idle
    RestartI2C(); // generate I2C bus restart condition
    while ( SSPCON2bits.RSEN ); // wait until re-start condition is over
    WriteI2C( ControlByte | 0x01 ); // WRITE 1 byte - R/W bit should be 1 for read
    IdleI2C(); // ensure module is idle
    getsI2C( rdptr, length ); // read in multiple bytes
    NotAckI2C(); // send not ACK condition
    while ( SSPCON2bits.ACKEN ); // wait until ACK sequence is over
    StopI2C(); // send STOP condition
    while ( SSPCON2bits.PEN ); // wait until stop condition is over
    return ( 0 ); // return with no error
    }


    unsigned char putstringI2C( unsigned char *wrptr )
    {

    unsigned char x;
    for (x = 0; x < PageSize; x++ ) // transmit data until PageSize
    {
    if ( SSPCON1bits.SSPM3 ) // if Master transmitter then execute the following
    {
    if ( putcI2C ( *wrptr ) ) // write 1 byte
    {
    return ( -3 ); // return with write collision error
    }
    IdleI2C(); // test for idle condition
    if ( SSPCON2bits.ACKSTAT ) // test received ack bit state
    {
    return ( -2 ); // bus device responded with NOT ACK
    } // terminateputstringI2C() function
    }
    else // else Slave transmitter
    {
    PIR1bits.SSPIF = 0; // reset SSPIF bit
    SSPBUF = *wrptr; // load SSPBUF with new data
    SSPCON1bits.CKP = 1; // release clock line
    while ( !PIR1bits.SSPIF ); // wait until ninth clock pulse received

    if ( ( !SSPSTATbits.R_W ) && ( !SSPSTATbits.BF ) )// if R/W=0 and BF=0, NOT ACK was received
    {
    return ( -2 ); // terminateputstringI2C() function
    }
    }
    wrptr ++; // increment pointer
    } // continue data writes until null character
    return ( 0 );
    }
     
  2. shumifan50

    shumifan50

    548
    56
    Jan 16, 2014
    The address word is 8 bits long. When you do a page write the bottom 4 bits are autoincremented, but the upper 4 bits are not. When you send the address word you select the page by setting the upper bits to the appropriate page number. Be aware that the lower auto increment will wrap - so if you start writing at an address that has a non-zero bottom 4 bits and you write 16 bytes then then when the autoinc reaches zero for the 4 bits, it will start writing at the beginning of the same page.
     
    Nandish likes this.
Ask a Question
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.
Electronics Point Logo
Continue to site
Quote of the day

-