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:
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?
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:
C:
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);
}
- 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?