• AVR Freaks

pic18lf57k42 and I2C1

Author
mbrowning
USNA79
  • Total Posts : 1556
  • Reward points : 0
  • Joined: 2005/03/16 14:32:56
  • Location: Melbourne, FL
  • Status: offline
2018/10/08 12:02:00 (permalink)
0

pic18lf57k42 and I2C1

I have a couple of PIC18LF56K42 designs with working I2C Master code (using only I2C1). I copied this code to a new design using 57K42 and both I2C ports. I duplicated the I2C1 code for I2C2 with appropriate changes for register names and port pins. Initialization, and first states of my I2C write state machine are below.
 
Fosc is 64MHz and the I2C clock comes from T6 with 2MHz rollover giving 400KHz SCL. This has worked fine on the 56K42. On the 57K42, I found that I2C2 didn't receive ACKs. I figured with more endpoints, maybe 2.2K pullups were too big, although the scope didn't show obvious issues and I was somewhat skeptical of this.
 
The BIG problem, however, is that I2C1 fails completely at 400KHz. As soon as I2C1CON0bits.S=1; is executed, the I2C bus spits out continuous clocks with SDA carrying repeated data (maybe address, it's physically hard to probe this design). The TXBE bit never goes high and MMA never goes low after .S=1 so state i2c_wr1 never checks for error or writes data to I2C1TXB. I2C1CNT never counts down from 2.
 
A coworker had some MCC generated code that worked. The only significant difference from my code was running the buses at 100KHz. I changed the I2C clock to 500KHz (for 100KHz SCL) and now both I2C buses work fine.
 
56K42 and 57K42 share a datasheet, but perhaps there's some silicon differences besides RAM and Flash. Anyone else seen oddities in I2C operation on the 57K42? I had zero difficulties with the 56K42. I'm going to try other SCL frequencies, and try to look closer at bus on the scope.
 
void init_i2c (void) {
    T6CLK    = 0x01;        // CLK = Fosc/4 (16MHz)
    T6PR     = 7;        // output = 16MHz / (7+1) = 2MHz
    T6HLT    = 0x00;        // pre not sync, rising edge, clk not sync, SW ctrl
    T6CON    = 0x80;        // T6 on, pre 1:1, post 1:1

    I2C1CON0 = 0x04;        // mode 7 bit master
    I2C1CON1 = 0x80;        // ACKCNT=1(nack), ACKDT=0(ack), sck stretch allow
    I2C1CON2 = 0x00;        // ACNT=0 GCEN=0 FME=0 ADB=0 SDAHT 300n, BFRET=0
    I2C1CLK  = 0x08;        // CLK TMR6 post-scaled output (2MHz)
    I2C1CON0 = 0x84;        // I2C Enbld, mode 7 bit master
    I2C1PIR  = 0;        // Clear all the error flags
    I2C1ERR  = 0;

    I2C2CON0 = 0x04;        // mode 7 bit master
    I2C2CON1 = 0x80;        // ACKCNT=1(nack), ACKDT=0(ack), sck stretch allow
    I2C2CON2 = 0x00;        // ACNT=0 GCEN=0 FME=0 ADB=0 SDAHT 300n, BFRET=0
    I2C2CLK  = 0x08;        // CLK TMR6 post-scaled output (2MHz)
    I2C2CON0 = 0x84;        // I2C Enbld, mode 7 bit master
    I2C2PIR  = 0;        // Clear all the error flags
    I2C2ERR  = 0;
}

 
    case i2c_wstart:
        if (I2C1STAT0bits.MMA == 0) {    // if I2C not busy
            I2C1ADB1    = i2c1addr;        // write operation
            I2C1CNT        = 2;            // eeadr (0) + ptr (1) + data (1)
            I2C1CON0bits.S    = 1;        // start the transfer
            PC1IF        = 0;
            I2C1TXB        = i2c1_reg;        // register ptr
            i2c1fault    = 0;
            i2c1_st        = i2c_wr1;
        }
        break;
    case i2c_wr1:
        if (I2C1STAT1bits.TXBE) {
            if (I2C1CON1bits.ACKSTAT == 1) {    // no ack received
                I2C1CNT        = 0;
                I2C1STAT1bits.CLRBF    = 1;        // clear buffer since no ack
                i2c1fault    = 1;
                i2c1_st        = i2c_error;    
            } else {
                I2C1TXB        = i2c1_wval;
                i2c1_st        = i2c_wr2;
            }
        }


Go Navy! Beat Army!
#1

6 Replies Related Threads

    qhb
    Superb Member
    • Total Posts : 9999
    • Reward points : 0
    • Joined: 2016/06/05 14:55:32
    • Location: One step ahead...
    • Status: offline
    Re: pic18lf57k42 and I2C1 2018/10/08 12:26:39 (permalink)
    +1 (1)
    Those chips use PPS for SDA and SCL.
    You didn't show any PPS code, or mention if you are using the default pins.
     

    Nearly there...
    #2
    mbrowning
    USNA79
    • Total Posts : 1556
    • Reward points : 0
    • Joined: 2005/03/16 14:32:56
    • Location: Melbourne, FL
    • Status: offline
    Re: pic18lf57k42 and I2C1 2018/10/09 06:23:34 (permalink)
    0
    I tried a number of I2C clock inputs and both ports can read/write at 320KHz SCL reliably. Higher speeds result in NACKs, and at 400KHz I2C1 goes into crazy mode. I don’t think PPS settings would be the difference from one clock setting to the other, but I checked all configuration code several times before trying the slower clock with success.

    This is my first time writing code for someone else’s PCB. Perhaps there’s some design related problem. I’ll need to review the layout and schematic again. This board has multiple 10Gbit links running with no errors so I2C should be cake.

    Go Navy! Beat Army!
    #3
    coffee critic
    Super Member
    • Total Posts : 378
    • Reward points : 0
    • Status: offline
    Re: pic18lf57k42 and I2C1 2018/10/09 08:49:43 (permalink)
    +1 (1)
    How long are the traces between master and slave?  Do you have a way to measure bus capacitance? 

    n_*$
    #4
    mbrowning
    USNA79
    • Total Posts : 1556
    • Reward points : 0
    • Joined: 2005/03/16 14:32:56
    • Location: Melbourne, FL
    • Status: offline
    Re: pic18lf57k42 and I2C1 2018/10/15 07:08:14 (permalink)
    +2 (2)
    I spent a few days finishing up the rest of the code while running both I2C buses at 320KHz (which worked fine). I tried my colleagues code (MCC based) at 400KHz and even faster and both I2C buses worked. My code at 400KHz however failed on I2C1 (I2C2 worked). The I2C1_bad photo shows the continuous SCL after setting the S bit. The clock never stops, TXBE is never set, and MMA never clears after setting S.
     
    I tracked this down to the RB1I2C and RB2I2C settings. I2C1 pins are RB1 (SCL1) and RB2 (SDA1) and I2C2 pins are RD0 (SCL2) and RD1 (SDA2). The four I2C Pad Control Registers for these pins were set to 0x41 (I2C specific slew enabled, I2C specific input thresholds).
     
    I found that if both RB1I2C and RB2I2c have bit 6 set (enabling I2C specific slew), then the result is the "bad" photo. If either registers have bit 6 cleared, then the result is the "good" photo (write to I2C address 0x22, register 0x3E, data 0xF7).
     
    I2C2 doesn't seem affected by these bits, but I2C1 won't run above about 340Khz with both these bits set.
     
    Well, I know what to do to make my code work, and I'll be reporting this to Microchip to see what they say.
     
     edit - sorry about the upside down pictures. I thought I had fixed it, but the forum still displays them upside down. Also, I know that SDA doesn't look great. I used a good probe with the witch hat and a 1" wire for SCL, but an ungrounded probe with a 2ft clip wire for SDA.
    post edited by mbrowning - 2018/10/15 07:13:02

    Attached Image(s)


    Go Navy! Beat Army!
    #5
    coffee critic
    Super Member
    • Total Posts : 378
    • Reward points : 0
    • Status: offline
    Re: pic18lf57k42 and I2C1 2018/10/15 15:40:44 (permalink)
    0
    Interesting information.  I can't tell from the picture.  Was the bottom of the clock pulse rounded with slew bit on? The top should be totally controlled by the value of the pullup resistors. 

    n_*$
    #6
    mbrowning
    USNA79
    • Total Posts : 1556
    • Reward points : 0
    • Joined: 2005/03/16 14:32:56
    • Location: Melbourne, FL
    • Status: offline
    Re: pic18lf57k42 and I2C1 2018/10/15 23:33:48 (permalink)
    +1 (1)
    The data line is distorted by lousy probing. If I switch the probes the clock looks bad. We make $25,000 boards but can’t afford new oscilloscope probes :)

    Go Navy! Beat Army!
    #7
    Jump to:
    © 2019 APG vNext Commercial Version 4.5