• AVR Freaks

Hot!PIC18F86J65 I2C problem

Author
stoyanoff
Super Member
  • Total Posts : 252
  • Reward points : 0
  • Joined: 2011/01/10 03:37:28
  • Location: 0
  • Status: offline
2020/01/28 01:07:13 (permalink)
0

PIC18F86J65 I2C problem

Greetings! Here is my code:

#define I2C_SCL_TRIS TRISCbits.TRISC2
#define I2C_SCL_Init() {I2C_SCL_TRIS=1;}
#define I2C_SDA_TRIS TRISCbits.TRISC3
#define I2C_SDA_Init() {I2C_SDA_TRIS=1;}
 
void I2C_Init()
{
I2C_SCL_Init();
I2C_SDA_Init();

SSP1CON1bits.SSPM=8;//master mode
//SSP1ADD=50;
SSP1STAT = 0x00;
SSP1CON2 = 0x00;
SSP1CON1bits.SSPEN = 1;
}
 
void RTCC_Read(unsigned char address,unsigned char value)
{
SSP1CON2bits.SEN=1;
SSP1BUF=address;
while(SSP1CON2bits.ACKSTAT);
SSP1BUF=value;
while(SSP1CON2bits.ACKSTAT);
SSP1CON2bits.PEN = 1;
}

 
The problem is I see some activity on the line, but I don`t see the values. I think something is wrong with my procedure. I`ve followed the procedure from page 299 of the PIC18F86J65.
Any ideas what I am doing wrong?
Thanks!
#1

14 Replies Related Threads

    ric
    Super Member
    • Total Posts : 25502
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: PIC18F86J65 I2C problem 2020/01/28 02:13:11 (permalink)
    +1 (1)
    stoyanoff
    ...
     I`ve followed the procedure from page 299 of the PIC18F86J65.
    Any ideas what I am doing wrong?

    You have missed the fact that you must wait for EACH operation to complete before doing the next one.
    You have also misunderstood the operation of ACKSTAT. You must wait for the transfer to finish, then read ACKSTAT once to see if it is high or low.
     
    e.g.
    SSP1CON2bits.SEN=1;
    while (SSP1CON2bits.SEN);    // wait until SEN falls, which indicates the START cycle has finished
    SSP1BUF=address;    // send slave address
    while (SSP1STATbits.R_W);    // wait until transfer finished and ACK/NAK has been received
    if (SSP1CON2bits.ACKSTAT == 0)    // did we receive an ACK?
    {
      SSP1BUF=value;    // send data
      while (SSP1STATbits.R_W);    // wait until transfer finished and ACK/NAK has been received
      if (SSP1CON2bits.ACKSTAT != 0)    // did we receive an ACK?
      {
        //maybe set a flag here to remember the data byte was NAKed)
      }
    SSP1CON2bits.PEN = 1;    // send STOP cycle
    while (SSP1CON2bits.PEN);    // wait until STOP has been sent

     
    post edited by ric - 2020/01/28 02:14:21

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #2
    stoyanoff
    Super Member
    • Total Posts : 252
    • Reward points : 0
    • Joined: 2011/01/10 03:37:28
    • Location: 0
    • Status: offline
    Re: PIC18F86J65 I2C problem 2020/01/28 04:25:26 (permalink)
    0
    Something is not right again! I`ve made my function same as yours and still I don`t see the data and clock on the pins. I`ve tried to transfer 3 bytes and there was only 1 transfer_init(SSP1CON2bits.SEN=1;) on the line... and just 4 tact pulses on the CLK line... Like I am interrupting it before it is done. But the bits are corrects -> like I`ve sent the data...
    #3
    ric
    Super Member
    • Total Posts : 25502
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: PIC18F86J65 I2C problem 2020/01/28 04:47:17 (permalink)
    +1 (1)
    Please show us the exact code you used.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #4
    stoyanoff
    Super Member
    • Total Posts : 252
    • Reward points : 0
    • Joined: 2011/01/10 03:37:28
    • Location: 0
    • Status: offline
    Re: PIC18F86J65 I2C problem 2020/01/28 08:47:03 (permalink)
    0
    Here you are:

    #define I2C_SCL_TRIS TRISCbits.TRISC2
    #define I2C_SCL_Init() {I2C_SCL_TRIS=1;}
    #define I2C_SDA_TRIS TRISCbits.TRISC3
    #define I2C_SDA_Init() {I2C_SDA_TRIS=1;}
    void I2C_Init()
    {
    I2C_SCL_Init();
    I2C_SDA_Init();

    SSP1CON1bits.SSPM=8;
    //SSP1ADD=50;
    SSP1STAT = 0x00;
    SSP1CON2 = 0x00;
    SSP1CON1bits.SSPEN = 1;
    }
     
    void I2C_Initalize_Write()
    {
    SSP1CON2bits.SEN=1;
    while (SSP1CON2bits.SEN); // wait until SEN falls, which indicates the START cycle has finished
    }
     
    unsigned char I2C_WriteByte(unsigned char data)
    {
    SSP1BUF=209; // send slave address
    while (SSP1STATbits.R_W); // wait until transfer finished and ACK/NAK has been received
    if (SSP1CON2bits.ACKSTAT == 0) // did we receive an ACK?
    { // did we receive an ACK?
    return 1;
    }
    return 0;
    }
     
    void I2C_Stop()
    {
    SSP1CON2bits.PEN = 1; // send STOP cycle
    while (SSP1CON2bits.PEN); // wait until STOP has been sent
    }
     
    void I2C_WriteProcedure()
    {
    I2C_Initalize_Write();
    I2C_WriteByte(209);
    I2C_Stop();
    }

    I`ve even tried with multiple I2C_WriteByte. In my logic analyzer it looks like there no 8 tacts on the CLK line but only 3-4...
    It could be something stupid, but I can`t see it now!
    #5
    ric
    Super Member
    • Total Posts : 25502
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: PIC18F86J65 I2C problem 2020/01/28 21:22:30 (permalink)
    +1 (1)
    My only other guess is that the R_W bit is not behaving as the datasheet says in your device
     
    Try changing
    SSP1BUF=209; // send slave address
    while (SSP1STATbits.R_W); // wait until transfer finished and ACK/NAK has been received

    to
    PIR1bits.SSPIF = 0;    // clear IF flag before write
    SSP1BUF=209; // send slave address
    while (PIR1bits.SSPIF == 0);    // wait until SSPIF is set

     
    Also note, your I2C_WriteByte() function should use
    SSP1BUF=data; // send data

    Right now it is always sending 209, regardless of the value passed to the function.
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #6
    stoyanoff
    Super Member
    • Total Posts : 252
    • Reward points : 0
    • Joined: 2011/01/10 03:37:28
    • Location: 0
    • Status: offline
    Re: PIC18F86J65 I2C problem 2020/01/30 03:46:57 (permalink)
    +1 (1)
    Yes!That`s it! Thanks!
    #7
    stoyanoff
    Super Member
    • Total Posts : 252
    • Reward points : 0
    • Joined: 2011/01/10 03:37:28
    • Location: 0
    • Status: offline
    Re: PIC18F86J65 I2C problem 2020/02/01 01:59:36 (permalink)
    0
    Ok! Something else is going on here! Here is my new code:

    void I2C_Init()
    {
    I2C_SCL_Init();
    I2C_SDA_Init();
    SSP1CON1bits.SSPM=8;
    SSP1ADD=77;
    SSP1STAT = 0x00;
    SSP1CON2 = 0x00;
    }
    void I2C_Start()
    {
    SSP1CON2bits.SEN=1;
    while (SSP1CON2bits.SEN); // wait until SEN falls, which indicates the START cycle has finished
    }
     
    void I2C_SendData(unsigned char data)
    {
    PIR1bits.SSPIF = 0;
    SSP1BUF=data; // send slave address
    while (PIR1bits.SSPIF == 0); // wait until SSPIF is set
    while(SSP1CON2bits.ACKSTAT);
    }
    unsigned char I2C_ReadData()
    {
    PIR1bits.SSPIF = 0;
    SSP1CON2bits.RCEN = 1;
    while (SSP1CON2bits.RCEN);
    while (PIR1bits.SSPIF == 0);
    SSP1CON2bits.ACKDT = 0;
    SSP1CON2bits.ACKEN = 1; // start the ACK/NACK
    while(SSP1CON2bits.ACKEN);
    return SSP1BUF;
    }
     
    void RTCC_Load()
    {
    unsigned char buffer[8];
    I2C_Start();
    I2C_SendData(208);
    I2C_SendData(0);
    I2C_Start();
    I2C_SendData(209);
    unsigned char i=0;
    for(i=0;i<8;i++)
    {
    buffer[i]=I2C_ReadData();
    }
    I2C_Stop();
    }

    When I execute this sequency once everything is fine. The values I get are correct and so on. But when I make second attemp to execute RTCC_Load(), my program blocks at while (PIR1bits.SSPIF == 0) on the very fisrt send data attempt! Any ideas what is going on here?
    Thanks!
    #8
    ric
    Super Member
    • Total Posts : 25502
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: offline
    Re: PIC18F86J65 I2C problem 2020/02/01 02:23:17 (permalink)
    +1 (1)
    When you read a sequence of bytes from a slave, send an ACK after all the intermediate bytes, but you MUST send a NAK after the last byte you want to read, not an ACK.
    You must do this to tell the slave to release the bus. Otherwise if the next bit it wants to send is a 0, you will not be able to send a STOP sequence, because the slave is holding SDA low.
     
     
     

    I also post at: PicForum
    Links to useful PIC information: http://picforum.ric323.co...opic.php?f=59&t=15
    NEW USERS: Posting images, links and code - workaround for restrictions.
    To get a useful answer, always state which PIC you are using!
    #9
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3638
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: PIC18F86J65 I2C problem 2020/02/01 05:08:24 (permalink)
    -1 (1)
    Make sure that the i2c 5 flags are clear before asserting i2c.
     
    while(I2C1CON&0x1F);
    Then set start etc..
     
    Every state must complete.

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #10
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3638
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: PIC18F86J65 I2C problem 2020/02/01 05:50:43 (permalink)
    0
    I use a function to read i2c.
    void i2c_gets(unsigned char ID, unsigned char Addr, void *Dest, int Len);
     
    The logic looks like this:
     
     1. assert start
     2. write device id
     3. write device addr
     4. assert restart
     5. write device id (set bit #0)
     6. loop Len {
     7.  Len == 1 ? x = NACK else x = ACK
     8. *Dest++=read(x)
     9. Len--
    10.}
    11. assert stop
     
    I will explain assert, write and read in the next post.

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #11
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3638
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: PIC18F86J65 I2C problem 2020/02/01 06:00:32 (permalink)
    0
    Assert, i.e. start
     
    1. repeat
    2. mask 5 ($1F) i2c flags
    3. until clear
    4. SEN = 1

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #12
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3638
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: PIC18F86J65 I2C problem 2020/02/01 06:07:32 (permalink)
    0
    Write (Databyte):
    1. busy 5 flags
    2. TRN = Databyte
    3. test i2c status register transmit complete flag
    4. wait until clear



     

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #13
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3638
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: PIC18F86J65 I2C problem 2020/02/01 06:19:37 (permalink)
    0
    Read:
    1. busy 5 flags
    2. RCEN = 1
    3. wait until RCEN is clear
    4. data byte is now in receive RCV
    5. ACKDT = 0 if not last, 1 if last
    6. ACKEN = 1
    7. return with RCV

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #14
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 3638
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: online
    Re: PIC18F86J65 I2C problem 2020/02/01 06:35:35 (permalink)
    0
    Writing is easier.
    void i2c_puts(unsigned char ID, unsigned char Addr, void *Dest, int Len);


     
     1. assert start
     2. write device id
     3. write device addr
     4. loop Len {
     5. write *Dest++
     6. Len--
     7.}
     8. assert stop
     
     

    MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
    https://www.youtube.com/watch?v=Iu1qa8N2ID0
    + ST:Continues, "What Ships are Made for", Q's back.
    #15
    Jump to:
    © 2020 APG vNext Commercial Version 4.5