I2C Read problem

jenya7
Posts: 19
Joined: Mon Feb 24, 2020 9:14 am

I2C Read problem

Postby jenya7 » Fri Mar 13, 2020 10:42 am

I want to read/write bno055
  1. s8 BNO055_I2C_bus_write(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
  2. {
  3.     i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  4.     i2c_master_start(cmd);
  5.     i2c_master_write_byte(cmd, (dev_addr << 1) | WRITE_BIT, ACK_CHECK_EN);
  6.     i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN);
  7.     i2c_master_write_byte(cmd, *reg_data, ACK_CHECK_EN);
  8.  
  9.     i2c_master_stop(cmd);
  10.  
  11.     esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS); //1000
  12.     i2c_cmd_link_delete(cmd);
  13.  
  14.     ets_delay_us(10000);
  15.  
  16.     return ret;
  17. }
  18.  
  19. s8 BNO055_I2C_bus_read(u8 dev_addr, u8 reg_addr, u8 *reg_data, u8 cnt)
  20. {
  21.     int ret;
  22.     int i;
  23.  
  24.     i2c_cmd_handle_t cmd = i2c_cmd_link_create();
  25.  
  26.     //first - write a pointer to a register
  27.     i2c_master_start(cmd);
  28.     i2c_master_write_byte(cmd, (dev_addr << 1) | WRITE_BIT, ACK_CHECK_EN);
  29.     i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN);
  30.     i2c_master_stop(cmd);
  31.  
  32.     //second - read from the pointer
  33.     ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);
  34.     i2c_cmd_link_delete(cmd);
  35.  
  36.     //if (ret != ESP_OK)
  37.         //return ret;
  38.  
  39.     cmd = i2c_cmd_link_create();
  40.     i2c_master_start(cmd);
  41.     i2c_master_write_byte(cmd, dev_addr << 1 | READ_BIT, ACK_CHECK_EN);
  42.  
  43.     if (cnt > 1)
  44.     {
  45.         for (i = 1; i < cnt; i++)
  46.         {
  47.             i2c_master_read_byte(cmd, reg_data, ACK_VAL);
  48.             reg_data++;
  49.         }
  50.         i2c_master_read_byte(cmd, reg_data, NACK_VAL);
  51.     }
  52.     else
  53.         i2c_master_read_byte(cmd, reg_data, NACK_VAL);
  54.  
  55.     i2c_master_stop(cmd);
  56.  
  57.     ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_RATE_MS);  //1000
  58.  
  59.     i2c_cmd_link_delete(cmd);
  60.  
  61.     return ret;
  62. }
And I check
  1. BNO055_I2C_bus_read(BNO055_I2C_ADDR1, BNO055_CHIP_ID_REG, &val, 1);
  2. printf("CHIP ID %X\n", val);
But I have a wrong reading from the chip. May be I do something wrong in I2C read/write routines?

markkuk
Posts: 38
Joined: Wed Mar 27, 2019 11:50 am

Re: I2C Read problem

Postby markkuk » Sat Mar 14, 2020 9:01 am

The read should be a single command, not two separate ones. This is the code I'm using:

Code: Select all

/**
 * Read a block of data from an I2C device.
 * @param dev_id    I2C address of device
 * @param reg_addr  register number where read starts
 * @param reg_data  pointer to buffer where read data is stored
 * @param len       number of bytes to read
 * @return Zero for success, non-zero for error
 */
int8_t user_i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
    if (len == 0) {
        return 0;
    }
    esp_err_t rslt = ESP_OK;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (dev_id << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, reg_addr, ACK_CHECK_EN);
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (dev_id << 1) | I2C_MASTER_READ, ACK_CHECK_EN);
    if (len > 1) {
        i2c_master_read(cmd, reg_data, len - 1, I2C_MASTER_ACK);
    }
    i2c_master_read_byte(cmd, reg_data + len - 1, I2C_MASTER_NACK);
    i2c_master_stop(cmd);
    rslt = i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(1000));
    if (rslt != ESP_OK) {
        ESP_LOGE(TAG, "Error on I2C read: (%x) %s ", rslt, esp_err_to_name(rslt));
    }
    i2c_cmd_link_delete(cmd);
    return rslt;
}

jenya7
Posts: 19
Joined: Mon Feb 24, 2020 9:14 am

Re: I2C Read problem

Postby jenya7 » Sun Mar 15, 2020 2:26 pm

Thank you!

Who is online

Users browsing this forum: No registered users and 85 guests