ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

NU1680在TWS耳机无线充电仓中的Qi协议适配与I2C调压实战解析

NU1680在TWS耳机无线充电仓中的Qi协议适配与I2C调压实战解析 干这行快十年了做过的无线充电项目没二十个也有十五个但NU1680这颗芯片在我心里的地位一直很特殊。TWS耳机充电仓的无线化方案我前后试过好几套有的方案外围电路复杂得能塞下半块木板有的方案协议栈封装得太死想调整输出都得重新流片一般。NU1680的出现算是把这中间的平衡点找到了——它把QI协议栈和整流稳压全集成进去又留了I2C接口让你能动态调压刚好踩在TWS耳机这类小体积、高集成度产品的刚需上。这篇就结合我个人实际跑过的项目把NU1680在TWS耳机里的应用从头到尾拆一遍重点讲I2C调压怎么实现、QI协议怎么适配、硬件怎么布局不出问题最后把调试中踩过的坑一一罗列出来。打算做无线耳机、智能手表充电底座、或者其他Qi标准小功率接收端的工程师朋友这篇应该能帮你少走不少弯路。1. NU1680这颗芯片到底解决了什么问题1.1 从TWS耳机充电仓的无线化说起TWS耳机这波浪潮起来之后充电仓的形态经历过好几次迭代。最早是Micro-USB后来换成Type-C再往后大家发现耳机仓本身就是一个天然的“无线充电接收端”——你把它放在一个发射板上仓里的接收线圈就能给耳机仓内部的电池充电。这个场景听起来简单但实现起来很拧巴耳机仓内部空间多一毫米都挤电池要占大头电路板要薄线圈还要贴在壳子上。你不可能像做手机无线充电底座那样堆一个大功率方案进去5W以内才是这个场景的安全区。而且耳机仓的电量管理逻辑比手机复杂耳机放进去要充电耳机仓本身要给手机反哺电量部分高端产品还要兼顾充电仓自身的MCU、灯效、霍尔传感器这些外设的供电。这就要求无线充电接收端不仅能稳定输出还得能动态调整输出电压配合后级充电管理IC完成不同阶段的充电策略。早期做法是接收端固定输出5V后面再挂一颗升降压和一个充电IC但这套方案在外围面积和成本上都吃亏。NU1680这类高度集成的接收芯片把整流、稳压、协议处理全收进去通过I2C直接动态配置输出电压自然就成了更优解。1.2 NU1680内部架构与核心资源我第一次拿到NU1680的规格书时第一反应是“这芯片把系统设计师的活抢了”。它内部集成了同步整流控制器、线性稳压或者DC-DC调整管、QI协议物理层和协议栈、以及一个I2C从机接口。从外面看你只需要接一个接收线圈、一个谐振电容、一个输出滤波电容再加一个I2C总线连接到主控MCU整个无线充电接收路径就齐了。具体到信号链路上接收线圈感应到高频磁场产生交流电压经过内部同步整流变成直流再通过内部调整管稳定输出。QI协议的部分由芯片内部的协议引擎自动处理包括数字ping的应答、信号强度上报、通信握手、控制误差包响应和异物检测(FOD)相关计算。这些原本需要MCU实时处理的流程NU1680自己就完成了主控MCU只需要定期通过I2C查询状态、读取功率数值、配置输出电压即可。1.3 为什么不用普通整流充电方案可能有朋友会问我直接用二极管整流桥加一颗LDO再接一颗充电IC不行吗答案是不行而且差很远。二极管整流的压降在低电压大电流场景下损失太惨无线充电接收线圈输出的交流电压通常只有几伏二极管每路压降按0.4V算全桥就是0.8V效率直接掉到70%以下5W输入最后能充到电池里的大概只有3W多一大半变成热量。更重要的是QI协议需要一个完整的物理层通信机制接收端要通过调制线圈负载来向发射端“说话”这个过程叫ASK幅移键控发射端则通过改变磁场频率来给接收端“回话”叫FSK频移键控。这些通信全部要按QI标准协议栈的时序来走。你自己用MCU实现需要实时监控线圈上的信号变化在几毫秒甚至几微秒的时间窗口内完成解调与应答普通MCU做起来非常吃力实时性和稳定性都不好保证。NU1680把这件事固化在硬件逻辑里可靠性完全不是一个量级。2. QI协议适配是第一步从握手到功率传输2.1 QI协议的关键包结构现实的工程经验是先把QI协议跑通了后面的I2C调压才有意义。NU1680虽然集成协议栈但你不了解协议流程出了问题连排查方向都没有。QI协议最核心的阶段可以理解为握手与会话模拟ping阶段发射端检测到接收端放在上面尝试建立连接。数字ping阶段发射端发出更大的能量脉冲接收端必须在这个窗口内返回信号强度包SSP否则发射端会认为没有合法接收设备重新回到待机。识别与配置阶段接收端发送ID包、配置包发射端据此确认功率等级BPP 5W或者EPP更高功率档位。功率传输阶段接收端持续发送控制误差包CE来告诉发射端“功率太强了减一点”或“太弱了加一点”同时定期发送电量包RP汇报接收功率用于FOD异物检测。结束阶段接收端发送结束功率传输包EPT正常结束充电。NU1680在握手阶段的表现很稳但前提是外围谐振参数要对否则接收端线圈在当前工作频率上得不到足够的电压SSP包的数字就不对发射端会认为接收端“不存在”。这个坑我踩过一次后面会展开说。2.2 谐振网络参数匹配实战谐振网络是无线充电接收端最容易出问题的地方。接收线圈本身有一个电感量通常会在接收端并联一颗谐振电容让线圈和电容在某个目标频率上产生并联谐振这样在磁场作用下可以感应出更高的电压。选电容的计算很直接就是用LC谐振公式f 1 / (2×π×√(L×C))比如说你用的接收线圈在100kHz附近电感量实测为12μH把频率定在110kHz左右求CC 1 / (4×π²×f²×L) 1 / (4×9.8696×(110000)²×0.000012) ≈ 174nF实际取值可以选择两颗普通X7R电容并联凑整比如100nF68nF168nF或者120nF47nF167nF误差完全可以接受。这里注意不要用高容量的MLCC直接单颗怼上去陶瓷电容的直流偏压特性会让容量在电压升高后大幅下降。我习惯用两个并联既调整容量又分摊电流应力。注意线圈电感会受周边金属件影响而漂移。耳机仓内电池、屏蔽罩、结构件都会改变等效电感。所以一定要把线圈贴在最终结构件上实测电感再反推谐振电容不要看规格书的标称值直接算。2.3 功率协商与FOD调试要点功率协商这部分NU1680内部已经闭环了发射端发来的功率调整命令它会在内部自动更新CE包。但FOD异物检测是一个需要应用层介入的点。发射端会默认接收端上报的功率和发射端自己送出的功率是吻合的如果差值超过阈值就认为中间有金属异物在吸收功率立即停止充电。问题出现在哪里呢接收端实际接收到的功率和发射端计算出的功率本身就存在误差。线圈对位偏移、接收端负载突变、甚至是充电仓内电池充饱后负载变小都会让差值变大。如果你的产品放在金属桌面上充电误报FOD的概率会更高。我处理FOD问题的方法是在NU1680的应用层配置里把FOD阈值根据实测结果做校准。具体做法是在正常充电场景下用电流探头和功率计同时测发射端输入功率和接收端输出功率把差值数据记录下来然后对应调整阈值。NU1680允许通过I2C读取实时接收功率配合上位机建立一份“功率差基线表”再把阈值设定为基线值加一点余量比如0.5W这样既能防异物又不会频繁误停。3. I2C调压机制深度拆解3.1 I2C在NU1680里的角色I2C总线在本项目里的角色一句话概括就是“应用层与协议层之间的桥梁”。主控MCU不需要也不可能直接干涉QI物理层的实时时序它只需要通过I2C向NU1680询问“你现在输出的是多少伏”“功率如何”“温度多少”以及下发“把输出电压调到4.35V”这样的指令。对比一下常见的几种串行总线就明白了UART是收发双方的异步传输没有时钟线靠波特率对齐适合点对点SPI是主从同步全双工速度快但至少4根线还要片选I2C只需要两根线SDA和SCL用地址区分设备适合一条总线上挂多个从机。NU1680在耳机仓系统里往往和触摸IC、霍尔传感器、电量计IC串在一条I2C总线上这种多设备共享总线的场景I2C天然合适。而且7位地址模式下能挂128个设备一个耳机仓主板上那点外设绰绰有余。3.2 开漏输出与上拉电阻的底层逻辑I2C总线物理层采用“开漏输出上拉电阻”结构这算得上是最经典也最容易被轻视的设计。开漏的意思是芯片内部的MOS管只负责把总线拉低灌电流不负责主动输出高电平高电平完全依靠外部上拉电阻把总线拉到供电电压。这样的好处有两个第一支持多设备“线与”操作任何一个设备拉低总线整条总线就是低电平不会发生两个设备同时输出高低电平导致短路第二可以通过选择不同上拉电阻值改变总线上升沿时间从而适配不同通信速率和总线长度。上拉电阻怎么选不能拍脑袋。I2C协议的快速模式Fast Mode400kHz要求上升时间不超过300ns上升时间由总线等效电容和上拉电阻共同决定公式是tR 0.8473 × R_pullup × C_bus如果总线上挂的设备多、走线长总线电容可能在100pF到200pF。按150pF算要求tR不超过300ns那么R_pullup ≤ 300ns / (0.8473 × 150pF) ≈ 2.36kΩ这是上限。下限则由灌电流能力决定低电平时芯片要能扛住上拉电阻流过来的电流Fast Mode要求IOL最大为3mA供电电压3.3VVOL最大0.4VR_pullup ≥ (3.3V - 0.4V) / 3mA ≈ 967Ω综合上面两个约束1kΩ到2.2kΩ是Fast Mode下的合理区间。我实际项目里NU1680和主控MCU距离很短同一块板子上不超过5cm总线电容很小用2.2kΩ没问题如果中间有FPC软排线连接总线电容变大就换1.5kΩ甚至1kΩ。很多人图省事直接上4.7kΩ低速场景没问题但在400kHz以上或者总线上多挂几个设备时容易出现上升沿过缓波形边缘圆滚滚严重时斜率不够触发阈值通信就时好时坏。提示如果MCU的I2C外设内部有上拉电阻可选建议直接禁用依靠外部上拉。内部上拉一般20kΩ到50kΩ等效并联后对外部上拉影响不大但内部上拉的温度漂移和工艺偏差不好控制不如彻底关掉来得干净。而且有些MCU在I2C模式下内部上拉逻辑复杂开着反而容易出现莫名奇妙的电流倒灌。3.3 输出电压配置流程与寄存器操作NU1680输出电压调节的基本思路是通过I2C写寄存器来改变内部调整管的参考电压。不同批次、不同封装的NU1680寄存器映射存在差异我这里只讲通用思路具体寄存器的偏移地址和bit定义务必以官方最新数据手册为准。典型流程如下主控MCU发起I2C写操作向NU1680的电压配置寄存器写入目标档位。芯片内部DAC更新参考电压稳压环路经过短暂过渡后把输出电压切换到新目标值。主控MCU通过I2C读取电压状态寄存器确认实际输出电压与目标一致。在TWS耳机场景里我会把调压逻辑和充电状态机绑定电池电量低时需要大电流充电可以把接收端输出电压调高一点给后级充电IC更充裕的压差电量接近充满时电压可以略微降低减少充电电流保护电池。这个策略并不复杂关键是在切换电压时加入延时和保护判断防止热插拔或负载突变造成输出过冲。4. 驱动代码开发与I2C时序验证4.1 通用I2C驱动框架基于MCU如果你用的是STM32的HAL库I2C底层驱动不需要自己操作寄存器HAL已经把时序细节封装好了。问题在于HAL库默认的I2C模式可能是推挽输出而I2C总线要求开漏。如果MCU引脚配置为推挽而外部又有上拉电阻那么MCU输出高电平时总线被拉高输出低电平时总线被拉低逻辑上看起来也能工作一旦总线上有另一个设备也在驱动同一根线就存在短路风险。正确的配置是把SDA和SCL引脚设置为开漏输出GPIO_MODE_AF_OD开启上拉或者依靠外部上拉。以STM32HAL库为例GPIO_InitTypeDef GPIO_InitStruct {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_I2C1_CLK_ENABLE(); GPIO_InitStruct.Pin GPIO_PIN_6 | GPIO_PIN_7; // SCL, SDA GPIO_InitStruct.Mode GPIO_MODE_AF_OD; // 开漏复用功能 GPIO_InitStruct.Pull GPIO_NOPULL; // 外部已接上拉内部不上拉 GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, GPIO_InitStruct);注意GPIO_NOPULL这个选项前面说过外部已经有2.2kΩ上拉内部上拉没意义反而可能引入不确定性。4.2 NU1680读写时序的完整代码下面这段代码是我从项目里简化出来的功能是设置NU1680输出电压并读回确认。注意I2C数据帧的完整时序我写在了注释里方便对照逻辑分析仪抓包验证。#define NU1680_I2C_ADDR 0x24 // 7位从机地址具体以手册为准 #define NU1680_REG_VOUT 0x20 // 输出电压配置寄存器 #define NU1680_REG_STATUS 0x21 // 状态寄存器 #define NU1680_VOUT_4P20V 0x0A // 档位定义示例4.20V #define NU1680_VOUT_4P35V 0x0B // 档位定义示例4.35V static HAL_StatusTypeDef nu1680_write_reg(uint8_t reg, uint8_t val) { // 完整时序 // START - 地址(7bit)W(0) - ACK - 寄存器地址 - ACK - 数据 - ACK - STOP uint8_t buf[2] {reg, val}; return HAL_I2C_Master_Transmit(hi2c1, NU1680_I2C_ADDR 1, buf, 2, 100); } static HAL_StatusTypeDef nu1680_read_reg(uint8_t reg, uint8_t *val) { // 完整时序 // START - 地址(7bit)W(0) - ACK - 寄存器地址 - ACK // REPEATED START - 地址(7bit)R(1) - ACK - 数据 - NACK - STOP HAL_StatusTypeDef status; status HAL_I2C_Master_Transmit(hi2c1, NU1680_I2C_ADDR 1, reg, 1, 100); if (status ! HAL_OK) return status; return HAL_I2C_Master_Receive(hi2c1, (NU1680_I2C_ADDR 1) | 1, val, 1, 100); } int nu1680_set_vout(float voltage) { uint8_t reg_val; uint8_t readback; if (voltage 4.35f) voltage 4.35f; if (voltage 3.50f) voltage 3.50f; // 电压到寄存器值的映射具体的量化步进要看芯片手册 // 这里假设步进50mV起点3.50V对应0x00 if (voltage 4.20f) { reg_val NU1680_VOUT_4P20V; } else { reg_val NU1680_VOUT_4P35V; } if (nu1680_write_reg(NU1680_REG_VOUT, reg_val) ! HAL_OK) return -1; // 回读确认 if (nu1680_read_reg(NU1680_REG_VOUT, readback) ! HAL_OK) return -1; // 加一点回读校验防止写失败导致输出电压停留在错误档位 if (readback ! reg_val) return -2; return 0; }关于写多个字节比如一次配置输出电压、输出限流、工作模式三个寄存器I2C时序是连在一起的START后先发设备地址写位再连续发送多个数据字节中间只有寄存器地址和连续数据最后才发STOP。这种“组合写”的方式比多次重复“START-写-写-STOP”效率高也避免总线中途被其他设备抢占。4.3 用逻辑分析仪验证时序的实操方法代码写完不要急着上板联调先抓波形。我常用的是几十元价位的逻辑分析仪加配套PC软件采样率开到10MHz以上通道一接SCL通道二接SDA地线一定要和板子共地。抓到的波形怎么看首先是起始条件SCL为高电平期间SDA发生高到低的跳变。然后是地址字节前7位是地址第8位是读写标志之后是ACK位从机拉低SDA表示应答。如果逻辑分析仪解码出来的设备地址跟你代码里设置的不一致大概率是地址位数搞错了——很多芯片手册给的是8位地址已经包含读写位而栈代码里写的是7位地址转换时漏掉左移一位这是最典型的低级错误。上升沿的观察同样重要。在波形视图里直接把时间轴拉细看SDA和SCL的上升沿是不是陡峭。如果上升沿弧度很大甚至有个明显的斜坡说明上拉电阻偏大总线电容也偏大可以考虑换小阻值的上拉电阻。另外如果从机发送的ACK一直读不到即第九个时钟周期SDA没有被拉低优先检查地址和电源然后看波形上有没有字节间空隙过大导致的超时。5. 硬件设计实战原理图、布局与协同5.1 典型应用电路详解NU1680的典型应用电路比很多电源芯片还精简。电源路径上接收线圈两端接芯片的AC1/AC2输入脚线圈两端并联谐振电容整流输出脚接输出滤波电容和负载。I2C部分SDA和SCL各接一颗2.2kΩ上拉电阻到3.3V主控电源两个引脚各对地加一颗100pF的小电容用于滤除无线充电时的电磁干扰。有人觉得100pF滤波电容会影响I2C上升沿其实在400kHz下影响很小。上拉电阻2.2k100pF对地电容带来的时间常数约220ns配合上升沿公式计算增加的延迟在可接受范围内收益是显著降低了空间耦合进来的噪声。还有一个容易忽视的器件是TVS管。无线充电线圈在耦合瞬间可能产生很高的尖峰电压即使芯片内部有保护外部在交流输入脚对地加一颗双向TVS更保险。TVS的结电容选小一点的几十pF以内即可太大并联在谐振回路上会影响谐振频率。5.2 PCB布局的散热与抗干扰TWS耳机充电仓的PCB往往是异形板留给无线充电接收部分的空间非常有限。但布局上有几个原则必须遵循第一接收线圈的走线要短粗。线圈到芯片AC脚之间的走线尽量短走线太细太长会引入额外的串联电阻和寄生电感导致接收效率下降。我用0.3mm以上的线宽走线直接在底层铺铜加宽。第二芯片底部的散热焊盘要真正连到地铜皮。NU1680的输出功率虽然只有几瓦但在小空间内热阻大散热焊盘不接地铜皮芯片温度会很容易超过规格。在PCB上把底层铺铜作为散热面多打过孔连接。第三I2C走线远离线圈和功率路径。线圈工作时周围有强磁场I2C线上的感应电压轻则导致通信毛刺重则把SDA钳死。我习惯让I2C走线走内层两侧包地地平面隔离。5.3 与TWS耳机充电仓整体的配合硬件设计不能只看芯片本身还要看它在整个耳机仓系统里的位置。线圈的位置直接决定用户把耳机仓放上充电板时的对位效果。线圈中心最好对准充电仓外壳上标识的充电区域而且线圈下面不能有大面积金属支架或者磁铁否则无线充电磁场的耦合效率会下降FOD误报率升高。电池位置也值得留意。NU1680输出给后级充电IC充电IC放在电池旁边避免长距离大电流走线。主控MCU放在NU1680的另一侧I2C走线不跨过电池和线圈区域。耳机仓的霍尔传感器如果用了磁铁方案磁铁位置要远离接收线圈不然磁铁会吸收磁场能量导致线圈感应电压虚高触发芯片过压保护。从结构角度讲耳机仓上盖一般压着线圈下壳里是电池和主板。这样线圈距离充电板的外壳表面近耦合效率高。但上盖如果是金属材质整个无线充电方案就要重新评估金属会屏蔽磁场。做结构方案之前一定先用实测线圈测试壳料对效率的影响别等到开模了才发现效率不够。6. 常见问题排查与调试经验速查6.1 I2C通信不稳定的典型现象与对策我在多个项目里都遇到过I2C通信“时好时坏”的情况表现是上电第一次读写成功之后偶尔失败复位后又好。排查思路按优先级排列最先是推挽与开漏的冲突。MCU引脚配置成了推挽输出而总线上拉了电阻。推挽输出高电平时直接强驱动外部上拉电阻变成负担低电平时又可能和其他设备抢线表现为偶发通信错误。把引脚改成开漏输出问题立即解决的概率很高。其次是上拉电阻阻值问题。之前已经算过400kHz下4.7kΩ已经偏大如果总线上还挂了其他设备总线电容更大上升沿超时更明显。把上拉电阻从4.7k换成2.2k或者1.5k一般都能改善。最后是电源噪声。NU1680是无线充电芯片工作时线圈切换会在电源上产生毛刺如果MCU的3.3V电源域和NU1680的电路共用一个LDOI2C高电平也会被拉出毛刺。解决办法是给MCU电源单独加一个RC滤波或者在I2C线上加100pF对地电容。注意I2C的SDA线被长时间拉低通常是某个从机在应答后进入异常状态把SDA锁住。排查时先断开所有从机的供电上电看SDA线上是否还有持续低电平。如果有就是总线某一端的开漏驱动没有释放。没有的话逐个接回从机锁定问题设备。6.2 QI充电异常的处理思路QI充电异常最常见的现象是放上充电板完全没有反应指示灯不亮。设备连上逻辑分析仪抓发射端输出的数字ping窗口看接收端是否返回了SSP包。如果没有检查三个地方一是接收线圈是否谐振在发射端工作频率附近如果谐振频率偏了太多感应电压过低芯片无法工作二是接收端输出电压是否稳定如果芯片的LDO输出没有建立起来协议引擎也无法启动三是线圈与发射端的距离TWS充电仓外壳太厚也会导致耦合不足。另一种常见现象是充电一开始过几秒就停止。这种情况多半是FOD误触发。解决办法是校准FOD阈值或者在结构上改善线圈对位。有时候接收端的负载变化也会引起功率差突变比如耳机仓内电池接近充满时电流下降接收功率突然减少发射端会认为功率异常触发保护。可以在配置里增加FOD检测的时间窗口让短时波动不被误判。6.3 批量生产和软件联调中的坑批量生产阶段最容易出现的问题是同一批板子有的I2C正常有的不正常。这种问题基本都是上拉电阻取值处在临界状态或者焊接不良导致的上拉电阻虚焊。我遇到过一整批板子SDA波形都是“斜坡状”最后发现是贴片厂把2.2kΩ电阻错贴成了22kΩ上拉能力差了十倍。所以批量产线最好增加一道I2C通信测试工位让产测程序连续读写100次统计失败率比单纯看功能通过更可靠。软件联调阶段还有一个常见BUG是主控MCU在初始化I2C外设时先对总线上电而NU1680此时还没有完成内部初始化。MCU发出的第一个I2C操作发生在芯片没有准备好应答的状态下收到NACK代码就直接返回错误导致整个初始化流程中断。解决办法是在初始化NU1680之前加一个延时或者MCU读不到ACK时自动重试几次。另外多个从设备挂在同一条总线上时要注意地址冲突。有些触摸IC和电量计IC的默认地址和NU1680相同或者地址距离过近导致寻址错乱。设计阶段一定要汇总所有I2C设备的7位地址确认没有冲突量产阶段如果有物料替代地址也要重新核对。最后分享一个实际的调压心得NU1680的I2C调压不是改完寄存器就万事大吉。输出电压跳变时后级充电IC的输入电容会瞬间吸收大量电流可能触发输出过流保护。我在实际项目里做了一个软件斜坡把电压从3.6V逐步升到4.35V每次升一个档位间隔10毫秒既避开了浪涌又不会让充电IC误判输入异常。这种小细节在产品稳定性上的提升比你去改电路还明显。
返回列表