1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Problem in I2C writing operation

Discussion in 'Code Repository' started by pimh123, Sep 4, 2015.

  1. pimh123

    pimh123 New Member

    Joined:
    Sep 4, 2015
    Messages:
    8
    Likes:
    0
    Hi guys,
    Im using PIC24FJ64GA002 microcontroller. Working in I2C protocol interfacing PIC with EEPROM(). Im not working in physically. All work are doing in proteus simulation only. My environment IDE is MPLAB v8.92, XC16 compiler and proteus simulation. My EEPROM slave address in "0xa0"(all address pins(A0,A1,A2) are grounded). In proteus i can't see whether data is writing or not, so i removed the eeprom and placed I2C debugger. Im new to I2C debugger. I almost see some info on I2C debug window. Im trying to write letter 'M' in eeprom. I can't see letter 'M' in I2C debug window. It seems data 'M' didnt send to eeprom. I didnt find any flaw in my code.

    My i2c.h:
    Code (text):
    #include "p24FJ64GA002.h"
    #include "stdio.h"

    void init_i2c()
    {
    ///Initiate I2C1 (Slave Device)
        I2C1CONbits.I2CEN = 1;    // I2C enable
        I2C1CONbits.I2CSIDL = 0;    // I2C stop in idle
        I2C1CONbits.SCLREL = 0;    // I2C clock release
        I2C1CONbits.STREN = 0;    // I2C clock stretch enable
        I2C1CONbits.IPMIEN = 0;    // I2C Peripheral Management
        I2C1CONbits.A10M = 0;    // I2C address size = 7 bit
        I2C1CONbits.SMEN = 0;    // I2C address size = 7 bit
        I2C1CONbits.SMEN = 0;    // I2C SMBUS enable
        I2C1MSK = 0x0000;    // I2C SMBUS enable
        I2C1BRG = 37; //Baud Rate
        I2C1ADD = 0xa0;
        _SI2C1IF = 0;
        _SI2C1IE = 1;
        //SendUARTStr("I2C Initiated ");
    }
    My main.c:
    Code (text):
    #include "p24FJ64GA002.h"
    #include <stdio.h>
    #include "uart.h"
    #include <stdint.h>
    #include "i2c.h"


    unsigned char I2CFlag,db,I2C2Rcv,C_I2CTimeout,I2CTimer;
    #define C_I2CTimeOut 30
    /* Main function*/
    int main (void)
    {
            TRISA=0x0000;
        //Set input port B
                TRISB = 0xFFFF;
                 //Assign uart pins///////////
                RPINR18bits.U1RXR = 10;
                //  Tx:RP13(Pin)
                RPOR6bits.RP13R   = 3;  
                ////////////////////////////
                           
                /////Initiate UART////////////////////////////////////////////
                InitUART();/////////////////////////////////////////////////////
                //////////////
                //////////////////////////////////////////////////////////////
            SendUARTStr("PIC24F connected");
            Timer(10);
            SendUARTStr("Uart initiated");
            Timer(10);
           
            init_i2c();
            Timer(10);
            //SendUARTStr("I2C Initiated");
            SaveEEPW(0xa0,'M');
            Timer(5);
                uint16_t Addr=0xa0;
            //    ReadEEPW(Addr);
               
                while(1)
                {
                   
                   
                }

               
    }

    /* End of Main function*/

    /* Function WriteRTC() - Writes a byte into RTC register */
    void WriteI2C(unsigned char DeviceAddress, uint16_t Addr, unsigned char db)
    {  
        uint32_t i;
        unsigned char WriteState;
        I2CTimer = WriteState = 0;
        IFS1 &= ~0x0002;                                                        // Master I2C interrupt flag MI2C2IF bit is set to = 1
        I2CFlag = 1;
        I2C1CON |= 0x0001;                                                                // SEN = 1;
        I2CTimer = 0;
        //Restart_WDT();                                                                // SEN = 1
        while(I2CFlag)
        {
            if(I2CTimer > C_I2CTimeout){                                                // Exit routine 0=30
                I2CFlag = 0;
                // Error to be handled here
            }
            if(IFS1 & 0x0002){                                                            // SSP1IF
           
                IFS1 &= ~0x0002;                                                        // Master I2C interrupt flag
                I2CTimer = 0;
                if(!WriteState){
                    I2C1TRN = (DeviceAddress & 0xa0);                                    // Device Address + Write 0
                    if(DeviceAddress == 0xde)WriteState = 1;                                // Skip State 1 for RTC                               // Skip State 1 for RTC
                }
                else if(WriteState == 1)I2C1TRN = Make8(Addr, 1);                        // MSB Send Address
                else if(WriteState == 2)I2C1TRN = Make8(Addr, 0);                        // LSB of Address
                else if(WriteState == 3)I2C1TRN = db;                                    // Write data
                else if(WriteState == 4)I2C1TRN |= 0x04;                                // PEN = 1, Stop enable
                else{WriteState = 98; I2CFlag = 0;}                                        // end of process
                WriteState++;                                                            // Next state
                SendUARTStr(db);
            }
        }
        Timer(2);
    }
    /* End Function WriteRTC() */

    /* Function SaveEEPW() - Saves a Word into EEPROM */
    void SaveEEPW(uint16_t EEPAddress, uint16_t Cx)
    {    unsigned char i, *Ptr;
        Ptr = &Cx;
        i = 2;
        do{
            WriteI2C(0xa0, EEPAddress++, *Ptr++);
       
        }while(--i);
    }
    /* End Function SaveEEPW() */

    /* Make8 */
    void Make8(uint16_t i,int j)
        {
            unsigned char loByte;
            unsigned char hiByte;
            loByte = i & 0x00ff;
            hiByte = i >> 8;

            if(j==0)
            {
                //printf("0x%2x",loByte);
                return loByte;
            }

            if(j==1)
            {
                //printf("0x%2x",hiByte);
                return hiByte;
            }

        }
    /* End of Make8 */  
       
    I2C debug window:

    [​IMG]

    Finally the schematic:
    [​IMG]

    Thanks...
     
  2. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    8,588
    Likes:
    821
    Location:
    Rochdale UK
    I2C write:

    send start
    send device address, wait for ack.
    send internal address ( one or two bytes ).. wait for ack
    send byte.
    send nack.
    sent stop.

    This is the minimum...

    C24 compiler has I2C routines....
     
  3. pimh123

    pimh123 New Member

    Joined:
    Sep 4, 2015
    Messages:
    8
    Likes:
    0
    Hi Roger,
    Thanks for the reply. I recoded very simply to test the write and read option. Im trying to write and read a single letter 'Q'. Hope i write successfully on the eeprom, while i reading the data from eeprom im always receiving "FF".

    Code (text):

            init_i2c();

            I2C1CONbits.SEN=1; //Initiates Start condition on SDAx and SCLx pins.
            Timer(2);
            //I2C1TRN=DeviceAddress; //I2c Device address(salve)
            I2C1TRN = (DeviceAddress | 0x00); //Write
            Timer(2);//=======================================>>>>>>>Checkpoint
            //Timer(1);
            //flag=1;
           
            if(IFS1bits.MI2C1IF==1)
            {
                //SendUARTStr("Ack Received");
                IFS1bits.MI2C1IF=0;//==============================clear interrupt
                Timer(2);
                //HighAddr = Address >> 8;
                I2C1TRN=HighAddr;
                Timer(2);
                if(IFS1bits.MI2C1IF==1)
                    {
                        //LowAddr = Address;
                        I2C1TRN = LowAddr;
                        Timer(2);
                    }
               
                if(IFS1bits.MI2C1IF==1)
                    {
                        //SendUARTStr("Ack Received 123");
                        IFS1bits.MI2C1IF=0;//==============================clear interrupt
                        Timer(2);
                        I2C1TRN = 'Q'; ////////////////Writing 'Q' into the eeprom
                        Timer(2);
                       
                        if(IFS1bits.MI2C1IF==1)
                    {
                        //SendUARTStr("Ack Received 321");
                        Timer(2);
                        I2C1CONbits.PEN=1;
                        Timer(2);
                    }
                       
                       
                    }
        }
           
    //==============================Read operation

            I2C1CONbits.SEN=1; //Initiates Start condition on SDAx and SCLx pins.
            Timer(2);
            //I2C1TRN=DeviceAddress; //I2c Device address(salve)
            I2C1TRN = (DeviceAddress | 0x01); /////Read mode
            Timer(2);//=======================================>>>>>>>Checkpoint
            if(IFS1bits.MI2C1IF)
            {
                SendUARTStr("Read123");
               
            }
            ///I2C1TRN = (DeviceAddress | 0x01);
            IFS1bits.MI2C1IF==0;
            Timer(2);
            I2C1CONbits.RCEN=1;
            Timer(2);
            Timer(1);
            db=I2C1RCV;
            SendUARTStr(db);
            //Timer(2);
            I2C1CONbits.ACKDT=1;  //Generate NACK
            //Timer(2);
            if(IFS1bits.MI2C1IF==1)
                    {
                        SendUARTStr("Received");
                        Timer(2);
                        I2C1CONbits.PEN=1; //Stop I2C
                        Timer(2);
                       
                    }
                   
            //flag=1;
           
           
                while(1)
                {
                 
                 
                }
    Below is my debugger windows after WRITE and READ operation.

    [​IMG]

    Thanks...
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. granddad

    granddad Active Member

    Joined:
    Jan 18, 2015
    Messages:
    676
    Likes:
    63
    Location:
    Worcestershire UK

    You need a delay after a write to eeprom (5 msec or so ) before you can read.
     
  6. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    8,588
    Likes:
    821
    Location:
    Rochdale UK
    Yes! Missed that!!

    You should try and make things easier for yourself... Write some low level routines and just call them... Your code is very hard to follow..
     
  7. pimh123

    pimh123 New Member

    Joined:
    Sep 4, 2015
    Messages:
    8
    Likes:
    0
    Thanks for the reply. Guys i gave 5m sec after wite and before read the data. Still read "FF".
    Below code is my delay code.

    Timer(10) ~ 1 sec.

    If i gave less that Timer(1) after wite and before read the data, im getting below sequence

    [​IMG]

    Code (text):
    void Timer(unsigned int S01)
            {  
                unsigned int lp;
                T2CON = 0b1000000000100000;  //  1/64,16Bit
                PR2 = 0x186A;  // 10Hz (0x186a;0d6250)
                TMR2 = 0;
                for(lp=0;lp<S01;lp++)
                    {
                        IFS0bits.T2IF = 0;
                        while(1)
                            {
                                if(IFS0bits.T2IF != 0 )break;   //See Manual P.25 (T2IF)
                            }
                    }
            }
     
    Last edited: Sep 8, 2015
  8. granddad

    granddad Active Member

    Joined:
    Jan 18, 2015
    Messages:
    676
    Likes:
    63
    Location:
    Worcestershire UK
    I have no proteus experience , so this may be off target. The I2C can be a headache , just quickly looking at your code, the I2C1ADD is for the pic24as a slave . not required as master. also... have the I2C pins been TRIS-ed as inputs, doest the eeprom have a write enable pin... ?
     
  9. pimh123

    pimh123 New Member

    Joined:
    Sep 4, 2015
    Messages:
    8
    Likes:
    0
    Ya. I gave TRISB = 0xFFFF; in my code.
     
  10. granddad

    granddad Active Member

    Joined:
    Jan 18, 2015
    Messages:
    676
    Likes:
    63
    Location:
    Worcestershire UK
    I have done my own I2C functions, but i do not use I2C interrupt , just poll the flags , but not with 'GA' but KA , think slight difference in names. will find and post if any help ?
     
  11. Ian Rogers

    Ian Rogers Super Moderator Most Helpful Member

    Joined:
    Mar 28, 2011
    Messages:
    8,588
    Likes:
    821
    Location:
    Rochdale UK
  12. granddad

    granddad Active Member

    Joined:
    Jan 18, 2015
    Messages:
    676
    Likes:
    63
    Location:
    Worcestershire UK
    Hi pimh123 Perhaps best to start at the start .... first have you followed the procedures in the eeprom data sheet for write to eeprom . ( you have not made it clear the eeprom involved ) . I am guessing 24LC256 ? (below) as it has h'0A device address... Caution ! some routines shift this address << 1 ... thus setting write or read flag... so may need to be h'50 as argument ... as a side issue your uart TXing may be effecting the I2C timing . but deal with that later.....
    writebyte.jpg

    edit
    PS I think you are reading the next address !
     
    Last edited: Oct 5, 2015

Share This Page