fix(pwr): shut down at 6.8V and light the charge page only above it

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yuquanjun 2026-09-26 15:06:36 +08:00
parent cde5a80a3d
commit 8bf68e256d
4 changed files with 58 additions and 17 deletions

View File

@ -355,6 +355,16 @@ static void app_adc_volume_process(void)
static uint16_t s_vbat_raw = 0;
static uint8_t s_vbat_valid = 0;
static uint8_t s_charge_ui_allowed = 0;
/* 高于 6.8V 才允许点亮关机充电页;未采样视为不允许 */
uint8_t app_adc_charge_ui_allowed(void)
{
return (s_vbat_valid && s_vbat_raw > (uint16_t)VBAT_SHUTDOWN_RAW) ? 1u : 0u;
}
static bat_state_t bat_state = BAT_IDLE; static bat_state_t bat_state = BAT_IDLE;
static uint32_t bat_last_sample_tick = 0; /* 上次采样时刻 */ static uint32_t bat_last_sample_tick = 0; /* 上次采样时刻 */
static uint32_t bat_state_tick = 0; /* 进当前状态的时刻 */ static uint32_t bat_state_tick = 0; /* 进当前状态的时刻 */
@ -383,6 +393,9 @@ void app_adc_init(void)
bat_poweron_done = 0; bat_poweron_done = 0;
bat_sample_cnt = 0; bat_sample_cnt = 0;
bat_sample_tick = 0; bat_sample_tick = 0;
s_vbat_raw = 0;
s_vbat_valid = 0;
s_charge_ui_allowed = 0;
} }
/* 采样:读 ADC + 滑动平均 */ /* 采样:读 ADC + 滑动平均 */
@ -396,11 +409,14 @@ static void app_adc_battery_do_sample(void)
bat_index = (bat_index + 1) % BAT_SAMPLE_COUNT; bat_index = (bat_index + 1) % BAT_SAMPLE_COUNT;
} }
/* 上报:映射成百分比,变化才发消息;低于 6.8V 触发低电量关机(插着 Type-C 也执行) */ /* 上报:映射成百分比,变化才发消息;低于等于 6.8V 触发低电量关机(插着 Type-C 也执行) */
static void app_adc_battery_report(void) static void app_adc_battery_report(void)
{ {
uint16_t filtered = bat_sum / BAT_SAMPLE_COUNT; uint16_t filtered = bat_sum / BAT_SAMPLE_COUNT;
uint8_t pct; uint8_t pct;
uint8_t allow;
uint8_t pct_changed;
uint8_t allow_changed;
if (filtered < VBAT_MIN_RAW) if (filtered < VBAT_MIN_RAW)
pct = 0; pct = 0;
@ -409,27 +425,34 @@ static void app_adc_battery_report(void)
else else
pct = (uint8_t)(100 * (filtered - VBAT_MIN_RAW) / (VBAT_MAX_RAW - VBAT_MIN_RAW)); pct = (uint8_t)(100 * (filtered - VBAT_MIN_RAW) / (VBAT_MAX_RAW - VBAT_MIN_RAW));
/* 开机使用中包电压低于 6.8V:停负载并关机。插着 Type-C 同样执行,避免边充边用拉过保护电压 */ allow = (filtered > (uint16_t)VBAT_SHUTDOWN_RAW) ? 1u : 0u;
if (powon && !System_LowBat_IsActive() && s_vbat_raw = filtered;
filtered < (uint16_t)VBAT_SHUTDOWN_RAW) s_vbat_valid = 1u;
/* 开机使用中包电压低于等于 6.8V:提示页停留 10s 后关机。插着 Type-C 同样停负载 */
if (powon && !System_LowBat_IsActive() && allow == 0u)
{ {
LOG_W("BAT", "lowbat raw=%u thr=%u → tip+shutdown", LOG_W("BAT", "lowbat raw=%u thr=%u → tip+shutdown",
(unsigned)filtered, (unsigned)VBAT_SHUTDOWN_RAW); (unsigned)filtered, (unsigned)VBAT_SHUTDOWN_RAW);
MainTask_Sendmsg(MSG_ID_LOW_BAT_TIP, pct, filtered, 0); MainTask_Sendmsg(MSG_ID_LOW_BAT_TIP, pct, filtered, 0);
} }
if (pct != percentage) { /* 变化才上报 */ pct_changed = (pct != percentage) ? 1u : 0u;
allow_changed = (allow != s_charge_ui_allowed) ? 1u : 0u;
s_charge_ui_allowed = allow;
if (pct_changed)
percentage = pct; percentage = pct;
if (usb_charging_state && !powon) if (usb_charging_state && !powon)
{ {
/* 跨过 6.8V 也要通知,否则百分比不变时充电页不会亮或熄 */
if (pct_changed || allow_changed)
MainTask_Sendmsg(MSG_ID_POWOFF_CHARG, percentage, usb_charging_state, 0); MainTask_Sendmsg(MSG_ID_POWOFF_CHARG, percentage, usb_charging_state, 0);
} }
else else if (pct_changed)
{ {
MainTask_Sendmsg(MSG_ID_BATTERY_VALUE, percentage, usb_charging_state, 0); MainTask_Sendmsg(MSG_ID_BATTERY_VALUE, percentage, usb_charging_state, 0);
} }
}
} }
/* 电池采集状态机入口(app_adc_scan 每 1ms 调用,状态推进约每 10ms 一次) */ /* 电池采集状态机入口(app_adc_scan 每 1ms 调用,状态推进约每 10ms 一次) */
@ -450,9 +473,13 @@ static void app_adc_battery_process(void)
{ {
uint32_t interval = BAT_SAMPLE_INTERVAL_MS; uint32_t interval = BAT_SAMPLE_INTERVAL_MS;
uint16_t last_avg = bat_sum / BAT_SAMPLE_COUNT; uint16_t last_avg = bat_sum / BAT_SAMPLE_COUNT;
/* 关机充电不加快采样,避免每 2 秒停一次充电 */ /* 开机接近低电时加快采样。关机充电且尚未高于 6.8V 也加快,
* 但不停充电芯片,便于电压回升后尽快点亮充电页。 */
if (powon && last_avg != 0 && last_avg < (uint16_t)VBAT_FAST_SAMPLE_RAW) if (powon && last_avg != 0 && last_avg < (uint16_t)VBAT_FAST_SAMPLE_RAW)
interval = BAT_SAMPLE_INTERVAL_LOW_MS; interval = BAT_SAMPLE_INTERVAL_LOW_MS;
else if (!powon && usb_charging_state && s_vbat_valid &&
s_vbat_raw <= (uint16_t)VBAT_SHUTDOWN_RAW)
interval = BAT_SAMPLE_INTERVAL_LOW_MS;
if (now - bat_last_sample_tick >= interval) if (now - bat_last_sample_tick >= interval)
bat_state = BAT_START; bat_state = BAT_START;
} }

View File

@ -22,6 +22,8 @@ extern bool pick_hold_up;
extern bool usb_charging_state; extern bool usb_charging_state;
extern bool usb_charging_laststate; extern bool usb_charging_laststate;
extern uint8_t percentage; extern uint8_t percentage;
/* 关机充电页:仅当已采到的包电压高于 6.8V 时为 1。未采样或低于等于 6.8V 为 0。 */
uint8_t app_adc_charge_ui_allowed(void);
void app_adc_scan_all(void); void app_adc_scan_all(void);
void app_adc_in1_scan_part(uint8_t channel); void app_adc_in1_scan_part(uint8_t channel);
bool app_adc_usb_is_plugged(void); bool app_adc_usb_is_plugged(void);

View File

@ -204,7 +204,7 @@ static volatile uint8_t s_pwr_rails_cut = 0;
/* TMR7:关机长按已触发请求后的紧急倒计时(ms) */ /* TMR7:关机长按已触发请求后的紧急倒计时(ms) */
static volatile uint16_t s_pwr_off_grace_ms = 0; static volatile uint16_t s_pwr_off_grace_ms = 0;
/* 电量 <6.8V:提示界面停留后关机(插着 Type-C 也停负载) */ /* 电量 <=6.8V:提示界面停留后关机(插着 Type-C 也停负载) */
#define LOWBAT_SHUTDOWN_DELAY_MS 10000u #define LOWBAT_SHUTDOWN_DELAY_MS 10000u
static volatile uint8_t s_lowbat_active = 0; static volatile uint8_t s_lowbat_active = 0;
static volatile uint32_t s_lowbat_deadline_ms = 0; static volatile uint32_t s_lowbat_deadline_ms = 0;
@ -438,7 +438,7 @@ void System_PowerOff_Poll(void)
} }
} }
/* 电量 <6.8V:提示界面停留后关机(插着 Type-C 也停负载) */ /* 电量 <=6.8V:提示界面停留 10s 后关机(插着 Type-C 也停负载) */
void System_LowBat_Arm(void) void System_LowBat_Arm(void)
{ {
if (s_lowbat_active) if (s_lowbat_active)

View File

@ -257,6 +257,18 @@ void IdleProcess(DisplayTaskMessage_Type msg)
/* 已开机:忽略滞后的关机充电消息,勿覆盖模式选择页或切断主电 */ /* 已开机:忽略滞后的关机充电消息,勿覆盖模式选择页或切断主电 */
if (powon) if (powon)
break; break;
if (usb_charging_state && !app_adc_charge_ui_allowed())
{
/* Type-C 充电且包电压未高于 6.8V:不点亮、不画充电页 */
LCD_BLK_Clr();
LCD_WR_REG(0x28);
if (s_charge_ui_drawn)
LCD_FillByColor(0, 0, 240, 320, BLACK);
s_charge_ui_drawn = false;
BSP_MainPowerEnable(0);
LOG_I("UI", "type-c charge <=6.8V, lcd off");
break;
}
if(!s_charge_ui_drawn) if(!s_charge_ui_drawn)
{ {
uint8_t peek[4]; uint8_t peek[4];