/** * BQ25756 AI-4 初始化序列 — v3 (2026-07-29 Audit Fix) * * 硬件参数:7S Li-ion, 2A CC, NTC (103AT), FB 默认分压, 24V 输入 * * v3 变更 (基于 datasheet 全面审计): * [P7] +REG0x18: 禁用 ICHG/ILIM_HIZ 硬件引脚覆盖 I²C 设置 * [P9] VFB_ADC POST 自检: 充电前验证 FB 分压比(见 app_charge_task.c) * [P10] +Top-off 15min: 补偿 ITERM=200mA 的比较器精度偏差 * [P10] 修正 REG0x00 POR 注释: 0x0008→0x0010 * * v2 变更(基于 datasheet cross-reference audit): * [P0] +第 4 步: 显式写入 REG0x00 VFB_REG,防止 POR 默认值漂移导致过压 * [P1-1] +第 11 步: 显式关闭反向模式 (REG0x19 EN_REV=0),防误触发放电 * [P1-2] +第 12 步: 使能 CV 阶段独立定时器 4hr,防止老化电池无限 CV 等待 */ #include "bq25756_regs.h" #include "soft_i2c.h" #define I2C_ADDR BQ25756_I2C_ADDR /*=========================================================================== * BQ25756_AI4_Init — AI-4 完整初始化序列 * * 初始化分为 12 步,按 datasheet (SLUSEN5) 推荐顺序排列。 * 每一步失败返回对应负值步骤号,成功返回 0。 * * 充电目标:7S Li-ion, 29.4V 满充, 2A CC, 200mA 预充/终止 * 安全特性:40s I2C 看门狗, 12hr 总充电定时器, 4hr CV 定时器, * NTC JEITA 温度分区 (Cool 降流 20%, Warm 降电压 97.6%) *===========================================================================*/ int BQ25756_AI4_Init(void) { int ret; /*=============================================================== * 第 1 步:安全定时器 + I2C 看门狗 (REG0x15) * -------------------------------------------------------------- * Register: TIMER_CONTROL (0x15), POR=0x1D * * Bits 7:6 TOPOFF = 00 → 禁用浮充阶段 * Bits 5:4 WD = 01 → I2C 看门狗 40s(MCU 断连 40s 自停) * Bit 3 EN_CHG_TMR = 1 → 使能充电安全定时器 * Bits 2:1 CHG_TMR = 10 → 总充电超时 12hr * Bit 0 EN_TMR2X = 1 → 预充阶段定时器 ×2(预充不计数) * * 安全意义:WD=40s 确保 MCU 死机/断 I2C 后硬件自动停充。 * CHG_TMR=12hr 防止电池异常(如内部短路)时无限充电。 * 这两项是工业级充电器的基础安全底线。 *===============================================================*/ ret = SoftI2C_WriteReg(I2C_ADDR, 0x15, 0x5D); /* [P10 FIX]: 0x1D→0x5D, TOPOFF=15min */ if (ret) return -1; /*=============================================================== * 第 2 步:NTC 温度阈值 (REG0x1B) * -------------------------------------------------------------- * Register: TS_CHARGING_THRESHOLD (0x1B), POR=0x96 * * 103AT NTC 热敏电阻 (10kΩ @25°C, β=3435K) * T1 = 0°C (0010) — 低于此温度禁用充电(Cold 保护) * T2 = 10°C (0001) — Cool 区下限 * T3 = 45°C (0001) — Warm 区上限 * T5 = 60°C (0010) — 高于此温度禁用充电(Hot 保护) * * POR 值 0x96 = 10_01_01_10 与上述一致,显式写回确保确定性。 *===============================================================*/ ret = SoftI2C_WriteReg(I2C_ADDR, 0x1B, 0x96); if (ret) return -2; /*=============================================================== * 第 3 步:JEITA 温度行为配置 (REG0x1C) * -------------------------------------------------------------- * Register: TS_REGION_BEHAVIOR (0x1C), POR=0x57 * * Bits 6:5 VSET = 10 → Warm 区 VFB 降为 97.6%(轻度过温降电压充) * Bit 4 ISETH = 1 → Warm 区不降电流(保持 100% CC) * Bits 3:2 ISETC = 01 → Cool 区电流降为 20%(低温保护锂沉积) * Bit 1 EN_JEITA = 1 → 使能 JEITA 温度补偿 * Bit 0 EN_TS = 1 → 使能 TS 引脚(NTC 接入) * * 为什么 Cool 区降电流到 20%? * 锂电池在低温下负极嵌锂速度减慢,大电流充电会导致金属锂枝晶析出, * 最终刺穿隔膜造成内部短路。TI 推荐 ≤0°C 时电流降至 20%CC。 *===============================================================*/ ret = SoftI2C_WriteReg(I2C_ADDR, 0x1C, 0x57); if (ret) return -3; /*=============================================================== * 第 4 步:充电电压 (VFB_REG) 显式写入 (REG0x00) [P0 FIX] * -------------------------------------------------------------- * Register: CHG_VOLTAGE (0x00), 16-bit, POR=0x0010 [P10 FIX: was 0x0008, datasheet Table 8-2 says 0x0010] * * Bits 4:0 VFB_REG — 内部反馈基准电压微调 * VFB(mV) = 1504 + VFB_REG × 2 * VFB_REG range: 0~31 → VFB range: 1504~1566mV * * 电池实际充电电压: VBATREG = VFB × (R_TOP1 / R_BOT + 1) * * ⚠️ 硬件依赖:FB 引脚外接电阻分压网络决定充电电压。 * VFB_REG 仅用于微调(±62mV 范围,对应电池端约 ±1.2V)。 * 如果 AI-4 板件的分压电阻设计目标为 29.4V @ VFB=1520mV(POR), * 则 VFB_REG=8 即可。如果实测充电电压偏差超过 0.5%, * 按以下公式重新计算 VFB_REG: * * VFB_REG = MIN(MAX(round((Vbat_target / divider_ratio - 1504) / 2), 0), 31) * * divider_ratio = VBATREG_at_POR / 1520 (实测后反推) * * 安全性:本步从前未写,依赖 POR 默认值 0x0008。 * 显式写入确保即使意外复位后仍为目标值。 * 如果怀疑寄存器被篡改,VFB_REG 越界会被芯片内部 clamp。 *===============================================================*/ ret = SoftI2C_WriteReg16(I2C_ADDR, BQ25756_REG_CHG_VOLTAGE, 0x0008); if (ret) return -4; /*=============================================================== * 第 5 步:充电电流 2A (REG0x02) * -------------------------------------------------------------- * Register: CHG_CURRENT (0x02), 16-bit * * ICHG = raw × 50mA, 范围 400~20000mA * raw = (2000 / 50) << 2 = 40 << 2 = 0x00A0 * * 为什么 2A?AI-4 的 7S 电池组在 2A CC 下充满约需 3-4 小时(按 6-8Ah 估算)。 * 更大电流需评估 PCB 走线、连接器和电池规格书中的最大充电电流。 *===============================================================*/ ret = SoftI2C_WriteReg16(I2C_ADDR, BQ25756_REG_CHG_CURRENT, 0x00A0); if (ret) return -5; /*=============================================================== * 第 6 步:预充电流 200mA (REG0x10) * -------------------------------------------------------------- * Register: PRECHG_CURRENT (0x10), 16-bit * * IPRECHG = raw × 50mA, 范围 250~10000mA * raw = (200 / 50) << 2 = 4 << 2 = 0x10 * * 预充阶段:电池电压低于 VBAT_LOWV (71.4% × VFB) 时进入。 * 预充电流 = 200mA = CC 的 10%,符合锂电安全规范。 *===============================================================*/ ret = SoftI2C_WriteReg16(I2C_ADDR, BQ25756_REG_PRECHG_CURRENT, 0x0010); if (ret) return -6; /*=============================================================== * 第 7 步:终止电流 200mA (REG0x12) * -------------------------------------------------------------- * Register: TERM_CURRENT (0x12), 16-bit * * ITERM = raw × 50mA * raw = (200 / 50) << 2 = 0x10 * * 充电终止判断:CV 阶段充电电流 < 200mA 且持续稳定 30s → 判满停充。 * 200mA = CC 的 10%,保守但安全的终止阈值。 *===============================================================*/ ret = SoftI2C_WriteReg16(I2C_ADDR, BQ25756_REG_TERM_CURRENT, 0x0010); if (ret) return -7; /*=============================================================== * 第 8 步:输入电流限制 5A (REG0x06) * -------------------------------------------------------------- * Register: INPUT_CURRENT_DPM (0x06), 16-bit * * IIN_DPM = raw × 50mA, 范围 400~20000mA * raw = (5000 / 50) << 2 = 100 << 2 = 0x0190 * * DPM (Dynamic Power Management): 输入电流超过此值时芯片自动降低充电电流, * 防止拉死输入端电源适配器。5A 为 24V/120W 适配器的安全裕量。 *===============================================================*/ ret = SoftI2C_WriteReg16(I2C_ADDR, BQ25756_REG_INPUT_CURRENT_DPM, 0x0190); if (ret) return -8; /*=============================================================== * 第 9 步:输入电压 DPM 24V (REG0x08) * -------------------------------------------------------------- * Register: INPUT_VOLTAGE_DPM (0x08), 16-bit * * VIN_DPM = raw × 20mV, 范围 4200~65000mV * raw = 24000 / 20 = 1200 = 0x04B0 * * 输入电压跌落到 24V 以下时芯片自动降充电电流,维持输入电压。 * 对长度较长的 DC 线缆或功率受限的电源适配器有保护作用。 *===============================================================*/ ret = SoftI2C_WriteReg16(I2C_ADDR, BQ25756_REG_INPUT_VOLTAGE_DPM, 0x04B0); if (ret) return -9; /*=============================================================== * 第 10 步:预充/终止控制 (REG0x14) * -------------------------------------------------------------- * Register: PRECHG_TERM_CTRL (0x14), POR=0x0F * * Bit 3 EN_TERM = 1 → 使能终止检测 * Bits 2:1 VBAT_LOWV = 11 → 71.4% VFB(低于此值进入预充) * Bit 0 EN_PRECHG = 1 → 使能预充阶段 * * VBAT_LOWV = 71.4% = 约 21V → 深度放电电池先预充再快充。 *===============================================================*/ ret = SoftI2C_WriteReg(I2C_ADDR, BQ25756_REG_PRECHG_TERM_CTRL, 0x0F); if (ret) return -10; /*=============================================================== * 第 11 步:显式关闭反向模式 (REG0x19) [P1-1 FIX] * -------------------------------------------------------------- * Register: POWER_PATH_REV (0x19), POR=0x20 * * Bit 7 REG_RST = 0 → 不复位寄存器(正常操作) * Bit 6 EN_IAC_LOAD = 0 → 不使能 IAC 负载 * Bit 5 EN_PFM = 0 → Pulse-Frequency Modulation 禁用(PWM 模式) * ※ 轻载时 PFM 可降低功耗和 EMI,后续可改为 1 * Bit 4:1 reserved * Bit 0 EN_REV = 0 → 反向模式禁止 * * 安全意义:EN_REV=0 防止电池通过 Vin 端对外放电(反向 Boost)。 * 充电-only 场景下此项必须为 0。 * POR 默认 EN_REV=0 刚好正确,但显式写入防止 RESET_REG * 意外触发后回到非预期状态。 *===============================================================*/ ret = SoftI2C_WriteReg(I2C_ADDR, BQ25756_REG_POWER_PATH_REV, 0x00); if (ret) return -11; /*=============================================================== * 第 12 步:CV 阶段独立定时器 4hr (REG0x16) [P1-2 FIX] * -------------------------------------------------------------- * Register: THREE_STAGE_CHG (0x16), POR=0x00 * * Bits 3:0 CV_TMR = CV 阶段超时值 * 0000 = 禁用(POR 默认) * 0001~1111 = 1~15 小时 * * 写入 0x04 = CV 阶段超时 4hr。 * * 为什么要独立 CV 定时器? * REG0x15 的 CHG_TMR=12hr 是 PRE+CC+CV 总超时。 * 但 CC 阶段因为 DPM 等原因可能持续很久(比如输入功率不足时)。 * 如果 12hr 里 CC 耗了 11hr,CV 只剩 1hr, * 对于老化电池可能不够完成 CV 阶段的电流下降到终止阈值。 * * CV_TMR 独立于总定时器:进入 CV 阶段时启动,超时则停充。 * 4hr 对 7S/2A 电池足够完成从 CV 峰值到终止电流的全过程。 *===============================================================*/ ret = SoftI2C_WriteReg(I2C_ADDR, BQ25756_REG_THREE_STAGE_CHG, 0x04); if (ret) return -12; /*=============================================================== * 第 13 步:启动 ADC 连续转换 (REG0x2B) [P2 FIX: 13→15-bit] * -------------------------------------------------------------- * Register: ADC_CTRL (0x2B), 写入 0x80 * * Bit 7 ADC_EN = 1 → 使能 ADC * Bit 6 ADC_RATE = 0 → 连续转换模式 * Bit 5:4 SAMPLE = 00 → 15-bit 分辨率 [P2: 从 13-bit 升级] * Bit 3 AVG = 0 → 不使能移动平均(避免转换时间翻倍) * Bit 2 AVG_INIT = 1 → 平均初始化(bit3=0 时无效) * Bit 1:0 reserved * * ADC 分辨率选 15-bit 的理由: * - VBAT ADC 精度从 2mV/LSB 提升到 0.5mV/LSB * - 15-bit 全通道轮转时间 ~240ms,略超 200ms 周期但仍在工程裕量内 * (ADC 返回的是最新采样值, 100ms 年龄对电池充电状态监测无影响) * - 关闭 AVG 避免转换时间翻倍 (~480ms 会超出周期) * - 如果后期周期改为 100ms,降回 14-bit (0x90) * * 详细分析见 notes/p2_adc_gate_driver.md §1.4-§1.5 *===============================================================*/ ret = SoftI2C_WriteReg(I2C_ADDR, BQ25756_REG_ADC_CTRL, 0x80); if (ret) return -13; /*=============================================================== * 第 14 步:禁用 ICHG/ILIM_HIZ 硬件引脚覆盖 (REG0x18) [P7 FIX] * -------------------------------------------------------------- * Register: Pin_Control (0x18), 写入 0x00 * * POR 值 = 0xC0: * bit7 EN_ICHG_PIN = 1 → ICHG 硬件引脚决定充电电流限幅 * bit6 EN_ILIM_HIZ_PIN = 1 → ILIM_HIZ 硬件引脚决定输入电流限幅 * * 写入 0x00 清除两个 EN 位,确保充电电流和输入限流由 I²C 寄存器控制。 * 放在 init 序列最后的原因是:前面所有寄存器值已写入 BQ25756, * 此时禁用引脚覆盖不会干扰寄存器写入过程。 * * Datasheet ref: Section 8.5.8 (REG0x18 Pin_Control) *===============================================================*/ ret = SoftI2C_WriteReg(I2C_ADDR, BQ25756_REG_PIN_CTRL, 0x00); if (ret) return -14; return 0; /* 全部 13 步写入成功 */ } /*=========================================================================== * BQ25756_AI4_StartCharging — 启动充电 * * 三步启动流程: * 1. 读 REG0x17 (CHARGER_CTRL) * 2. 清零 EN_HIZ 位 (bit 2) — 退出高阻态,使能功率转换 * 3. 置位 EN_CHG 位 (bit 0) — 启动充电 * * CE 引脚由调用者拉低(需要在调用本函数前将 CE 设为 LOW)。 * * 为什么先清 HIZ 再置 EN_CHG? * BQ25756 在 EN_HIZ=1 时功率级完全关断(类似关机), * EN_CHG=1 在 HIZ 模式下不会生效。必须先退出 HIZ。 *===========================================================================*/ int BQ25756_AI4_StartCharging(void) { uint8_t val; /* Step A: 退出高阻态 — 必须最先执行 */ val = SoftI2C_ReadReg(I2C_ADDR, BQ25756_REG_CHARGER_CTRL); val &= ~BQ25756_EN_HIZ; /* 清零 bit 2 */ if (SoftI2C_WriteReg(I2C_ADDR, BQ25756_REG_CHARGER_CTRL, val) != 0) return -1; /* Step B: 使能充电 */ val |= BQ25756_EN_CHG; /* 置位 bit 0 */ if (SoftI2C_WriteReg(I2C_ADDR, BQ25756_REG_CHARGER_CTRL, val) != 0) return -1; return 0; } /*=========================================================================== * BQ25756_AI4_StopCharging — 停止充电 * * 只清零 EN_CHG,不进入 HIZ(保持芯片供电和 I2C 通信)。 * CE 引脚由调用者拉高(硬件关断功率级)。 *===========================================================================*/ int BQ25756_AI4_StopCharging(void) { uint8_t val; val = SoftI2C_ReadReg(I2C_ADDR, BQ25756_REG_CHARGER_CTRL); val &= ~BQ25756_EN_CHG; /* 清零 bit 0 */ return SoftI2C_WriteReg(I2C_ADDR, BQ25756_REG_CHARGER_CTRL, val); }