Page 1 of 2
低功耗设备使用硬件i2c驱动异常
Posted: 2024年 Mar 19日 21:19
by hzb
SDK版本:TLSR8258_TuyaOS-3.8.0
低功耗设备("dev_role":"sleep_end_dev"),在使用硬件i2c时,通过drv_i2c_read_series读取aht20传感器温湿度,发现读取失败(读取缓存pst->ReadByte全是0),但是通过逻辑分析仪抓取波形,是正常的。并且在代码原封不动的情况下,将appconfig.json中"dev_role"配置从改为"router",读取就正常了,数据也是对的。请问低功耗设备如何使用硬件i2c设备(尝试在__tuya_post_sleep_cb中重新初始化i2c和gpio配置(具体如下,还是不行):
Code: Select all
VOID_T __tuya_post_sleep_cb(VOID_T)
{
tal_main_debug("post_sleep_cb!!!\r\n");
drv_i2c_master_init(100000);
drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1);
}
BOOL_T tkl_gpio_output_use_wakeup_mode(TUYA_GPIO_NUM_E pin_id)
{
if((TUYA_GPIO_NUM_16 == pin_id) || (TUYA_GPIO_NUM_17 == pin_id) || (GPIO_APP_NET_LED == pin_id)){
return TRUE;
}
else
{
return FALSE;
}
}
I2C代码主要摘录如下:
Code: Select all
#define AHT20_SAMPLE_PERIOD 5000 //单位:ms, 且不小于MinReadTim
/* I2C Clock */
#define I2C_CLOCK 100000//100K
/* I2C slave ID */
#define I2C_SLAVE_ID 0x38
#define I2C_SLAVE_ADDR_LEN 1
#define ATH20_ADDR 0x38
#define AHT20_STATUS_REG 0x00 //状态字 寄存器地址
#define AHT20_INIT_REG 0xBE //初始化 寄存器地址
#define AHT20_SOFTRESET_REG 0xBA //软复位 单指令
#define AHT20_MEASURE_REG 0xAC //触发测量 寄存器地址
#define SENSOR_IDLE 0 //
#define SENSOR_MEASURE 1 //
#define SENSOR_COMPLETE 2 //
//****************************************
// 定义 AHT20 内部地址
//****************************************
#define ATH20_ADDR 0x38
#define AHT20_STATUS_REG 0x00 //状态字 寄存器地址
#define AHT20_INIT_REG 0xBE //初始化 寄存器地址
#define AHT20_SOFTRESET_REG 0xBA //软复位 单指令
#define AHT20_MEASURE_REG 0xAC //触发测量 寄存器地址
/*----------------------------------------------------------------------------
Section: Type Definitions
----------------------------------------------------------------------------*/
typedef struct
{
unsigned char Adrr;
unsigned int timcnt;
unsigned char ErrFlag;
unsigned char Step;
unsigned int SetRTim;
unsigned char SendByte[16];
unsigned char ReadByte[16];
float RH;//湿度
float T;//温度
}MYI2C_Struct;
static MYI2C_Struct SENx;
static TIMER_ID aht20_etimerid;
static TIMER_ID aht20_sample_etimerid;
/*******************************************************************************
* Function Name :
* Description :
* Input :None
* Output :None
* Return :None
*******************************************************************************/
static void MYI2C_Handle(TIMER_ID timer_id, VOID_T *arg)
{
MYI2C_Struct *pst = (MYI2C_Struct *)arg;
pst->Step = SENSOR_IDLE;
tal_sw_timer_start(aht20_sample_etimerid, 10, TAL_TIMER_ONCE);
//tkl_cpu_force_wakeup();
}
static void aht20_measure_handle(TIMER_ID timer_id, VOID_T *arg)
{
unsigned char i;
unsigned long s32x;
MYI2C_Struct *pst = (MYI2C_Struct *)arg;
TAL_PR_DEBUG("[%s] step = %d", __FUNCTION__, pst->Step);
if(pst->Step == SENSOR_IDLE)
{
pst->SendByte[0]=0x33;
pst->SendByte[1]=0x00;
drv_i2c_write_series((I2C_SLAVE_ID<<1) | 0, AHT20_MEASURE_REG, I2C_SLAVE_ADDR_LEN, pst->SendByte, 2);
pst->Step = SENSOR_MEASURE;
//TODO: 开启定时器等待75ms测量完成
tal_sw_timer_start(aht20_sample_etimerid, 100, TAL_TIMER_ONCE);
}
else if(pst->Step == SENSOR_MEASURE)
{
pst->Step=SENSOR_COMPLETE;
drv_i2c_read_series((I2C_SLAVE_ID<<1)|1, 0,I2C_SLAVE_ADDR_LEN, pst->ReadByte, 7);
/* 换算温度和湿度 */
if(pst->ErrFlag==0)
{
//if((CheckCrc8(&pst->ReadByte[0],6)==pst->ReadByte[6])&&((pst->ReadByte[0]&0x98) == 0x18))
{
s32x=pst->ReadByte[1];s32x=s32x<<8;s32x+=pst->ReadByte[2];s32x=s32x<<8;s32x+=pst->ReadByte[3];s32x=s32x>>4;
pst->RH=s32x;
pst->RH=pst->RH*100/1048576;
s32x=pst->ReadByte[3]&0x0F;s32x=s32x<<8;s32x+=pst->ReadByte[4];s32x=s32x<<8;s32x+=pst->ReadByte[5];
pst->T=s32x;
pst->T=pst->T*200/1048576-50;
}
TAL_PR_DEBUG("pst->ReadByte: %02x-%02x-%02x-%02x-%02x-%02x-%02x", pst->ReadByte[0], pst->ReadByte[1], pst->ReadByte[2],\
pst->ReadByte[3], pst->ReadByte[4], pst->ReadByte[5], pst->ReadByte[6]);
TAL_PR_DEBUG("temp = %.2f, humi = %.2f", pst->T, pst->RH);
}
else
{
pst->RH=0;
pst->T=0;
}
//tkl_cpu_allow_sleep();
}
}
int app_aht20_init(void)
{
drv_i2c_master_init(I2C_CLOCK);
drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1);
SENx.Adrr = ATH20_ADDR;
SENx.Step = SENSOR_IDLE;
//SENx.SetRTim=AHT20_SAMPLE_PERIOD;
WaitMs(40);
/* 定时启动读取温湿度用 */
OPERATE_RET ret = tal_sw_timer_create(MYI2C_Handle, &SENx, &aht20_etimerid);
if(ret != OPRT_OK)
{
TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__);
return ret;
}
/* 温湿度采集时动作延迟用 */
ret = tal_sw_timer_create(aht20_measure_handle, &SENx, &aht20_sample_etimerid);
if(ret != OPRT_OK)
{
TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__);
return ret;
}
//
ret = tal_sw_timer_start(aht20_etimerid, AHT20_SAMPLE_PERIOD, TAL_TIMER_CYCLE);
if(ret != OPRT_OK)
{
TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__);
return ret;
}
return 0;
}
附件图片:
1.异常情况下,逻辑分析仪抓到的波形正常
2.router配置时正常读取
3. sleep_end_dev配置时,读取异常
Re: 低功耗设备使用硬件i2c驱动异常
Posted: 2024年 Mar 19日 21:20
by hzb
Re: 低功耗设备使用硬件i2c驱动异常
Posted: 2024年 Mar 21日 16:57
by huanghuan
1.你好,低功耗设备如果不进去休眠硬件iic与router的库执行部分是一样的;建议你在 last init中调用 tkl_cpu_force_wakeup();并确保不调用 allow sleep 确认下不进入休眠的话 硬件iic是否功能正常
2.sdk有check兜底防止急速耗电机制,超过2min不进入休眠会自动重启一次,我们先确认是否是由于进入休眠导致的功能问题
Re: 低功耗设备使用硬件i2c驱动异常
Posted: 2024年 Mar 21日 19:48
by hzb
尝试了在tuya_init_last中调用tkl_cpu_force_wakeup,还是不正常,代码如下:
Code: Select all
OPERATE_RET tuya_init_last(VOID_T)
{
tal_main_debug("/*********last init4*********/\r\n");
// __tuya_uart_debug_init();
sys_init_finish_flag = TRUE;
__tuya_gpio_init();
__tuya_led_init();
__tuya_battery_init();
//heartbeat config
tal_heartbeat_type_set(HEARTBEAT_BATTERY_VOLTAGE);
tal_heartbeat_period_set(3 * 60 * 60 * 1000);//3小时
tal_heartbeat_start();
if(app_illuminance_init() != OPRT_OK)
{
tal_main_debug("app_illuminance_init failed\r\n");
}
if(app_sensor_init() != OPRT_OK)
{
tal_main_debug("app_sensor_init failed\r\n");
}
if(app_aht20_init() != OPRT_OK)
{
tal_main_debug("app_aht20_init failed\r\n");
}
app_dpid_init();
//#endif
tal_sw_timer_start(power_on_event_id, 0, TAL_TIMER_ONCE);
tkl_cpu_force_wakeup();
return OPRT_OK;
}
Re: 低功耗设备使用硬件i2c驱动异常
Posted: 2024年 Mar 21日 20:01
by hzb
感觉调用了tkl_cpu_force_wakeup();还是会睡眠,因为根据打印信息看执行到tuya_init_last后,还是会打印tuya_post_sleep_cb中的tal_main_debug("post_sleep_cb!!!\r\n");, 并且如果没有在tuya_post_sleep_cb中重新初始化i2c驱动drv_i2c_master_init(100000);drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1);,连模组发出的i2c波形都没了。
Code: Select all
VOID_T __tuya_post_sleep_cb(VOID_T)
{
tal_main_debug("post_sleep_cb!!!\r\n");
drv_i2c_master_init(100000);
drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1);
}
Re: 低功耗设备使用硬件i2c驱动异常
Posted: 2024年 Mar 21日 21:03
by iot_man
下面这样试试:
Code: Select all
#define AHT20_SAMPLE_PERIOD 5000 //单位:ms, 且不小于MinReadTim
/* I2C Clock */
#define I2C_CLOCK 100000//100K
/* I2C slave ID */
#define I2C_SLAVE_ID 0x38
#define I2C_SLAVE_ADDR_LEN 1
#define ATH20_ADDR 0x38
#define AHT20_STATUS_REG 0x00 //状态字 寄存器地址
#define AHT20_INIT_REG 0xBE //初始化 寄存器地址
#define AHT20_SOFTRESET_REG 0xBA //软复位 单指令
#define AHT20_MEASURE_REG 0xAC //触发测量 寄存器地址
#define SENSOR_IDLE 0 //
#define SENSOR_MEASURE 1 //
#define SENSOR_COMPLETE 2 //
//****************************************
// 定义 AHT20 内部地址
//****************************************
#define ATH20_ADDR 0x38
#define AHT20_STATUS_REG 0x00 //状态字 寄存器地址
#define AHT20_INIT_REG 0xBE //初始化 寄存器地址
#define AHT20_SOFTRESET_REG 0xBA //软复位 单指令
#define AHT20_MEASURE_REG 0xAC //触发测量 寄存器地址
/*----------------------------------------------------------------------------
Section: Type Definitions
----------------------------------------------------------------------------*/
typedef struct
{
unsigned char Adrr;
unsigned int timcnt;
unsigned char ErrFlag;
unsigned char Step;
unsigned int SetRTim;
unsigned char SendByte[16];
unsigned char ReadByte[16];
float RH;//湿度
float T;//温度
}MYI2C_Struct;
static MYI2C_Struct SENx;
static TIMER_ID aht20_etimerid;
static TIMER_ID aht20_sample_etimerid;
/*******************************************************************************
* Function Name :
* Description :
* Input :None
* Output :None
* Return :None
*******************************************************************************/
static void MYI2C_Handle(TIMER_ID timer_id, VOID_T *arg)
{
MYI2C_Struct *pst = (MYI2C_Struct *)arg;
pst->Step = SENSOR_IDLE;
tal_sw_timer_start(aht20_sample_etimerid, 10, TAL_TIMER_ONCE);
//tkl_cpu_force_wakeup();
}
static void aht20_measure_handle(TIMER_ID timer_id, VOID_T *arg)
{
unsigned char i;
unsigned long s32x;
MYI2C_Struct *pst = (MYI2C_Struct *)arg;
TAL_PR_DEBUG("[%s] step = %d", __FUNCTION__, pst->Step);
if(pst->Step == SENSOR_IDLE)
{
pst->SendByte[0]=0x33;
pst->SendByte[1]=0x00;
drv_i2c_write_series((I2C_SLAVE_ID<<1) | 0, AHT20_MEASURE_REG, I2C_SLAVE_ADDR_LEN, pst->SendByte, 2);
pst->Step = SENSOR_MEASURE;
//TODO: 开启定时器等待75ms测量完成
tal_sw_timer_start(aht20_sample_etimerid, 100, TAL_TIMER_ONCE);
tkl_cpu_force_wakeup();
}
else if(pst->Step == SENSOR_MEASURE)
{
pst->Step=SENSOR_COMPLETE;
drv_i2c_read_series((I2C_SLAVE_ID<<1)|1, 0,I2C_SLAVE_ADDR_LEN, pst->ReadByte, 7);
/* 换算温度和湿度 */
if(pst->ErrFlag==0)
{
//if((CheckCrc8(&pst->ReadByte[0],6)==pst->ReadByte[6])&&((pst->ReadByte[0]&0x98) == 0x18))
{
s32x=pst->ReadByte[1];s32x=s32x<<8;s32x+=pst->ReadByte[2];s32x=s32x<<8;s32x+=pst->ReadByte[3];s32x=s32x>>4;
pst->RH=s32x;
pst->RH=pst->RH*100/1048576;
s32x=pst->ReadByte[3]&0x0F;s32x=s32x<<8;s32x+=pst->ReadByte[4];s32x=s32x<<8;s32x+=pst->ReadByte[5];
pst->T=s32x;
pst->T=pst->T*200/1048576-50;
}
TAL_PR_DEBUG("pst->ReadByte: %02x-%02x-%02x-%02x-%02x-%02x-%02x", pst->ReadByte[0], pst->ReadByte[1], pst->ReadByte[2],\
pst->ReadByte[3], pst->ReadByte[4], pst->ReadByte[5], pst->ReadByte[6]);
TAL_PR_DEBUG("temp = %.2f, humi = %.2f", pst->T, pst->RH);
}
else
{
pst->RH=0;
pst->T=0;
}
tkl_cpu_allow_sleep();
}
}
int app_aht20_init(void)
{
drv_i2c_master_init(I2C_CLOCK);
drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1);
SENx.Adrr = ATH20_ADDR;
SENx.Step = SENSOR_IDLE;
//SENx.SetRTim=AHT20_SAMPLE_PERIOD;
WaitMs(40);
/* 定时启动读取温湿度用 */
OPERATE_RET ret = tal_sw_timer_create(MYI2C_Handle, &SENx, &aht20_etimerid);
if(ret != OPRT_OK)
{
TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__);
return ret;
}
/* 温湿度采集时动作延迟用 */
ret = tal_sw_timer_create(aht20_measure_handle, &SENx, &aht20_sample_etimerid);
if(ret != OPRT_OK)
{
TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__);
return ret;
}
//
ret = tal_sw_timer_start(aht20_etimerid, AHT20_SAMPLE_PERIOD, TAL_TIMER_CYCLE);
if(ret != OPRT_OK)
{
TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__);
return ret;
}
return 0;
}
Re: 低功耗设备使用硬件i2c驱动异常
Posted: 2024年 Mar 21日 21:05
by huanghuan
1.你好,试下用 VOID hardware_set_wakeup(UINT32_T bit_map) 这个函数保持唤醒试下
填入的参数可以填 0x00000002
Re: 低功耗设备使用硬件i2c驱动异常
Posted: 2024年 Mar 22日 11:36
by hzb
iot_man 2024年 Mar 21日 21:03
下面这样试试:
Code: Select all
#define AHT20_SAMPLE_PERIOD 5000 //单位:ms, 且不小于MinReadTim
/* I2C Clock */
#define I2C_CLOCK 100000//100K
/* I2C slave ID */
#define I2C_SLAVE_ID 0x38
#define I2C_SLAVE_ADDR_LEN 1
#define ATH20_ADDR 0x38
#define AHT20_STATUS_REG 0x00 //状态字 寄存器地址
#define AHT20_INIT_REG 0xBE //初始化 寄存器地址
#define AHT20_SOFTRESET_REG 0xBA //软复位 单指令
#define AHT20_MEASURE_REG 0xAC //触发测量 寄存器地址
#define SENSOR_IDLE 0 //
#define SENSOR_MEASURE 1 //
#define SENSOR_COMPLETE 2 //
//****************************************
// 定义 AHT20 内部地址
//****************************************
#define ATH20_ADDR 0x38
#define AHT20_STATUS_REG 0x00 //状态字 寄存器地址
#define AHT20_INIT_REG 0xBE //初始化 寄存器地址
#define AHT20_SOFTRESET_REG 0xBA //软复位 单指令
#define AHT20_MEASURE_REG 0xAC //触发测量 寄存器地址
/*----------------------------------------------------------------------------
Section: Type Definitions
----------------------------------------------------------------------------*/
typedef struct
{
unsigned char Adrr;
unsigned int timcnt;
unsigned char ErrFlag;
unsigned char Step;
unsigned int SetRTim;
unsigned char SendByte[16];
unsigned char ReadByte[16];
float RH;//湿度
float T;//温度
}MYI2C_Struct;
static MYI2C_Struct SENx;
static TIMER_ID aht20_etimerid;
static TIMER_ID aht20_sample_etimerid;
/*******************************************************************************
* Function Name :
* Description :
* Input :None
* Output :None
* Return :None
*******************************************************************************/
static void MYI2C_Handle(TIMER_ID timer_id, VOID_T *arg)
{
MYI2C_Struct *pst = (MYI2C_Struct *)arg;
pst->Step = SENSOR_IDLE;
tal_sw_timer_start(aht20_sample_etimerid, 10, TAL_TIMER_ONCE);
//tkl_cpu_force_wakeup();
}
static void aht20_measure_handle(TIMER_ID timer_id, VOID_T *arg)
{
unsigned char i;
unsigned long s32x;
MYI2C_Struct *pst = (MYI2C_Struct *)arg;
TAL_PR_DEBUG("[%s] step = %d", __FUNCTION__, pst->Step);
if(pst->Step == SENSOR_IDLE)
{
pst->SendByte[0]=0x33;
pst->SendByte[1]=0x00;
drv_i2c_write_series((I2C_SLAVE_ID<<1) | 0, AHT20_MEASURE_REG, I2C_SLAVE_ADDR_LEN, pst->SendByte, 2);
pst->Step = SENSOR_MEASURE;
//TODO: 开启定时器等待75ms测量完成
tal_sw_timer_start(aht20_sample_etimerid, 100, TAL_TIMER_ONCE);
tkl_cpu_force_wakeup();
}
else if(pst->Step == SENSOR_MEASURE)
{
pst->Step=SENSOR_COMPLETE;
drv_i2c_read_series((I2C_SLAVE_ID<<1)|1, 0,I2C_SLAVE_ADDR_LEN, pst->ReadByte, 7);
/* 换算温度和湿度 */
if(pst->ErrFlag==0)
{
//if((CheckCrc8(&pst->ReadByte[0],6)==pst->ReadByte[6])&&((pst->ReadByte[0]&0x98) == 0x18))
{
s32x=pst->ReadByte[1];s32x=s32x<<8;s32x+=pst->ReadByte[2];s32x=s32x<<8;s32x+=pst->ReadByte[3];s32x=s32x>>4;
pst->RH=s32x;
pst->RH=pst->RH*100/1048576;
s32x=pst->ReadByte[3]&0x0F;s32x=s32x<<8;s32x+=pst->ReadByte[4];s32x=s32x<<8;s32x+=pst->ReadByte[5];
pst->T=s32x;
pst->T=pst->T*200/1048576-50;
}
TAL_PR_DEBUG("pst->ReadByte: %02x-%02x-%02x-%02x-%02x-%02x-%02x", pst->ReadByte[0], pst->ReadByte[1], pst->ReadByte[2],\
pst->ReadByte[3], pst->ReadByte[4], pst->ReadByte[5], pst->ReadByte[6]);
TAL_PR_DEBUG("temp = %.2f, humi = %.2f", pst->T, pst->RH);
}
else
{
pst->RH=0;
pst->T=0;
}
tkl_cpu_allow_sleep();
}
}
int app_aht20_init(void)
{
drv_i2c_master_init(I2C_CLOCK);
drv_i2c_gpio_set(I2C_GPIO_GROUP_C0C1);
SENx.Adrr = ATH20_ADDR;
SENx.Step = SENSOR_IDLE;
//SENx.SetRTim=AHT20_SAMPLE_PERIOD;
WaitMs(40);
/* 定时启动读取温湿度用 */
OPERATE_RET ret = tal_sw_timer_create(MYI2C_Handle, &SENx, &aht20_etimerid);
if(ret != OPRT_OK)
{
TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__);
return ret;
}
/* 温湿度采集时动作延迟用 */
ret = tal_sw_timer_create(aht20_measure_handle, &SENx, &aht20_sample_etimerid);
if(ret != OPRT_OK)
{
TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__);
return ret;
}
//
ret = tal_sw_timer_start(aht20_etimerid, AHT20_SAMPLE_PERIOD, TAL_TIMER_CYCLE);
if(ret != OPRT_OK)
{
TAL_PR_DEBUG("[%s] timer create failed", __FUNCTION__);
return ret;
}
return 0;
}
尝试了,还是不行
Re: 低功耗设备使用硬件i2c驱动异常
Posted: 2024年 Mar 22日 11:38
by hzb
huanghuan 2024年 Mar 21日 21:05
1.你好,试下用 VOID hardware_set_wakeup(UINT32_T bit_map) 这个函数保持唤醒试下
填入的参数可以填 0x00000002
在last_init中调用:hardware_set_wakeup(0x00000002); 现象:确实不会回调__tuya_post_sleep_cb, 但是读取传感器还是失败
Re: 低功耗设备使用硬件i2c驱动异常
Posted: 2024年 Mar 25日 16:21
by hzb