蓝牙开发 杰理开发 AC7106 放入2.4V维持电压充电仓内自动关机 MT 2025-10-09 2025-10-16 AC7106 放入2.4V维持电压充电仓内自动关机 最近在使用杰理AC7106芯片开发TWS耳机项目时,我们遇到了在放入带有2.4V维持电压的充电仓时耳机自动关机的现象。
充电仓维持电压工作机制 维持电压目的:耳机出入仓检测 原理:VOUT输出2.4V电压,J8、J9分别为充电仓的正负极充电顶针,耳机放入充电仓相当于串入一个负载电阻(耳机端设置的下拉电阻),通过检测耳机的分压来确定耳机是否在仓内。
耳机充电检测机制 在AC7106的SDK中,充电检测主要通过 LDO5V_DET 信号来判断。系统会根据电压值将充电状态分为三种情况:
正常插入 (ldoin > VBat):执行 charge_ldo5v_in_deal() 函数
维持电压 (0.6V < ldoin < VBat):执行 ldo5v_keep_deal() 函数
正常拔出 (ldoin < 0.6V):执行 charge_ldo5v_off_deal() 函数
问题出现在第二种情况,即维持电压状态下的处理逻辑。
事件处理流程 当耳机检测到维持电压时,系统会触发CHARGE_EVENT_LDO5V_KEEP事件,并遍历所有注册的app_charge_handler处理函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 void ldo5v_keep_deal (void ) { int abandon = 0 ; const struct app_charge_handler *handler ; log_info("%s\n" , __func__); charge_close(); batmgr_send_msg(POWER_EVENT_POWER_CHANGE, 0 ); charge_check_and_set_pinr(0 ); for_each_app_charge_handler(handler) { abandon += handler->handler (CHARGE_EVENT_LDO5V_KEEP, 0 ); } if (get_charge_poweron_en() == 0 ) { if (abandon == 0 ) { ldo5v_keep_softoff(); } } else { batmgr_send_msg(BAT_MSG_CHARGE_ERR, 0 ); } } charge.c
经过分析代码,发现以下几个关键问题:
1. 模块级事件响应机制 系统使用了模块化的事件响应机制,每个模块可以通过APP_CHARGE_HANDLER宏注册自己的处理函数:
1 2 3 4 5 6 #define APP_CHARGE_HANDLER(name, priority) \ const struct app_charge_handler handler_##name SECTION ("charge_handler") = { .handler = name, .priority = priority }
各模块通过返回1或0来决定是否阻止关机流程:
返回1:表示需要保持系统运行,阻止关机
返回0:表示允许系统关机
所有handler的返回值会累加到abandon变量中,如果abandon最终为0,则执行关机。
2. 默认关机逻辑 在默认情况下,大部分模块对CHARGE_EVENT_LDO5V_KEEP事件的处理都是返回0,不阻止关机流程:
1 2 3 4 5 6 7 8 9 10 11 12 static int dev_manager_charge_handler(int event, u32 param) { switch (event) { case CHARGE_EVENT_LDO5V_KEEP: dev_manager_close_gsensor(); dev_manager_close_npu(); break; // ... } return 0; // 不阻止关机 }
解决方案 最直接的方法是修改 ldo5v_keep_deal() 函数,添加对维持电压状态的检测,阻止不必要的关机:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 void ldo5v_keep_deal (void ) { int abandon = 0 ; const struct app_charge_handler *handler ; log_info("%s\n" , __func__); charge_close(); batmgr_send_msg(POWER_EVENT_POWER_CHANGE, 0 ); charge_check_and_set_pinr(0 ); for_each_app_charge_handler(handler) { abandon += handler->handler (CHARGE_EVENT_LDO5V_KEEP, 0 ); } if (get_charge_poweron_en() == 0 ) { if (is_ldo5v_keep_state() && abandon == 0 ) { return ; } } else { batmgr_send_msg(BAT_MSG_CHARGE_ERR, 0 ); } }
额外优化:灯效处理 解决了关机问题后,还发现耳机在维持电压状态下会触发蓝灯亮三秒的效果。这是因为上面的ldo5v_keep_deal()还调用了charge_close(),导致了耳机原本的灯效被覆盖,修改即可。
解决了维持电压状态下会触发蓝灯亮三秒问题后,还发现耳机在维持电压状态下拔出会触发蓝灯亮三秒的效果。这是因触发了CHARGE_LDO5V_OFF,导致了耳机原本的灯效被覆盖,修改即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 static int ui_battery_msg_handler (int *msg) { switch (msg[0 ]) { case BAT_MSG_CHARGE_START: led_ui_set_state(LED_STA_RED_ON, DISP_CLEAR_OTHERS); break ; case BAT_MSG_CHARGE_FULL: case BAT_MSG_CHARGE_CLOSE: case BAT_MSG_CHARGE_ERR: case BAT_MSG_CHARGE_LDO5V_OFF: led_ui_set_state(LED_STA_BLUE_ON_3S, DISP_CLEAR_OTHERS); break ; } return 0 ; }