Hi Robert,
- Divider table change in SDK 2.0
About the divider table, we have simplified it in SDK 2.0, because we found that the table({ICR, SCL divider}) is {0x00, 20}, {0x01, 22}, {0x02, 24},{0x03, 26}....., which shows that the ICR is increasing by 1 at each time. So we remove the ICR from the table and make the ICR as index of table(s_i2cDividerTable) only containing SCL divider {20,22,24,26....}, an example: s_i2cDividerTable[0] = 20, s_i2cDividerTable[1] = 22, now the index (0, 1....) is just the ICR. That's why there is following code:
if (absError < bestError)
{
bestMult = mult;
bestIcr = i; /* the index of the s_i2cDriverTable is ICR. */
bestError = absError;
/* If the error is 0, then we can stop searching because we won't find a better match. */
if (absError == 0)
{
break;
}
}
The I2C is using bus clock for K64 clock driver, I do not have such issue running the K64F I2C examples , may you please try the i2c_read_accel_value_transfer example?
- Code issue in your application
I have went through your code and found an issue here, that's why the data you saw on the scope is not right:
The I2C_MasterStart is an non-blocking API, which means calling the API just check whether the bus is busy, if it's not busy, just send out a start signal and the address to the I2C->D register, and the API directly returns without waiting for the addess sent. If user use such functional API, user needs to wait until the address sent mannually in the application, so the right calling flow for your application shoud be
status= I2C_MasterStart(I2C0, address, kI2C_Write);
/* Return if error. */
if (status != kStatus_Success)
{
return status;
}
uint8_t hw_status;
/* Wait until address transfer complete. */
while (!((hw_status = I2C0->S) & kI2C_IntPendingFlag))
{
}
/* Check if there's error during address transfer. */
if (hw_status & kI2C_ArbitrationLostFlag)
{
/* Clear arbitration lost flag. */
I2C0->S = kI2C_ArbitrationLostFlag;
status = kStatus_I2C_ArbitrationLost;
}
/* Check NAK */
else if (hw_status & kI2C_ReceiveNakFlag)
{
status = kStatus_I2C_Nak;
}
if (status != kStatus_Success)
{
I2C_MasterStop(I2C0);
}
I2C_MasterWriteBlocking(I2C0, txBuff, txSize);
.......
And I strongly suggest you to just call an I2C_MasterTransferBlocking to ease your application.
status_t I2C::send(uint8_t address, const uint8_t *txBuff, size_t txSize) const {
i2c_master_transfer_t masterXfer;
memset(&masterXfer, 0, sizeof(masterXfer));
masterXfer.slaveAddress = address;
masterXfer.direction = kI2C_Write;
masterXfer.subaddress = 0;
masterXfer.subaddressSize = 0;
masterXfer.data = txBuff;
masterXfer.dataSize = txSize;
masterXfer.flags = kI2C_TransferDefaultFlag;
return I2C_MasterTransferBlocking(I2C0, masterXfer);
}