I²C clock problem
Posted: Fri Jan 18, 2019 10:09 am
I have some problems with I²2 when I communicating with a battery gauge-IC BQ35100. I am using a ESP-Wroom-32D with ESP-IDF 3.2
If I set the I²2 clock frequency to 100KHz or 400KHz I will get I²C timeouts all the time when reading.
What I have seen is that the clock is not consistent and varies during a single byte transfer and it does not look like a slave clock stretch. The application is only doing this and i have also tried running the I²C communication in a separate task on different cores.
Here is a recording with a logic analyzer with 100KHz clock. The marking circle to the right shows a strange behavior. The clock is 893KHz! See the the zoomed in picture below.
If I use 10KHz as I²C clock it work most of the time.
External pull-ups is used. Tried with both 10K and 2.2KOhm. Henceforth I will use 2.2KOhm because the BQ35100 requires maximum rise time of 300ns.
My reading routine is as follow:
If I set the I²2 clock frequency to 100KHz or 400KHz I will get I²C timeouts all the time when reading.
What I have seen is that the clock is not consistent and varies during a single byte transfer and it does not look like a slave clock stretch. The application is only doing this and i have also tried running the I²C communication in a separate task on different cores.
Here is a recording with a logic analyzer with 100KHz clock. The marking circle to the right shows a strange behavior. The clock is 893KHz! See the the zoomed in picture below.
If I use 10KHz as I²C clock it work most of the time.
External pull-ups is used. Tried with both 10K and 2.2KOhm. Henceforth I will use 2.2KOhm because the BQ35100 requires maximum rise time of 300ns.
My reading routine is as follow:
Code: Select all
esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t slave_address, uint8_t register_address, uint8_t* data_rd, size_t size)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
if (register_address!= -1) {
i2c_master_write_byte(cmd, slave_address << 1 | I2C_MASTER_WRITE, I2C_ACK_CHECK_EN);
i2c_master_write_byte(cmd, register_address, I2C_ACK_CHECK_EN);
i2c_master_start(cmd);
}
i2c_master_write_byte(cmd, slave_address << 1 | I2C_READ_BIT, I2C_ACK_CHECK_EN);
if (size > 1) {
i2c_master_read(cmd, data_rd, size - 1, I2C_ACK_VAL);
}
i2c_master_read_byte(cmd, data_rd + size - 1, I2C_NACK_VAL);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 100000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK)
ESP_LOGE(TAG, "i2c error: %s", esp_err_to_name(ret));
return ret;
}