风起
1
我在尝试读取光照度传感器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立马重启,又重新读了一次值?
风起
2
好像读回来的值是对的,之前跳变是驱动里面亮度调节的范围是0-100,我使用0-255向里面写入,引发错误
yxhuang
3
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
风起
4
没,我应当只有一条线程在获取时间,但是我也不能保证没有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那边读取出现错误了。正好连着打印了,所以看起来像是光感的错误
风起
6
OK,简单测试了一下,你是对的,才看到错误头是tpread,是触摸驱动的错误
,混在了一起