I2C读取错误,但返回结果是正确的

我在尝试读取光照度传感器opt3001的时候

有时候i2c读取错误,但是返回的ret依然是正确的,导致我的光照度值突然跳跃,屏幕亮度突变

bool opt3001_read_lux(opt3001_t *opt3001, float *lux)
{
    rt_uint8_t recv_buf[2];
    rt_err_t ret;
    rt_uint16_t raw_data;
    rt_uint16_t exponent, mantissa;

    if (opt3001 == RT_NULL || lux == RT_NULL)
    {
        return false;
    }

    /* 读取光照度数据寄存器 */
    ret = rt_i2c_mem_read(opt3001->i2c_dev, OPT3001_ADDR, OPT3001_RESULT, 8, recv_buf, 2);
    LOG_D("i2c read reg:0x%x,pdata:0x%x,ret:%d\n", OPT3001_RESULT, *recv_buf, ret);

    // ret = read_regs(opt3001->i2c_dev, 2, recv_buf);
    if (ret == false)
    {
        LOG_E("opt3001 read data register failed!\n");
        return false;
    }

    raw_data = (recv_buf[0] << 8) | recv_buf[1];

    exponent = OPT3001_REG_EXPONENT(raw_data);
    mantissa = OPT3001_REG_MANTISSA(raw_data);

    /* 计算光照度值,单位为lux */
    *lux = mantissa * (0.01 * (1 << exponent));

    return true;
}

错误时候的打印

[2706111] E/drv.i2c tpread: bus err:0, xfer:0/2, i2c_stat:20, i2c_errcode=4
[2706145] E/drv.i2c tpread: reset and send 9 clks
[2712678] D/opt3001 brightne: i2c read reg:0x0,pdata:0x3f,ret:2

这里ret为2,这是为什么,我怀疑是不是有可能是读取错误后,IIC立马重启,又重新读了一次值?

好像读回来的值是对的,之前跳变是驱动里面亮度调节的范围是0-100,我使用0-255向里面写入,引发错误

i2c_errcode=4 是 HAL_I2C_ERROR_AF, 是I2C no ack的错误。

ret 2是因为读取的数据量是2,返回的是读取的数据量,不是rt_err_t 类型。

至于为啥出现i2c错误了,还能返回2,你这有多线程读取的动作吗?看你的log前2条好像是TP读取出现超时,最后一条是brightne这个线程读数据是正常的

[2706111] E/drv.i2c tpread: bus err:0, xfer:0/2, i2c_stat:20, i2c_errcode=4

[2706145] E/drv.i2c tpread: reset and send 9 clks

[2712678] D/opt3001 brightne: i2c read reg:0x0,pdata:0x3f,ret:2

没,我应当只有一条线程在获取时间,但是我也不能保证没有bug,这本身只是为测试光感拼凑的测试代码,按照代码来说只有一个专门的task在做这件事

void bringhtness_task(void *parameter)
{
    opt3001_t opt3001;
    uint8_t brightness;
    uint16_t delay_ms;
    if (!opt3001_init(&opt3001, NULL))
    {
        rt_kprintf("opt3001 init failed\n");
    }
    while (1)
    {
        if(alc_get_cur_brightness(&opt3001, &brightness, &delay_ms))
        {
            // rt_kprintf("Set brightness to %d\n", brightness);
            set_brightness(brightness);
        }
        rt_thread_mdelay(delay_ms);
    }
}

/**
  * @brief  Main program
  * @param  None
  * @retval 0 if success, otherwise failure number
  */
int main(void)
{
    rt_err_t ret = RT_EOK;
    rt_uint32_t ms;

    // hwp_pmuc->PERI_LDO |= PMUC_PERI_LDO_EN_VDD33_LDO3;

    // int pin = GET_PIN(1,9);
    // rt_pin_mode(pin, PIN_MODE_OUTPUT);
    // rt_pin_write(pin, PIN_HIGH);
    // rt_kprintf("Pin %d set to high\n", pin);
    // rt_thread_mdelay(2000);

    /* init littlevGL */
    rt_kprintf("Initializing littlevGL...\n");

    ret = littlevgl2rtt_init("lcd");
    if (ret != RT_EOK)
    {
        return ret;
    }
    lv_ex_data_pool_init();
    // init_pin();

    lv_demo_main();

    rt_thread_t tid = rt_thread_create("brightness_task", bringhtness_task, NULL, 2048, 10, 20);
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid);
    }

    while (1)
    {
        if (rt_mutex_take(lcd_mutex, RT_WAITING_FOREVER) == RT_EOK)
        {
            ms = lv_task_handler();
            rt_thread_mdelay(ms);
            rt_mutex_release(lcd_mutex);
        }
    }
    return RT_EOK;
}

TP的读取本身就是有一个线程的,在drv_touch.c
所以你这个错误,不是光感的I2C读取错误,是TP那边读取出现错误了。正好连着打印了,所以看起来像是光感的错误

OK,简单测试了一下,你是对的,才看到错误头是tpread,是触摸驱动的错误 :roll_eyes: ,混在了一起