Trying to start i2c communication on dspic33fj128gp802, but I cannot write on the SEN bit of the I2CxCON register

i2cpicregister

Good evening,
I was trying to start the communication with the I2C on my pic. I only set the bits in the control register in the code for now and the inizialization of both the pins and the PLL, and I found that the lower 4 bits( RCEN, PEN, RSEN and SEN) could not be written.
Since I cannot write on the SEN bit, the clock does not start. Also, I am setting the register so the device operates as master.

Here is my code:

int main(void)
{
InitOsc();
InitPin();
InitTimer4();
InitTimer5();   


MCUinit();  //initialization MLX

//enable I2c
I2C1CONbits.I2CEN=1;    
I2C1CONbits.I2CSIDL=0; //continues operation in idle
I2C1CONbits.SCLREL=1; // releases clock
I2C1CONbits.IPMIEN=0;   //ipmi should be disabled when operating as master
I2C1CONbits.A10M=0; // slave address are 7-bits
I2C1CONbits.DISSLW=1;   //slew rate control bit enabled
I2C1CONbits.SMEN=0; //disables smbus imput threshold (!!)
I2C1CONbits.ACKDT=0;
I2C1CONbits.ACKEN=1;

// Apparently no effect from here on! If I set a breakpoint here and track
// the variables none of these are on even for a single clock cycle!
I2C1CONbits.RCEN=1;
I2C1CONbits.PEN=1;
I2C1CONbits.RSEN=1; 
I2C1CONbits.SEN=1;

return 0;
}

Is there anything I am doing wrong? I am quite a beginner with this microcontroller, so any explanation would be of use.

I tested the SCL channel with an oscilloscope and nothing at all comes out of that, just stays at a flat 0V signal.

Thank you!

Best Answer

Firstly, the PIC micro-controller's I2C module does not support command queuing (hence brhans' comment). You must verify that the last operation completed before starting the next operation.

e.x. (note that the register names for the interrupt flags will need to be rechecked for this PIC as this was adapted from another PIC's code)

//Pre clear the intterupt flag
IFS1bits.MI2C1IF = 0;

//Send the start condition
I2C1CONbits.SEN = 1;

//Wait for the start condition to complete
while (!IFS1bits.MI2C1IF);
IFS1bits.MI2C1IF = 0;

//Send the I2C address
I2C1TRN = I2C_ADDR;

//Wait for the send to complete and check that the node acknowledged
while (!IFS1bits.MI2C1IF);
IFS1bits.MI2C1IF = 0;

if (I2C1STATbits.ACKSTAT)
    return 0; //ERROR, node did not acknowledge!!!

...

Secondly, as Majenko correctly pointed out, you do not seem to configure the baud rate generator (I2C1BRG). It may be in an invalid state were the I2C module cannot successfully complete an operation.