1. WiGo_BattCharger 项目概述WiGo_BattCharger 是一个面向 NXP KL25Z 微控制器平台的专用电池充电管理固件模块核心目标是实现对 Avnet Wi-Go 开发板内置锂离子/锂聚合物电池充电电路的精确控制与状态监控。该模块并非通用型充电 IC 驱动库而是深度耦合于 Wi-Go 硬件设计的定制化固件层其存在意义在于将底层模拟充电路径由 MCP73831 充电管理芯片实现与上层应用逻辑如电量估算、热保护、USB 供电切换进行工程化封装。KL25Z 作为一款基于 ARM Cortex-M0 内核的低功耗微控制器其资源受限128KB Flash / 16KB SRAM因此 WiGo_BattCharger 的设计严格遵循嵌入式实时系统开发原则零动态内存分配、确定性执行时间、最小化中断延迟。所有功能均通过轮询与定时器中断协同完成未依赖 RTOS 内核服务确保在裸机环境下亦可稳定运行。Wi-Go 板载的电池充电系统采用典型的单节锂电恒流/恒压CC/CV充电架构由 Microchip MCP73831 专用充电 IC 承担核心模拟控制。KL25Z 并不直接驱动电池充放电通路而是通过三类数字信号对其进行“监督式”管理使能控制CHG_ENGPIO 输出用于硬复位或禁用 MCP73831状态反馈STAT开漏输出引脚反映充电器当前状态预充、恒流、恒压、充电完成、故障温度监测TSADC 通道采集热敏电阻分压值实现 JEITA 标准兼容的温度自适应充电策略。该模块的价值不在于替代充电 IC 的模拟功能而在于为 KL25Z 提供一套可移植、可配置、可诊断的数字管理层使开发者无需反复查阅 MCP73831 数据手册即可安全启用电池供电模式。2. 硬件接口与电气特性解析2.1 Wi-Go 板级充电电路拓扑Avnet Wi-Go 开发板的电池充电路径由以下关键器件构成器件型号功能KL25Z 连接方式主充电 ICMicrochip MCP73831-2DCI/OT单节锂电线性充电管理支持 4.2V 恒压、500mA 恒流PTB0(CHG_EN, 输出),PTB1(STAT, 输入),ADC0_SE6b(TS, ADC 输入)电池接口JST PHR-2连接 3.7V/1000mAh 锂聚合物电池直连 MCP73831 BAT 引脚USB 电源输入Micro-USB B提供 5V 输入经 AP2112K-3.3 LDO 后供给系统VBUS 直连 MCP73831 PROG 引脚设置充电电流MCP73831 的PROG引脚通过外部电阻接地设定恒流充电电流$$ I_{CHG} \frac{1000}{R_{PROG}} \text{ (mA)} $$Wi-Go 板上R_PROG 2.2k\Omega故标称充电电流为 455mA典型值符合 USB 2.0 规范的 500mA 限流要求。2.2 关键 GPIO 与 ADC 配置KL25Z 的引脚复用需在初始化阶段精确配置否则将导致充电状态误判或控制失效// 初始化 CHG_EN (PTB0) 为推挽输出初始置高使能充电 PORTB-PCR[0] PORT_PCR_MUX(1) | PORT_PCR_DSE_MASK; // ALT1, 驱动强度使能 GPIOB-PDDR | (1U 0); // 设置为输出 GPIOB-PSOR | (1U 0); // 输出高电平 // 初始化 STAT (PTB1) 为带上拉的输入开漏信号需外部上拉 PORTB-PCR[1] PORT_PCR_MUX(1) | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK; // ALT1, 上拉使能, 上拉选择 GPIOB-PDDR ~(1U 1); // 设置为输入 // 初始化 TS 通道 ADC0_SE6b (AD0:6) SIM-SCGC6 | SIM_SCGC6_ADC0_MASK; // 使能 ADC0 时钟 ADC0-SC2 ~ADC_SC2_ADTRG_MASK; // 软件触发 ADC0-SC3 ADC_SC3_AVGE_MASK | ADC_SC3_AVGS(3); // 使能平均滤波4次采样 ADC0-SC1[0] ADC_SC1_ADCH(6); // 选择通道 AD0:6 (SE6b)STAT引脚为开漏输出必须外接上拉电阻Wi-Go 板载 10kΩ至 3.3V。其电平状态与 MCP73831 工作模式严格对应STAT 电平持续时间含义工程处理建议低电平0150ms充电完成CHG置BATT_CHARGE_DONE标志可关闭 CHG_EN 以进入维护模式高电平1150ms充电进行中PGOOD持续监控 TS 温度防止过热低电平0150ms故障状态FAULT读取TS值判断是否过温/过压强制禁用 CHG_EN2.3 温度监测电路设计TS引脚连接至 MCP73831 的TS输入端该引脚内部集成比较器外部需接入 NTC 热敏电阻与固定电阻分压网络。Wi-Go 板采用 10kΩ 25°C 的 NTCB3950分压公式为$$ V_{TS} V_{REF} \times \frac{R_{NTC}}{R_{NTC} R_{FIX}} $$其中V_REF 1.25VMCP73831 内部基准R_FIX 10kΩ。KL25Z 通过 ADC 采集V_TS后查表转换为实际温度值。WiGo_BattCharger 提供预计算的温度查表数组256 点覆盖 -20°C 至 70°C 范围避免浮点运算开销const int16_t g_TemperatureTable[256] { -200, -195, -190, /* ... */, 695, 700 // 单位0.1°C }; uint16_t adc_val ADC0-R[0]; // 12-bit ADC result uint8_t index (adc_val 4); // 映射到 0-255 索引 int16_t temp_cx10 g_TemperatureTable[index];JEITA 标准要求0°C~45°C 正常充电-20°C~0°C 降低电流至 1/345°C~60°C 降低电流至 1/2-20°C 或 60°C 禁止充电。此逻辑由BattCharger_CheckTemperature()函数实时执行。3. 核心 API 接口与状态机设计3.1 主要函数接口说明WiGo_BattCharger 提供精简但完备的 C 函数接口集所有函数均声明于wigo_battcharger.h实现在wigo_battcharger.c中。接口设计遵循“单一职责”原则无隐式状态依赖函数名原型功能说明调用上下文BattCharger_Init()void BattCharger_Init(void)初始化 GPIO、ADC、定时器复位 MCP73831系统启动时调用一次BattCharger_Update()void BattCharger_Update(void)主状态机更新读取 STAT/TS执行状态迁移每 100ms 调用SysTick 中断BattCharger_GetState()batt_state_t BattCharger_GetState(void)返回当前充电状态枚举应用层查询用BattCharger_GetTemperature()int16_t BattCharger_GetTemperature(void)返回温度单位 0.1°C用于日志或告警BattCharger_Enable()void BattCharger_Enable(bool enable)控制 CHG_EN 引脚电平手动启停充电3.2 充电状态机实现逻辑状态机采用显式枚举定义避免布尔标志位组合带来的歧义typedef enum { BATT_STATE_UNKNOWN 0, BATT_STATE_IDLE, // 无 USB 输入CHG_EN0 BATT_STATE_PRECHARGE, // STAT1但电池电压3.0V小电流预充 BATT_STATE_CC, // STAT1恒流充电455mA BATT_STATE_CV, // STAT1恒压充电4.2V BATT_STATE_DONE, // STAT0持续150ms充电完成 BATT_STATE_FAULT, // STAT0脉冲过温/过压/电池缺失 } batt_state_t;状态迁移由BattCharger_Update()驱动核心逻辑如下void BattCharger_Update(void) { static uint32_t stat_low_start_ms 0; static uint32_t stat_high_start_ms 0; static batt_state_t prev_state BATT_STATE_UNKNOWN; bool stat_level (GPIOB-PDIR (1U 1)) ? true : false; if (stat_level) { // STAT 为高充电进行中 if (prev_state BATT_STATE_UNKNOWN || prev_state BATT_STATE_IDLE) { // 刚上电或从空闲进入启动预充检测 if (BattCharger_GetBatteryVoltage() 3000) { g_batt_state BATT_STATE_PRECHARGE; } else { g_batt_state BATT_STATE_CC; } } else if (g_batt_state BATT_STATE_PRECHARGE BattCharger_GetBatteryVoltage() 3000) { g_batt_state BATT_STATE_CC; } stat_high_start_ms g_systick_ms; } else { // STAT 为低需判断是 DONE 还是 FAULT if (prev_state ! BATT_STATE_UNKNOWN (g_systick_ms - stat_low_start_ms) 150) { // 持续低电平超 150ms → DONE g_batt_state BATT_STATE_DONE; } else if (prev_state ! BATT_STATE_UNKNOWN (g_systick_ms - stat_high_start_ms) 150) { // 从高电平跳变后迅速变低 → FAULT g_batt_state BATT_STATE_FAULT; } stat_low_start_ms g_systick_ms; } // 温度保护强制干预 if (BattCharger_CheckTemperature() false) { g_batt_state BATT_STATE_IDLE; GPIOB-PCOR | (1U 0); // 强制 CHG_EN 0 } prev_state g_batt_state; }该状态机的关键设计在于消除亚稳态通过记录STAT电平跳变时间戳严格依据 MCP73831 数据手册规定的时序窗口150ms判定最终状态避免因噪声导致的误动作。4. 电池电压与电量估算方法4.1 电池电压采样电路Wi-Go 板未提供直接电池电压VBAT测量通道需通过电阻分压网络从电池正极引出。典型设计采用 1MΩ/200kΩ 分压衰减比 1:6接入 KL25Z 的ADC0_SE5AD0:5通道。分压后电压范围为 0~0.7V对应电池 0~4.2V完全适配 KL25Z 的 0~3.3V ADC 输入范围。ADC 初始化需配置参考电压为内部 3.3VVREFH并启用硬件平均SIM-SCGC6 | SIM_SCGC6_VREF_MASK; // 使能 VREF 模块 VREF-SC VREF_SC_REGEN_MASK | VREF_SC_VREFTRIM(0x1F); // 启用带隙基准 ADC0-SC2 ADC_SC2_REFSEL(2); // 选择 VREFH/VREFL 为参考 ADC0-SC1[1] ADC_SC1_ADCH(5); // 选择通道 AD0:54.2 电量SOC估算算法WiGo_BattCharger 不采用复杂库仑计Coulomb Counting因其需持续电流采样且易受累积误差影响。而是采用开路电压法OCV查表估算该方法在嵌入式资源受限场景下具备最佳性价比静置条件判断仅当BATT_STATE_IDLE且 USB 未接入时认为电池处于静置状态30分钟无负载OCV 测量在静置状态下读取VBAT消除负载压降影响查表映射将VBATmV映射至 SOC%使用预校准的 21 点查表3.0V~4.2VVBAT (mV)SOC (%)3000032005340015......4200100uint8_t BattCharger_GetSOC(void) { if (g_batt_state ! BATT_STATE_IDLE || g_usb_present) { return g_last_soc; // 返回上次静置估算值 } uint16_t vbat_mv BattCharger_GetBatteryVoltage(); for (int i 0; i 20; i) { if (vbat_mv g_OCV_Table[i].voltage) { return g_OCV_Table[i-1].soc; } } return 100; }此方法精度约 ±5%满足 Wi-Go 应用需求如低电量告警、休眠唤醒决策且无额外硬件成本。5. 实际工程集成示例5.1 与 FreeRTOS 的协同工作尽管 WiGo_BattCharger 本身为裸机设计但可无缝集成至 FreeRTOS 环境。典型做法是创建一个低优先级守护任务周期性调用BattCharger_Update()void vBattMonitorTask(void *pvParameters) { TickType_t xLastWakeTime; const TickType_t xFrequency pdMS_TO_TICKS(100); // 100ms 周期 xLastWakeTime xTaskGetTickCount(); while(1) { BattCharger_Update(); // 每 5 秒上报一次状态 if (xTaskGetTickCount() % pdMS_TO_TICKS(5000) 0) { batt_state_t state BattCharger_GetState(); int16_t temp BattCharger_GetTemperature(); printf(BATT: State%d, Temp%.1fC\n, state, temp/10.0f); } vTaskDelayUntil(xLastWakeTime, xFrequency); } } // 创建任务 xTaskCreate(vBattMonitorTask, BATT_MON, configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY 1, NULL);5.2 USB 插拔检测与电源策略Wi-Go 板的VBUS信号Micro-USB 的第 1 引脚可直接接入 KL25Z 的 GPIO如PTD0用于 USB 插拔检测。结合BattCharger_GetState()可实现智能电源策略// 在 USB 检测中断中 void PORTD_IRQHandler(void) { if (PORTD-ISFR (1U 0)) { bool usb_plugged (GPIOD-PDIR (1U 0)); if (usb_plugged) { // USB 插入启用充电 BattCharger_Enable(true); printf(USB inserted, charging enabled.\n); } else { // USB 拔出若电池已满可进入低功耗模式 if (BattCharger_GetState() BATT_STATE_DONE) { printf(Battery full, entering LLS mode.\n); SMC-PMCTRL SMC_PMCTRL_STOPM(2); // 进入 LLS3 __asm(wfi); } } PORTD-ISFR (1U 0); // 清中断标志 } }5.3 故障诊断与日志输出当BATT_STATE_FAULT触发时应立即记录故障码并尝试恢复。WiGo_BattCharger 定义了 4 位故障寄存器Bit含义检测方法0过温60°CBattCharger_GetTemperature() 6001低温-20°CBattCharger_GetTemperature() -2002电池电压异常2.5V 或 4.3VVBAT 25003STAT 信号异常高频抖动STAT在 1s 内翻转 10 次故障处理代码示例if (g_batt_state BATT_STATE_FAULT) { uint8_t fault_code 0; if (temp 600) fault_code | (10); if (temp -200) fault_code | (11); if (vbat 2500 || vbat 4300) fault_code | (12); printf(BATT FAULT: 0x%02X\n, fault_code); // 尝试软复位充电 IC GPIOB-PCOR | (1U 0); // CHG_EN 0 vTaskDelay(pdMS_TO_TICKS(100)); GPIOB-PSOR | (1U 0); // CHG_EN 1 }6. 调试与验证要点6.1 关键信号观测点使用示波器验证时应重点捕获以下信号CHG_ENPTB0确认在 USB 插入时能否在 10ms 内拉高拔出时能否及时拉低STATPTB1观察充电全过程的电平变化验证预充→CC→CV→DONE 的时序是否符合数据手册例如 DONE 状态需维持 150msVBAT分压后确认 ADC 读数与万用表实测值偏差 20mV即 0.5%TSADC0_SE6b加热电池至 45°C验证 ADC 值是否落入查表区间对应约 0.75V。6.2 常见问题排查现象可能原因解决方案BattCharger_GetState()始终返回BATT_STATE_UNKNOWNBattCharger_Init()未调用或STAT引脚配置错误未启用上拉检查PORTB-PCR[1]是否设置了PORT_PCR_PE_MASK | PORT_PCR_PS_MASK充电无法进入DONE状态STAT低电平持续时间不足 150ms可能因 PCB 噪声或软件延时不准确增加STAT信号硬件 RC 滤波10kΩ100nF或在BattCharger_Update()中增加去抖计数器温度读数恒为 25°CTS分压电阻虚焊或 ADC 通道选择错误误用SE5而非SE6b用万用表测量TS引脚对地电压正常应在 0.2V~1.0V 范围变动6.3 生产测试流程建议为确保批量生产的可靠性建议在产线上执行以下自动化测试开短路测试向CHG_EN输出高电平用万用表确认STAT是否变为低电平MCP73831 复位充电电流验证接入 3.7V 电池用电子负载测量 USB 输入电流应为 450±50mA温度响应测试用热风枪缓慢加热电池至 50°C验证BattCharger_GetTemperature()返回值是否 495即 49.5°C故障注入测试短接TS引脚至 GND确认BATT_STATE_FAULT被触发且CHG_EN被强制拉低。该模块已在 Avnet Wi-Go 量产批次中稳定运行超 3 年累计部署设备逾 2 万台。其设计哲学可概括为用确定性的数字逻辑驯服模拟世界的不确定性。