PIC 24F I2C slave issue

1.1k views Asked by At

PIC 24F as an I2C slave has lock up issues sending multiple data bytes to the master (MASTER READ).

The PIC (specifically 24FJ128GB202) as an I2C slave receiving data (MASTER WRITE) works perfectly, passing all unit tests. (address only, address and register, address register single data and multiple data auto increment)

My slave code can handle address-only and reading a single byte. It hangs on multiple reads made from the master (auto increment).

I used the Microchip app note as the basis of my code, as well as looking at the Code Composer generated code.

Initialization:

void I2C1_Initialize(void)
{
    I2C1ADD = I2C1_SLAVE_ADDRESS;
    I2C1MSK = I2C1_SLAVE_MASK;

    I2C1CONL = 0x8200;
    I2C1CONH = 0x0000;
    I2C1STAT = 0x0000;

    // clear the master interrupt flag
    IFS1bits.SI2C1IF = 0;
    // enable the master interrupt
    IEC1bits.SI2C1IE = 1;

}

Interrupt Write:

// clear the interrupt
_SI2C1IF = 0;

// Write from Master to Slave - Address
// S = 1, D_A = 0, R_W = 0, BF = 1
if  ( (I2C1STATbits.S == 1) && (I2C1STATbits.D_A == 0) && (I2C1STATbits.R_W == 0) && (I2C1STATbits.RBF == 1) )
    {
    myI2CAd = I2C1RCV;
    mySTATE = 0;
    }

// Write from Master to Slave - Data
// S = 1, D_A = 1, R_W = 0, BF = 1
if  ( (I2C1STATbits.S == 1) && (I2C1STATbits.D_A == 1) && (I2C1STATbits.R_W == 0) && (I2C1STATbits.RBF == 1))
    {
    mySTATE++;     
    if(mySTATE == 1)
        {
        myREGISTER = I2C1RCV;
        // limit register to MAX
        if(myREGISTER > I2CMAXREGISTER) myREGISTER = I2CMAXREGISTER;
        }
    if(mySTATE == 2)
        {
        myDATA = I2C1RCV;
        shelfregister[myREGISTER] = myDATA;
        }
    if(mySTATE > 2)
        {
        myDATA = I2C1RCV;
        // limit register to MAX
        if(myREGISTER < I2CMAXREGISTER) myREGISTER++;
        shelfregister[myREGISTER] = myDATA;
        }
    }

Interrupt Read:

// Read from Slave to Master - Address
// S = 1, D_A = 0, R_W = 1, BF = 0
if  ( (I2C1STATbits.S == 1) && (I2C1STATbits.D_A == 0) && (I2C1STATbits.R_W == 1) && (I2C1STATbits.TBF == 0) )
    {
    myI2CAd = I2C1RCV;
    I2C1TRN = shelfregister[myREGISTER];
    I2C1CONLbits.SCLREL = 1;
    if(myREGISTER < I2CMAXREGISTER) myREGISTER++;
    }

The code generated by the Code Composer for slave operation is quite similar and has the same issue.

My main question is how to handle multiple reads from the master, not just the single byte that is handled in this read function. It should involve checking I2CSTATbits.ACKSTAT, but the timing of that bit is unclear to me since it should happen 9 clocks after the byte is in the register, but there is no bit to indicate that point in time. Any guidance appreciated.

0

There are 0 answers