• AVR Freaks

Hot!Slave I2C with PIC16F18313

Author
buddacedcc
Super Member
  • Total Posts : 199
  • Reward points : 0
  • Joined: 2009/02/01 15:39:06
  • Location: Italy
  • Status: offline
2020/11/22 13:59:59 (permalink)
0

Slave I2C with PIC16F18313

First time for me with slave I2C configuration. Problem communication don't work with master. Master (PIC18F) work with other I2C devices (I2C LCD).
For me very terrible problem pic 16F can't work with ICD and simulator can't simulate I2C.
Init Code:
    TrisSDA_PIN = TRUE;

    TrisSCLK_PIN = TRUE;
    
    //I2C
    // initialize the hardware
    // R_nW write_noTX; P stopbit_notdetected; S startbit_notdetected; BF RCinprocess_TXcomplete; SMP High Speed; UA dontupdate; CKE disabled; D_nA lastbyte_address;
    SSP1STAT = 0x00;
    // SSPEN enabled; WCOL no_collision; CKP disabled; SSPM 7 Bit Polling; SSPOV no_overflow;
    SSP1CON1 = 0x26;
    // ACKEN disabled; GCEN enabled; PEN disabled; ACKDT acknowledge; RSEN disabled; RCEN disabled; ACKSTAT received; SEN enabled;
    SSP1CON2 = 0x00;
    // ACKTIM ackseq; SBCDE disabled; BOEN disabled; SCIE disabled; PCIE disabled; DHEN disabled; SDAHT 100ns; AHEN disabled;
    SSP1CON3 = 0x00;
    // SSP1MSK 127;
    SSP1MSK = (I2C1_SLAVE_MASK << 1); // adjust UI mask for R/nW bit
    // SSP1ADD 8;
    SSP1ADD = (I2C1_SLAVE_ADDRESS << 1); // adjust UI address for R/nW bit
 
    // clear the slave interrupt flag
    PIR1bits.SSP1IF = 0;
    // enable the master interrupt
    PIE1bits.SSP1IE = 1;

 
Interrupt :
void interrupt isr(void){ 
    if((PIE1bits.SSP1IE == TRUE) && (PIR1bits.SSP1IF == TRUE))
    {
    BYTE i2c_data = 0x55;

    PIR1bits.SSP1IF = 0; // clear the slave interrupt flag
    i2c_data = SSP1BUF; // read SSPBUF to clear BF
    if((SSP1STATbits.R_nW == TRUE) && (SSP1STATbits.D_nA == FALSE))
    {
        SSP1BUF = sx_input;
    }
    SSP1CON1bits.CKP = 1; // release SCL
       
    }

return;
}

#1

18 Replies Related Threads

    ric
    Super Member
    • Total Posts : 29495
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Slave I2C with PIC16F18313 2020/11/22 14:08:34 (permalink)
    +1 (1)
    Inevitably, when you only post snippets of your code, you leave out much that is important.
    What pins are you using for SDA and SCL ( you don't show the definitions of TrisSDA_PIN or TrisSCLK_PIN)
    Have you done the full PPS setup for those pins (assigning them for both input AND output) ?
    Have you switched those pins from analog mode to digital mode?
     

    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
    BroadwellConsultingInc
    Super Member
    • Total Posts : 99
    • Reward points : 0
    • Joined: 2020/06/09 06:07:55
    • Location: 0
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/22 15:21:14 (permalink)
    0
    If you're using the default I2C handler generated by MCC, you have to call I2C1_Open() once after enabling interrupts in order for any of the I2C stuff to work.  Did you do that?
    #3
    buddacedcc
    Super Member
    • Total Posts : 199
    • Reward points : 0
    • Joined: 2009/02/01 15:39:06
    • Location: Italy
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/22 15:22:39 (permalink)
    0
    ric
    Inevitably, when you only post snippets of your code, you leave out much that is important.
    What pins are you using for SDA and SCL ( you don't show the definitions of TrisSDA_PIN or TrisSCLK_PIN)
    Have you done the full PPS setup for those pins (assigning them for both input AND output) ?
    Have you switched those pins from analog mode to digital mode?

    Thanks for reply :D
    requested code:
        ANSELA = 0;
        PORTA = 0;

        SSP1CLKPPS = 0x05; //RA5->MSSP1:SCL1;
        RA5PPS = 0x18; //RA4->MSSP1:SCL1;
        RA4PPS = 0x19; //RA5->MSSP1:SDA1;
        SSP1DATPPS = 0x04; //RA4->MSSP1:SDA1;

        PPSLOCKbits.PPSLOCKED = TRUE;

     
    #define TrisSDA_PIN TRISAbits.TRISA4

    #define TrisSCLK_PIN TRISAbits.TRISA5

    #4
    buddacedcc
    Super Member
    • Total Posts : 199
    • Reward points : 0
    • Joined: 2009/02/01 15:39:06
    • Location: Italy
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/22 15:26:57 (permalink)
    0
    BroadwellConsultingInc
    If you're using the default I2C handler generated by MCC, you have to call I2C1_Open() once after enabling interrupts in order for any of the I2C stuff to work.  Did you do that?




    I'm using part of MCC but is not present any "I2C1_Open()" only "I2C1_Initialize()" called for I2C register setup.
    #5
    ric
    Super Member
    • Total Posts : 29495
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Slave I2C with PIC16F18313 2020/11/22 15:47:24 (permalink)
    +1 (1)
    buddacedcc
    I'm using part of MCC but is not present any "I2C1_Open()" only "I2C1_Initialize()" called for I2C register setup.

    That's your problem. It doesn't complete the setup until you call I2C1_Open()
    It's unclear if you are showing snippets of MCC code, or stuff you are running yourself.
     

    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
    buddacedcc
    Super Member
    • Total Posts : 199
    • Reward points : 0
    • Joined: 2009/02/01 15:39:06
    • Location: Italy
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/22 15:54:59 (permalink)
    +1 (1)
    ric
    buddacedcc
    I'm using part of MCC but is not present any "I2C1_Open()" only "I2C1_Initialize()" called for I2C register setup.

    That's your problem. It doesn't complete the setup until you call I2C1_Open()
    It's unclear if you are showing snippets of MCC code, or stuff you are running yourself.
     


    Thanks for answer. I'm generating code whit MCC in separate project (MCC too invasive of my point of view) and paste in my project necessary code.
    So my question a this time is in MCC code I don't see any "I2C1_Open()" is a built-in function ???
    #7
    Mysil
    Super Member
    • Total Posts : 4071
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Slave I2C with PIC16F18313 2020/11/22 15:56:00 (permalink)
    +1 (1)
    Hi,
    Check that the MSSP peripheral have actually been Enabled.
    MCC code have a tendency to Not enable the peripheral, and defer that until a I2C_Open(...)
    Edit, yes, shown in message #1.
     
    Also, have the I2C Slave address to listen for, been correctly set?
    Edit, set in message #1.
     
        Mysil
    post edited by Mysil - 2020/11/22 16:03:56
    #8
    buddacedcc
    Super Member
    • Total Posts : 199
    • Reward points : 0
    • Joined: 2009/02/01 15:39:06
    • Location: Italy
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/22 16:08:18 (permalink)
    0
    Mysil
    Hi,
    Check that the MSSP peripheral have actually been Enabled.
    MCC code have a tendency to Not enable the peripheral, and defer that until a I2C_Open(...)

    As snippet code I enabled MSSP as MCC I2C_Open(...) nor present in my MCC (XC8 version ? my 1.45)
    Mysil
    Also, have the I2C Slave address to listen for, been correctly set?



    Great suggestion! ad my stupid error :D
    Master code PIC18F and C18
    Wrong:
    #define SX_I2C1_SLAVE_ADDRESS (0x08 | 0x01)

    Now:
    #define SX_I2C1_SLAVE_ADDRESS ((0x08 << 1) | 0x01)

    "| 0x01" because I have only to read device and set read bit in define.
    Code to read in master:
    StartI2C2();

    S = WriteI2C2(SX_I2C1_SLAVE_ADDRESS); //write the address of slave
    if(S == -1) //check if bus collision happened
    {
        sx_iic_occupancy = SSP2BUF; //upon bus collision detection clear the buffer,
        SSPCON1bits.WCOL=0; // clear the bus collision status bit
    }

    sx_iic_occupancy = ReadI2C2();

    StopI2C2();

     
    So next this fix in master code loop inside "ReadI2C2();", any idea why ?
     
    post edited by buddacedcc - 2020/11/22 16:10:29
    #9
    ric
    Super Member
    • Total Posts : 29495
    • Reward points : 0
    • Joined: 2003/11/07 12:41:26
    • Location: Australia, Melbourne
    • Status: online
    Re: Slave I2C with PIC16F18313 2020/11/22 16:13:05 (permalink)
    +2 (2)
    That test for bus collision is no good.
    If you get a collision (or a NAK), then you have to abandon the entire transaction, you can't just clear the error and keep going.
     

    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!
    #10
    buddacedcc
    Super Member
    • Total Posts : 199
    • Reward points : 0
    • Joined: 2009/02/01 15:39:06
    • Location: Italy
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/22 16:24:24 (permalink)
    0
    ric
    That test for bus collision is no good.
    If you get a collision (or a NAK), then you have to abandon the entire transaction, you can't just clear the error and keep going.

    After your adds modified in:
     
    do
    {
    S = WriteI2C2(SX_I2C1_SLAVE_ADDRESS); //write the address of slave
        if(S == -1) //check if bus collision happened
        {
            sx_iic_occupancy = SSP2BUF; //upon bus collision detection clear the buffer,
            SSPCON1bits.WCOL=0; // clear the bus collision status bit
        }
    }
    while(S!=0); //write untill successful communication
    sx_iic_occupancy = ReadI2C2();

     
    But same problem code looped in ReadI2C2(..) :
      555E A06D BTFSS 0xf6d, 0, ACCESS
      5560 D7FE BRA 0x555e

    "BF: Buffer Full Status bit", buffer not full...not transmission from slave ?
     
    post edited by buddacedcc - 2020/11/22 16:25:31
    #11
    Mysil
    Super Member
    • Total Posts : 4071
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Slave I2C with PIC16F18313 2020/11/22 17:58:12 (permalink)
    +1 (1)
    Hi,
    About test for Bus Collision,
    I have no idea what is hidden inside WriteI2C2(...)
    to detect whether Bus Collision have happened.
    Be aware that Write collision, and Bus collision are two different situations,
    and SSP1CON1bits.WCOL    is not bus collision status bit.
    In 8-bit PIC with MSSP peripheral, the only indication of  Bus Collision, (or Lost Arbitration),
    is the Bus Collision Interrupt Flag   BCL2IF, aka. PIR3bits.BCL2IF.
     
    Although, if there is a bus collision, and do not handle it right, there may be a Write Collision also.
     
    Then in snippet in message #11, why is there:
        WriteI2C2(...)  ;
    and 
        ... = SSP2BUF;
    and then
        SSPCON1bits.WCOL=0;    //  Without instance index ?
    Device support header files may have alias definitions of register names,
    with  SSPCON1  ==  SSP1CON1  beeing the same register
          SSPCON1  is not the same as  SSP2CON1  register.
     
        Mysil
     
    #12
    buddacedcc
    Super Member
    • Total Posts : 199
    • Reward points : 0
    • Joined: 2009/02/01 15:39:06
    • Location: Italy
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/23 00:53:11 (permalink)
    0
    Mysil
          SSPCON1  is not the same as  SSP2CON1  register.



    Very thanks for mistake "note" :D
    #13
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 4014
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/23 07:27:54 (permalink)
    -2 (2)
    If you get a Write Collision or BCL, reset the module and return from interurrpt.
    Master asserts restart condition and re-sends.
     
    A Write Collision should not happen, it means that the Receive Buffer was not read on the last interrupt when RBF was set and still is.  Coding error.
     
    Bus Collision h/w, bus is busy, should test before accessing.
    i.e. Before asserting start, test S bit.
     
    I will be putting an I2C Demo on Youtube soon showing Master and Slave side by side.
    Scanner in action, 7bit and 10bit Chip ID Addressing, reading and writing from/to Master and Slave.
    General Calls: Reset and Receive Slave (as Master) ID.  Interrupts with color Register views like in the PDFs.  Mask Slave Chip ID by external Port Pins.
     
    Don't know if this has been covered, the range of addresses that a slave can have.
     
     7bit    $08 -  $77   240 addresses
    10bit   $000 - $3FF  1024 addresses
     
    All slaves receive start, restart, stop, I2COV and BCL  (Even if not addressed)
     
    Start and Restart Condition resets R_W and D_A to zero so that the device can receive a new address to either read or write depending on if R_W is set in the received address.
     
    The demo will use this RAM Device structure.
    typedef struct{
        i2cslave_t      Base;                   // slave_t
        unsigned char   Cell[MEMSIZE];          // user view, RW, at end of cell set pos 0
        unsigned long   RDCount;                // user view, RD only, count databytes read from memory
        unsigned long   WRCount;                // user view, RD only, count databytes written to memory
        unsigned int    Address;                // user view, RD only, last 16bit ram address read or written
        unsigned char   DataByte;               // user view, RD only, last databyte received or transmitted
        unsigned char   ErrorCode;              // user view, RD, last error code
        unsigned char   Status;                 // user view, RD only, status bits
        unsigned char   Config;                 // user view, RW, configuration bits
        unsigned int    DumpAddress;            // start buffer address
        unsigned int    DumpCount;              // count
        unsigned char   GCDataArea[GCDATASIZE]; // general call data area, receive data bytes
    }I2C_RAM_t;
    // ----------------------------------------------------


    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 : 4014
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/23 07:28:13 (permalink)
    -1 (3)
    If you get a Write Collision or BCL, reset the module and return from interurrpt.
    Master asserts restart condition and re-sends.
     
    A Write Collision should not happen, it means that the Receive Buffer was not read on the last interrupt when RBF was set and still is.  Coding error.
     
    Bus Collision h/w, bus is busy, should test before accessing.
    i.e. Before asserting start, test S bit.
     
    I will be putting an I2C Demo on Youtube soon showing Master and Slave side by side.
    Scanner in action, 7bit and 10bit Chip ID Addressing, reading and writing from/to Master and Slave.
    General Calls: Reset and Receive Slave (as Master) ID.  Interrupts with color Register views like in the PDFs.  Mask Slave Chip ID by external Port Pins.
     
    Don't know if this has been covered, the range of addresses that a slave can have.
     
     7bit    $08 -  $77   240 addresses
    10bit   $000 - $3FF  1024 addresses
     
    All slaves receive start, restart, stop, I2COV and BCL  (Even if not addressed)
     
    Start and Restart Condition resets R_W and D_A to zero so that the device can receive a new address to either read or write depending on if R_W is set in the received address.
     
    The demo will use this RAM Device structure.
    typedef struct{
        i2cslave_t      Base;                   // slave_t
        unsigned char   Cell[MEMSIZE];          // user view, RW, at end of cell set pos 0
        unsigned long   RDCount;                // user view, RD only, count databytes read from memory
        unsigned long   WRCount;                // user view, RD only, count databytes written to memory
        unsigned int    Address;                // user view, RD only, last 16bit ram address read or written
        unsigned char   DataByte;               // user view, RD only, last databyte received or transmitted
        unsigned char   ErrorCode;              // user view, RD, last error code
        unsigned char   Status;                 // user view, RD only, status bits
        unsigned char   Config;                 // user view, RW, configuration bits
        unsigned int    DumpAddress;            // start buffer address
        unsigned int    DumpCount;              // count
        unsigned char   GCDataArea[GCDATASIZE]; // general call data area, receive data bytes
    }I2C_RAM_t;
    // ----------------------------------------------------


    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
    Mysil
    Super Member
    • Total Posts : 4071
    • Reward points : 0
    • Joined: 2012/07/01 04:19:50
    • Location: Norway
    • Status: online
    Re: Slave I2C with PIC16F18313 2020/11/23 09:00:14 (permalink)
    +1 (1)
    Hi,
    Even the mighty Gort have made a mistake
    7bit    $08 -  $77   240 addresses

    Instead:
    7bit addressing:
       0x77 - 0x08 inclusive + 1 = 0x70 give 112 addresses that are available for slave  devices.

     
    Regards,
        Mysil
    #16
    buddacedcc
    Super Member
    • Total Posts : 199
    • Reward points : 0
    • Joined: 2009/02/01 15:39:06
    • Location: Italy
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/23 10:55:31 (permalink)
    0
    Mysil
          SSPCON1  is not the same as  SSP2CON1  register.



    Fixed mistake but loop inside function ReadI2C2(); ...buffer not full. I would like try to stretch clock in slave.
    #17
    buddacedcc
    Super Member
    • Total Posts : 199
    • Reward points : 0
    • Joined: 2009/02/01 15:39:06
    • Location: Italy
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/23 14:33:27 (permalink)
    +3 (3)
    Solved with clock stretch, thanks to all for help!
    #18
    Gort2015
    Klaatu Barada Nikto
    • Total Posts : 4014
    • Reward points : 0
    • Joined: 2015/04/30 10:49:57
    • Location: 0
    • Status: offline
    Re: Slave I2C with PIC16F18313 2020/11/25 16:29:35 (permalink)
    0 (2)
    Yes, the bad math.
     
    128 - 16
     
    Exclude bottom  8  ($00 - $07)
    Exclude top        8  ($78 - $7F)

    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.
    #19
    Jump to:
    © 2021 APG vNext Commercial Version 4.5