I've found that I2C_RTOS_Transfer does not send a Stop if dataSize is 0.
Am I doing something wrong or is there a bug is the API?
I'm using a Sensirion SHT 21 (datasheet).
One of the command available is to send a soft reset (easily explained via screen shot from the data sheet).
My I2C is configured as follows:
status_t status;
i2c_master_config_t i2c_master_config;
uint32_t i2c_source_clock_hz;
I2C_MasterGetDefaultConfig(&i2c_master_config);
i2c_master_config.baudRate_Bps = 10000;
i2c_master_config.enableMaster = false;
i2c_source_clock_hz = CLOCK_GetFreq(kCLOCK_CoreSysClk);
CLOCK_EnableClock(kCLOCK_I2c0);
status = I2C_RTOS_Init(&i2c_rtos_handle, I2C0, &i2c_master_config,
i2c_source_clock_hz);
/* Disable I2C module and gate its clock */
I'm sending a soft reset in the following manner:
static void soft_reset_sht(void)
{
i2c_master_transfer_t i2c_soft_reset;
i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
i2c_soft_reset.direction = kI2C_Write;
i2c_soft_reset.subaddress = SHT_SOFT_RESET;
i2c_soft_reset.subaddressSize = 1;
i2c_soft_reset.data = NULL;
i2c_soft_reset.dataSize = 0;
i2c_soft_reset.flags = kI2C_TransferDefaultFlag;
I2C_Enable(I2C0, true);
I2C_RTOS_Transfer(&i2c_rtos_handle, &i2c_soft_reset, CEIL_US_TO_TICKS(MS_TO_US(100)) );
// Disable I2C hardware
I2C_Enable(I2C0, false);
return;
}
This doesn't' send a stop command and leaves SCL low:
If I add in some dummy data and send a send it (i.e. i2c_soft_reset.dataSize is not set to zero) the an I2C stop is correctly sent.
static void soft_reset_sht(void)
{
i2c_master_transfer_t i2c_soft_reset;
uint8_t local_u8_buffer[1];
i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
i2c_soft_reset.direction = kI2C_Write;
i2c_soft_reset.subaddress = SHT_SOFT_RESET;
i2c_soft_reset.subaddressSize = 1;
i2c_soft_reset.data = local_u8_buffer;
i2c_soft_reset.dataSize = 1;
i2c_soft_reset.flags = kI2C_TransferDefaultFlag;
I2C_Enable(I2C0, true);
I2C_RTOS_Transfer(&i2c_rtos_handle, &i2c_soft_reset, CEIL_US_TO_TICKS(MS_TO_US(100)) );
I2C_Enable(I2C0, false);
return;
}
This gives
Solved! Go to Solution.
Hi Ben,
For the I2C driver to work properly (ie, send stop to complete transfer), at least 1 data byte need to be there, when using a subaddress. So, for transmitting only 1 data byte (as in your case), use data to send the byte and give no subaddress. Like this:
i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
i2c_soft_reset.direction = kI2C_Write;
i2c_soft_reset.subaddress = 0;
i2c_soft_reset.subaddressSize = 0;
i2c_soft_reset.data = SHT_SOFT_RESET;
i2c_soft_reset.dataSize = 1;
i2c_soft_reset.flags = kI2C_TransferDefaultFlag;
Regards,
Visakhan
Hi Ben,
For the I2C driver to work properly (ie, send stop to complete transfer), at least 1 data byte need to be there, when using a subaddress. So, for transmitting only 1 data byte (as in your case), use data to send the byte and give no subaddress. Like this:
i2c_soft_reset.slaveAddress = SENSIRION_I2C_ADDRESS;
i2c_soft_reset.direction = kI2C_Write;
i2c_soft_reset.subaddress = 0;
i2c_soft_reset.subaddressSize = 0;
i2c_soft_reset.data = SHT_SOFT_RESET;
i2c_soft_reset.dataSize = 1;
i2c_soft_reset.flags = kI2C_TransferDefaultFlag;
Regards,
Visakhan