
简介英集芯IP5365寄存器手册面向移动电源与快充类产品的嵌入式开发者、硬件工程师聚焦IP5365这颗集成Type-C、UFCS、PD3.0等协议的电源SoC在寄存器层面的配置与调试需求。压缩包内含1个PDF文档约3.52MB章节划分清晰可作为设计阶段的对照查阅资料。目前已有677人学习下载。文档从I2C接口讲起说明LED1、LED2复用为I2C的默认连接方式、最高300kHz通信频率、8位寄存器地址与数据高位在前的格式并给出0xE8/0xE9与0xEA/0xEB两组设备地址的读写时序示例与信号流程图。应用笔记部分还涉及VCC总电容不超过3.3uF、MCU侧电容与串阻、大电流场景外加LDO等供电约束以及休眠转工作状态时的I2C检测、INT拉高100ms后再读写、SDA与SCK配置为高阻等实操要点。另附LED3、INT引脚的电气特性与中断复用说明并强调寄存器须按读—修改—写逐位操作避免误改保留位。1. 一颗 SoC 的 I2C 藏在 LED 引脚里翻开 IP5365 寄存器手册很多人第一反应是找那张地址表但真正决定这颗移动电源 SoC 能不能被 MCU 管起来的是两颗 LED 引脚上的 3.3k 上拉电阻。它把充电、升压、多口快充协议、电量计全塞进单颗 die引脚数量是硬通货所以 I2C 的 SDA/SCK 没有独立管脚而是和 LED1、LED2 复用。代价很直接芯片每次从休眠醒过来都要先看一眼 LED1、LED2 是不是同时被拉到 3.3V才决定自己当一颗只管灯效的芯片还是当一颗可被寄存器操控的电源。这套握手没搞明白地址表背得再熟也会在第一个 ACK 上翻车。2. 进 I2C 模式靠两根 LED 引脚投票上拉检测、VCC 电容与时序窗口IP5365 默认就是支持 I2C 的不需要烧配置、不需要发特殊命令只要按手册给的方式把 LED1、LED2 通过 3.3k 电阻上拉到 VCC上电后其他功能自动关闭直接进 I2C 模式。听起来像是硬件一接就通但真正的机制藏在什么时候检测和检测到什么这两个细节里而这两个细节决定了你 90% 的调试时间花在哪里。2.1 每次唤醒都重跑一遍的引脚投票芯片从休眠转入工作状态只有三种触发源按键、负载接入、5V 充电接入。每一次触发内部都会先把 LED1、LED2 这两个脚当普通 GPIO 读一遍电平只有两者同时为高即同时被上拉到 VCC 的 3.3V才判定外部挂了数字接口切进 I2C 模式并把 LED3 拉出一个 3.1V 的高电平只要有一个没被拉高就退回 LED 灯显模式。注意手册里的措辞是每次从休眠进入工作状态都会进行检测不是上电检测一次就完事这意味着运行期间任何一次状态回落都会重新投票。这个设计的好处很实在同一颗芯片、同一套固件焊到带 MCU 的板子上就是智能电源焊到不带 MCU 的板子上就是普通充电宝产线不用分型号。而 LED3 那一路 3.1V 高电平在多数原理图里会串一颗 510k 电阻引出去当 INT 用MCU 拿它判断有按键了、有负载插入了、有 5V 接入了。510k 这个阻值选得很大既能把 3.1V 电平送出去又不会在芯片休眠时反向灌电流。真正容易出问题的是投票的物理含义所谓上拉本质是要求这两根线上没有别的东西在往下拽。MCU 休眠时如果把 SDA/SCK 配成推挽输出低外部 3.3k 上拉根本拽不住一个几十欧输出阻抗的引脚芯片采样到的就是低电平于是判定没有 I2C切回灯显模式。这就是手册第 5 条反复强调 MCU 休眠时必须把这两根线配成输入或高阻的全部原因——不是建议是硬性前提。2.2 VCC 上的电容预算3.3uF 和 1uF 是从哪来的手册给了一条很硬的约束VCC 上总电容容量必须小于 3.3uF超过这个阈值会影响 IC 的上电速度。这个数字背后是两种失效模式。常见的实现思路是VCC 既是内部数字域的供电轨也是上电复位POR的参考点上电瞬间的充电电流由芯片内部决定容性负载越大VCC 爬升越慢爬升慢本身不致命致命的是 POR 释放点和 LED 上拉检测的采样窗口都挂在 VCC 电压上——电压还在 1.x V 徘徊时数字逻辑已经开始跑此刻采样到的电平无效结果就是随机的有时进 I2C、有时不进。针对挂 MCU 的场景手册给了三张图对应三种功耗等级的解法。MCU 附近那颗 VCC 电容必须 ≤1uF这是图 aMCU 确实需要更大容量的储能电容时先用 R1 ≥ 2Ω 串在中间再接 2.2uF 的大电容让 RC 把大电容的充电电流限住主轨该快还是快这是图 bMCU 自身耗电超过 30mA 时直接外挂一颗 3.3V LDO 单独喂 MCUVCC 只负责 IP5365这是图 c。这里有一对看起来互相矛盾的条款需要一起读。手册第 6 条说 MCU 供电必须由 VCC 来因为 IP5365 内部数字电平就是 3.3V如果 MCU 走外部 LDO当电池没电或低于 2V、VIN 接入 5V 时VCC 有电会启动 I2C 检测但 MCU 那边还没上电SDA/SCK 状态不定可能把线拉低导致检测失败。图 c 又明确允许外挂 LDO。我一般会这么理解手册允许 LDO但要求 LDO 的输入取自 VCC 或与 VCC 同源同时序保证IP5365 在采样时MCU 的引脚已经处于高阻态这个前提成立。如果 LDO 直接从 VIN 取电、上电斜率比 VCC 慢那就是踩着这条坑走。2.3 MCU 侧的上电时序INT 为高之后还要再等 100ms手册写得很清楚MCU 在休眠时要把 SDA 和 SCK 配成输入或高阻直到检测到 INT 为高后持续 100ms 以上才开始读写 I2C 数据。这 100ms 不是随手拍的延时它覆盖的是芯片完成模式判定 内部状态机就绪 数字域稳定这一段窗口。很多实现里把它当成可省的冗余结果就是首次读寄存器偶发 NACK重试一次又好了——这种玄学问题的根源就在这。/* 前提SCK/SDA 已由 3.3k 上拉到 VCCINT 由 LED3 经 510k 引出 */ static int ip5365_bringup(void) { /* 1. 第一步先把两根线放开别让 MCU 把上拉拽低。 这一步必须在配置 I2C 外设之前因为唤醒瞬间芯片就在采样 */ gpio_config_input(SDA_PORT, SDA_PIN); gpio_config_input(SCK_PORT, SCK_PIN); /* 2. 等 INT 稳定为高再额外等 100ms。 加超时是为了区分没进 I2C 模式和进了但还没就绪 */ uint32_t t0 millis(); while (gpio_read(INT_PIN) 0) { if (millis() - t0 500) return -1; /* 500ms 还没高基本是硬件没上拉 */ } delay_ms(100); /* 3. 确认握手完成才把引脚切成 I2C 复用功能 */ i2c_pinmux_enable(); i2c_init(200000); /* 手册上限 300K工程上留余量 */ return 0; }三个动作的顺序不能换。第一步放在最前是因为从休眠唤醒的那一刻芯片就在读引脚电平如果先调i2c_init()多数 HAL 会把引脚配成复用推挽采样窗口正好落在推挽阶段芯片看到的是低电平。第二步的 100ms 是硬等待不是可优化项。第三步的频率之所以取 200K 而不是手册标称的 300K是因为 MCU 侧的时钟源通常是 RC 振荡器几个百分点的偏差叠加在 300K 上就可能越过从机的时序容限手册自己也建议应用时用 200K 左右。3. 两组从地址与一帧事务0xE8 和 0xEA 为什么必须分开记地址表上最容易被扫过去的一行是IP5365 有两组 I2C 地址。一组写 0xE8、读 0xE9另一组写 0xEA、读 0xEB。同一颗芯片、同一条总线却有两个门牌而且寄存器分散在这两组里——这是整份手册里最容易写错的地方也是读得到但读错这类问题的源头。3.1 一帧里到底发了什么8bit 地址 8bit 数据 MSB firstIP5365 的寄存器寻址非常朴素8bit 寄存器地址8bit 寄存器数据地址和数据都是高位在前MSB。写一个寄存器的事务序列是Start → 从机写地址 → ACK → 寄存器地址 → ACK → 数据 → ACK → Stop。手册给的例子是往 0xEA 这组的 0x05 寄存器写 0x5AStart、0xEA、ACK、0x05、ACK、0x5A、ACK、Stop。没有页寄存器、没有地址自增、没有 CRC简单到几乎不会出错——除非你把 8bit 地址直接喂给了只认 7bit 地址的 HAL。这是第一个高频翻车点。0xE8 的二进制是 1110 1000最低位就是 I2C 协议里的 R/W 位真正的 7bit 从机地址是 0x740xEA 对应 0x75。很多 MCU 的 I2C 驱动接口要求传 7bit 地址并在内部自己拼 R/W 位如果你把 0xE8 原样传进去驱动会左移一位变成 0x1D0溢出成 0xD0 发到总线上然后你收获一个干脆利落的 NACK。两组地址的换算关系如下访问组写地址8bit含 R/W0读地址8bit含 R/W17bit 从机地址主组0xE80xE90x74扩展组0xEA0xEB0x75有意思的是切换读写只需要把最低位翻转这和标准 I2C 完全一致说明这两个门牌其实是同一物理器件的两个 7bit 地址只不过这组相邻地址被用来扩展寄存器空间把 8bit 地址空间从 256 个扩到 512 个。这个做法在引脚紧张、又不想引入页寄存器的芯片里非常常见。3.2 读操作必须 Restart地址指针为什么不能跨 Stop 保留读一个寄存器不是发读地址然后收数据因为从机不知道自己该从哪个地址读。手册给的读时序是Start → 0xEA写→ ACK → 0x05寄存器地址→ ACK → Restart → 0xEB读→ ACK → 数据 → NACK → Stop。中间那个 Restart 是关键它不发 Stop直接重新发 Start从而在不释放总线的前提下切换方向。为什么不干脆先写地址、Stop、再 Start 读因为一旦发 Stop从机内部的地址指针就可能被复位第二次 Start 时它不知道你要读哪儿。而且 Stop 意味着总线控制权交还理论上其他主机可以插进来。Restart 在协议上就是为了解决我需要连续两段方向不同的传输、但不允许中间被打断这个场景而存在的。还有一个容易忽略的细节读的最后一个字节主机必须回 NACK 而不是 ACK。ACK 的意思是我还要继续读从机会把下一个地址的数据推上来只有 NACK 才告诉从机到此为止。如果你回错了 ACK 再发 Stop多数从机会继续驱动数据线表现为总线偶发卡死。3.3 把读-改-写封成一个函数手册里那句必须按照读-修改-写来进行出现了不止一次这不是保守建议而是这颗芯片的寄存器里大量存在 Reserved 位而且这些位的复位值标的是 XX——也就是出厂值不确定。直接整字节写等于把不认识的位一起覆盖掉后果是不可预期的行为异常。#define IP5365_ADDR_MAIN_W 0xE8 #define IP5365_ADDR_MAIN_R 0xE9 #define IP5365_ADDR_EXT_W 0xEA #define IP5365_ADDR_EXT_R 0xEB /* 单字节写返回 0 成功-1 表示某个 ACK 没等到 */ int ip5365_write_reg(uint8_t dev_w, uint8_t reg, uint8_t val) { i2c_start(); if (i2c_send_byte(dev_w) ! ACK) goto fail; /* 写地址R/W0 */ if (i2c_send_byte(reg) ! ACK) goto fail; /* 8bit 寄存器地址 */ if (i2c_send_byte(val) ! ACK) goto fail; /* 8bit 数据MSB 先出 */ i2c_stop(); return 0; fail: i2c_stop(); return -1; } /* 单字节读中途必须 Restart不能先 Stop 再 Start */ int ip5365_read_reg(uint8_t dev_w, uint8_t dev_r, uint8_t reg, uint8_t *val) { i2c_start(); if (i2c_send_byte(dev_w) ! ACK) goto fail; /* 先立地址指针 */ if (i2c_send_byte(reg) ! ACK) goto fail; i2c_start(); /* Restart保持总线 */ if (i2c_send_byte(dev_r) ! ACK) goto fail; /* 读地址R/W1 */ *val i2c_recv_byte(NACK); /* 最后一字节回 NACK */ i2c_stop(); return 0; fail: i2c_stop(); return -1; } /* 读-改-写只动 mask 覆盖的位其余位保留读回值 */ int ip5365_update_bits(uint8_t dev_w, uint8_t dev_r, uint8_t reg, uint8_t mask, uint8_t value) { uint8_t old; if (ip5365_read_reg(dev_w, dev_r, reg, old) ! 0) return -1; uint8_t neu (uint8_t)((old ~mask) | (value mask)); if (neu old) return 0; /* 值没变就不写省总线也省寄存器写寿命 */ return ip5365_write_reg(dev_w, reg, neu); }mask描述哪些位归我管value是这些位的目标值两者按位与之后再或上原值未被 mask 覆盖的位原样保留。函数末尾那句值没变就不写值得保留I2C 总线在移动电源这种强干扰环境里不是绝对可靠的少一次写就少一次翻车机会而且寄存器写次数本身也不是无限的。dev_w和dev_r成对传入而不是让函数内部自己算dev_w 1是有意的。因为这颗芯片的寄存器分散在两组地址上调用点必须明确写清楚这个寄存器属于哪一组把地址归属做成调用签名的一部分比在注释里写一行注意本寄存器在 0xEA 组要可靠得多。4. 寄存器不是配置表而是控制树从总闸到端口的三级开关把 60 多个寄存器按地址顺序读一遍很容易觉得这是一堆平铺的开关。实际上它们组成了一棵三层控制树最上面是系统级的使能与策略中间是轻载关机的判定逻辑最下面才是每个输出口的独立开关。理解这个分层比记住任何一个寄存器的地址都有用因为你调任何一个口的行为都要先确认上面两层没有把它覆盖掉。4.1 总闸与拔电策略En_Boost、En_Charger、En_C2B_DetSYS_CTL00x00主组 0xE8是整个芯片的总闸低三位分别是 En_Chargerbit0充电使能、En_Boostbit1升压输出使能和 En_C2B_Detbit3:2拔掉输入充电后是否自动转 Boost。前两个是布尔开关复位值都是 1也就是上电默认既能充也能放。第三个才是真正带策略的字段。En_C2B_Det 的编码是 00、01、1X 三档00 表示无论输出有没有负载拔掉充电器后都自动开 Boost01 表示只有输出口检测到负载才开 Boost没负载就进关机以 1 开头的两个值行为相同都是不转 Boost、直接进待机。这种1X的写法是省寄存器位的老手段两个编码合并成一个语义读取的时候不要以为是文档写漏了。这个字段的默认值是 00也就是拔线即升压。对常开的移动电源产品这是合理默认但对带小电流负载的产品就是功耗陷阱设备拔走后 Boost 还在空转直到轻载关机逻辑把它关掉。所以调这块的时候00 和 01 的选择实际上是在响应速度和待机功耗之间做取舍而不是在调一个功能开关。4.2 轻载关机系统级与端口级的双重判定轻载关机是这颗芯片里逻辑最绕的一块因为它有两套并行的判定一套看整机一套看单个口。系统级在 SYS_CTL10x03和两个阈值寄存器上。首先要选看什么En_Ipow_Lowbit3让系统看 VSYS 功率En_Isys_Lowbit2让系统看 VSYS 电流默认只开电流这一路。然后是阈值多少POW_LOW0x44的 6 个 bit 定义POW_LOW 17.7 * N毫瓦ISYS_LOW0x45的 6 个 bit 定义ISYS_LOW 5.4 * N毫安N 最大 63也就是功率阈值最高约 1.1W、电流阈值最高约 340mA。最后是多久算轻载Set_Ilow_Timebit5:4给 8S、16S、32S、64S 四档默认 10 对应 32S。端口级在每个输出口的 CTL1 寄存器里。VOUT1_CTL10x13、VOUT2_CTL10x17、VBUS_CTL10x1B、VIN_CTL10x53结构几乎一致bit3:2 是本口的轻载关断时间2S、4S、8S、16S 四档比系统级的档位更短更细bit1 和 bit0 分别是充电状态下轻载关本口和放电状态下轻载关本口的独立使能。阈值则在各口的 IMOSLOW 寄存器里IMOS_LOW 2.68 * N毫安8 个 bit 覆盖 0 到 683mA步进比系统级的 5.4mA 细一倍。为什么要做两级因为它们的职责完全不同。系统级回答整机是不是该睡了它关心的是电池别被白白耗光端口级回答这个口上还有没有设备多口输出时哪个口空了就关哪个口的 MOS把开关损耗和静态电流省下来。步进做得更细也是同一个原因手表、耳机这类设备的充电电流只有几十毫安2.68mA 的分辨率才能把它们和真的空载区分开用 5.4mA 的步进容易误杀。4.3 端口三件套 DCP / QC / MOS 为什么拆成三个位每个输出口都有三个独立开关En_VoutX_Dcp 控制普通 5V DCP 输出En_VoutX_qc 控制快充能力En_VoutX_mos 控制 MOS 输出通路。以 VOUT1_CTL00x10为例bit3 是 DCP、bit2 是 QC、bit0 是 MOS复位值全是 1。VOUT2 在 0x14VBUS 在 0x18VIN 在 0x50扩展组 0xEA结构完全对称。拆成三个位而不是一个口使能是因为它们处在协议栈的不同层。MOS 是物理层关掉等于把这个口从电路上断开后面挂什么设备都测不到QC 是协议层关掉之后口上还有 5V但不会走快充握手DCP 是基础充电能力关掉就只剩协议不通的裸电压。调试时最典型的症状是口上有 5V但手机就是不快充——这种时候先看 QC 位是不是被清了而不是怀疑协议芯片坏了。再往下还有两个检测使能容易混淆。En_VoutX_DmDp_Det 在 VOUT1_CTL20x1C、VOUT2_CTL20x1D、VBUS_CTL20x1E里走的是 D/D- 上的负载识别而 En_VoutX_VDet 在扩展组的 0x4D 里手册专门注明不控制 DM DP 检测。更省空间的是VOUT1_CTL3 和 VOUT2_CTL3 共用 0x4D 这一个字节bit0 归 VOUT1、bit1 归 VOUT2。写这个寄存器的时候如果用了整字节写顺手就把隔壁口的配置改了——这正是读-改-写必须贯彻到每一次写操作的原因。4.4 欠压环路与充电超时把能充约束成不出事CHG_CTL0 到 CHG_CTL2 三个寄存器管的是输入欠压环路电压也就是输入电压跌到多少时开始回退充电电流。12V 输入有 8 档从 10.7V 到 11.8V默认 011 对应 11.4V9V 输入 8 档7.98V 到 8.80V默认 100 对应 8.58V5V 输入的 5V_Uvloop 也是 8 档4.46V 到 4.92V默认 001 对应 4.54V。这些档位的存在意义在于线材劣质线缆的内阻在 2A 电流下能压掉几百毫伏环路点定得太高会频繁触发降流定得太低又会让适配器被拉到保护点以下。CHG_CTL2 里还多一个 Ppath_Uvloopbit5:3默认 111 对应 4.92V。这个值比同寄存器的 5V_Uvloop 高因为同充同放时输入要同时喂系统和电池环路点必须留更大余量否则一插充电器就掉压。超时控制分在两个寄存器。CHG_CTL30x21的 Set_chg_time 是总充电超时0 为关闭1 到 7 分别对应 12、18、24、30、36、42、48 小时默认 100 即 30 小时。CHG_CTL40x22拆得更细bit6:4 是 CV 阶段超时默认 011 即 4 小时bit3:1 是涓流阶段超时默认 001 即 2 小时。涓流超时是最容易被忽略的一项但它的安全意义最大电芯长期停在低压区时涓流会一直往里灌超时机制就是防止这种状态无限持续。4.5 25mA 步进背后的校准语义寄存器值是相对量所有充电电流寄存器用的都是同一个公式I 25mA * N。但每个寄存器的描述后面还跟了一句校准值为 X 左右如需要调整时可在校准值上增加或者减小相应档位。这句话是全篇最重要的设计事实寄存器值描述的是相对量不是绝对量。清单摊开看就很清楚CHG_CTL50x26的同充同放电流校准值约 0.5ACHG_CTL60x27的 12V VIN 约 1.5ACHG_CTL70x28的 5V VIN 约 2.9ACHG_CTL80x29的 5V VBUS 约 2.9ACHG_CTL100x2B的 9V VIN 约 2ACHG_CTL110x6E的 12V VBUS 约 1.5ACHG_CTL120x6F的 9V VBUS 约 2A。7bit 上限 127对应 3.175A这是单路电流的硬顶。校准值三个字意味着出厂时这颗芯片的实际本文还有配套的精品资源点击获取