PIC16 with MCC: I²C master read with repeated-start condition

Thread Starter


Joined Feb 6, 2020
I am using a PIC16F18875, with MPLAB X / MCC generated library to use I2C as a master.
By default, reading data from a slave will produce a STOP,START pair after the first START and the writing of device address + register number.
Using that, I only get 0xff back from a UCD9090 IC, while other devices on the bus reply more sensibly.
Attaching my raspi to the bus, it reads the 9090 just fine.
The logic analyzer reveals that what the pi does is, put a repeated-start, instead of stop/start.
(Btw.: I checked with the scope that the bus signal is good, e.g. levels are reached, not bent out of shape)

Since that's what the 9090 seems to be happy with, I am now trying to make the MCC I2C lib behave that way when reading.

It was pointed out to me elsewhere that setting the "data complete" callback to an already provided function to "restart read" instead of stop, this could be achieved.
It didn't work out quite as imagined.

Here is what I did:

i2c_error_t i2c_readRegRepeatStart(uint8_t reg, void* data, uint8_t size)
    i2c_error_t ret;   
    m_reg = reg;
    i2c_setBuffer(&m_reg, 1);
    i2c_setDataCompleteCallback( i2c_restartRead, 0 ); // changing default behavior to use repeated-start, not a stop
    ret = i2c_masterOperation(false); // write address and register
    i2c_setDataCompleteCallback( i2c_returnStop, 0 ); // change back to default, to create a STOP at the very end - or so I thought
    if (ret == I2C_NOERR)
        i2c_setBuffer(data, size);
        ret = i2c_masterOperation(true); // read the data bytes
    return (ret);
Now if I call that with a valid register number and size=2, the start of the sequence I see in the logic analyzer starts as intended:
- Start, W Addr, W Register, Repeat start, R Addr, R Data, R Data
Since that's what I wanted to read, I'd expect a STOP next. But that's not what I get:
- an extra 20 times: R Data, with an Ack for each besides the last, which has Nack.
- a stop, start
- address, data, data, STOP.

With a breakpoint in the MCC library's i2c_master.c / i2c_masterOperation(bool read), I look at i2c_status.data_length, and it is 2, as expected. Not 22 or something.

Would anyone have an idea what I did wrong here?

Thread Starter


Joined Feb 6, 2020
This helped. Gave up on using the MCC stuff for this, other than the clicked-together basic peripheral init stuff.
I basically just added a further parameter to indicate whether I want to use stop,start; or restart (aka repeated start condition), making it so that for "restart" the write-block routine omits the STOP at the end, and the read-block routine calls restart() instead of start().
Also note that that code expects left-aligned slave addresses (Lshift 1).