Continue to Site

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.

  • 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.

Problem in I2C writing operation

Status
Not open for further replies.

pimh123

New Member
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:
#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:
#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:

I2c_debug_zpsd8fnm8ad.jpg


Finally the schematic:
PIC_I2C_zpsrrduffl7.jpg


Thanks...
 
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....
 
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:
        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.

qx7vjb.png


Thanks...
 
You need a delay after a write to eeprom (5 msec or so ) before you can read.
 
You need a delay after a write to eeprom (5 msec or so ) before you can read.
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..
 
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

v4oy37.png


Code:
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:
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... ?
 
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 ?
 
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:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top