资讯动态

HLW8112计量芯片实战:硬件搭建、UART解析与校准经验

发布时间:2026/9/10 0:38:57 来源:尧图企业网站定制
简介基于STM32F4系列MCU通过SPI接口驱动HLW8112电流电压传感器的完整Keil工程示例。资源面向嵌入式开发者和能源监测项目解决实际项目中电流/电压采集的软硬件协同问题演示从GPIO复用配置、SPI模式选择、NSS片选管理到HLW8112读写时序的整套实现适合需要快速上手电能计量或传感器调试的读者。包内共191个文件以C源文件47个和头文件45个为主辅以Keil工程配置uvproj/uvopt及编译生成的axf、hex、o等文件压缩包约6.51MB解压后可直接用Keil打开工程并仿真或下载验证其中还包含若干备份文件与批量清理脚本方便工程维护与二次开发。已有2429人学习和下载说明该示例对实践者有实际参考价值。通过对SPI通信协议和HLW8112寄存器操作的源码研读可以快速移植到自己的项目中减少底层调试时间是一份兼顾实用性和完整性的参考代码。 把HLW8112_IU.zip从FAE手里接过来的时候我第一反应是直接解压烧例程。后来发现这个压缩包的名字本身就是最小的一份产品需求文档I 是电流U 是电压IU 就是这颗芯片要做的全部事情——把交流线路里的电流电压变成一串能解析的数字。如果你最近在做智能插座、智能断路器、充电桩或者任何需要统计电量的设备大概率会在选型表里碰到 HLW8112 这颗单相双路计量芯片。这篇内容不是把数据手册翻译一遍而是我从“拿到这个包”到“串口出数、精度校完、能上产线”的完整过程。我不会事无巨细念说明书只讲真正卡过人的地方硬件怎么搭、串口帧怎么拆、校准系数怎么算、以及一例串口全是0xFF的完整排查过程。新手可以照着走一遍流程老手可以重点看第五、六节的坑和量产经验。1. 一个ZIP包背后的芯片画像为什么先看这两页1.1 文件名里的 IU 到底是什么很多工程师第一次看到HLW8112_IU.zip会以为只是厂家随手起的名字其实不是。I 在工程里通常指 CurrentU 指 Voltage德语体系里电压符号就是 U所以 IU 直接点明了这颗芯片的计量对象电流和电压。这颗芯片本质上是一个带 ADC 的计量前端。交流电压、电流先经过外部采样网络变成芯片输入引脚上的小信号然后由内部 Sigma-Delta ADC 做数字化再通过数字逻辑算出电压有效值、电流有效值、有功功率、能量等参数最后经 UART 主动上报给 MCU。外部不需要晶振内部集成基准源所以一个插座方案里芯片周边真正需要的阻容元件数量很少这也是它适合做智能设备计量部分的原因。拿到这个压缩包我建议你先别急着解压看代码而是先把数据手册翻到两个固定位置一个是电气特性表确认供电电压、ADC 输入范围、UART 电平另一个是寄存器映射表确认每一帧数据里各字段的排列顺序和换算公式。这两页看明白后面几乎不会走弯路。1.2 芯片内部是怎么把模拟量变成数字量的HLW8112 这类计量芯片的采样链路可以拆成四段输入引脚 - 增益放大器 - Sigma-Delta ADC - 数字滤波与计算。电流通道输入的是电流采样电阻或电流互感器二次侧产生的差分小电压信号典型幅度在毫伏级别。电压通道输入的是电阻分压网络从火线取来的分压信号同样以差分形式进入芯片。两路信号经过内部 PGA 放大后进入 ADCADC 以很高的过采样率把模拟量转成数字流再经过数字滤波器得到稳定的有效值和功率。这四段里最容易出问题的其实是第一段外部采样网络的设计。芯片本身精度可以做得很好但如果你把采样电阻选大了功耗和温漂都会上来选小了小电流工况下信噪比又不够。这个我在第 2 节重点说。1.3 同门兄弟对比选型时怎么区分做计量方案时经常有人把 HLW8012、HLW8032 和 HLW8112 混在一起问我整理了一个对比型号输出方式典型场景注意点HLW8012脉冲频率输出纯硬件计量、不需要MCU读数的场合MCU需要测频率或脉宽精度依赖定时器HLW8032UART 单路计量输出单路插座、简单功率统计单路采样报文解析简单HLW8112UART 双路计量输出双路负载统计、剩余电流监测等双通道同时采样需注意通道间串扰HLW8112 相对前面两款的差异主要是“双路”意味着一个芯片就能同时盯两路电流或者一路电流加一路电压的组合这在需要同时监测主副回路的设备里很有用。具体到你这个包里的型号是哪种后缀以手册首页丝印和封装图为准。2. 点亮之前先把硬件摆平引脚、采样网络和串口电平2.1 典型应用电路怎么搭HLW8112 的典型应用电路并不复杂交流输入端经过保险丝进入采样网络电流信号通过锰铜分流器或电流互感器接到芯片的电流通道正负输入引脚电压信号通过电阻分压网络接到电压通道输入引脚芯片供电由辅助电源提供稳定的 3.3V 或 5VTXD/RXD 两根线接 MCU 串口。这里面有几个容易忽略的细节VDD 退耦电容一定要靠近芯片引脚。计量芯片内部 ADC 对电源纹波很敏感0.1uF 陶瓷电容必须放在 VDD 和 GND 引脚旁边再配合一个 10uF 左右的电解电容做低频退耦。芯片的 UART 是主动上报模式也就是上电稳定后芯片自己会定时往外发数据帧MCU 不需要发命令去“问”它。这个特性决定了你调串口时会看到源源不断的帧数据如果一直收不到问题反而好定位。串口模块或者 MCU 的 GND 必须和芯片 GND 共地。很多调试时读数乱码、完全无数据的问题最后都出在共地上。2.2 采样电阻和分压电阻的计算思路电流采样的常用方案有两种锰铜分流器和电流互感器。锰铜便宜、体积小适合中小功率设备电流互感器带隔离、适合大电流或安全要求高的场景。以锰铜方案举例假设产品额定电流 10A选择 1mΩ 的锰铜电阻那么满载时采样电阻上的压降是U I × R 10A × 0.001Ω 10mV这个 10mV 会作为差分信号送到电流通道正好落在芯片常见输入范围内。同时要注意采样电阻的功耗P I² × R 100A² × 0.001Ω 0.1W所以 1mΩ 的采样电阻至少要选 0.25W 封装才算留了余量如果额定电流到 20A功耗会到 0.4W必须换成更大功率的合金电阻或者改用互感器方案。电压采样一般是电阻分压。220V 有效值的市电峰值约 311V不能直接进芯片需要先用大阻值电阻限流、再用小阻值电阻取样。具体分压比以数据手册给出的最大差分输入电压为基准来算常见设计是让电压通道的输入信号在额定电压下处于满量程的 60%-80% 左右这样既保证分辨率又留出了过压余量。计算时把电阻网络的总功耗也估算一下避免电阻发热影响阻值稳定。2.3 串口电平与上电时序HLW8112 的串口输出电平一般跟随芯片供电电压供电是 3.3V 时输出就是 3.3V 逻辑。如果 MCU 是 5V 系统建议确认引脚是否兼容最好加电平转换或至少加串联电阻限流。我见过不少直接把 5V 单片机 RX 引脚连芯片 TXD 的案例短时间没烧但长期可靠性没人能保证。上电时序也是老问题。计量芯片内部需要一点时间完成复位和自校准通常在上电后要等一段时间才会稳定输出数据帧。如果芯片还没准备好、MCU 就开始收串口数据收到的往往是一堆0xFF或者残帧。调试时建议在 MCU 初始化串口之前加 10ms 以上的延时或者直接看逻辑分析仪上第一帧完整数据出现的时间。3. UART报文拆解从一帧原始数据到可读的电压电流功率3.1 先找到帧头再谈解析HLW8112 这类芯片的串口数据是固定格式的帧芯片上电后会按照设定周期持续往外发。解析时最忌讳的做法是拿到一个字节就当成某字段的高位去处理——一旦某一帧中间丢了一个字节后面所有数据都会错位而且很难排查。正确做法是使用帧头同步逐字节搜索帧头特征值常见为0x55或0xAA具体看手册。找到帧头后按固定帧长度接收后续字节收满一帧。对整帧做校验和常见为所有字节累加取低 8 位校验通过才解析不通过直接丢弃。使用 USB 转 TTL 工具先接在芯片 TXD 上看原始十六进制数据是最快的确认方法。因为芯片是主动上报模式串口助手里应该能看到周期性的帧如果在串口助手这一层就已经乱码说明物理链路还没通后面写 MCU 代码也是白费。3.2 寄存器的原始码值怎么换算成物理量帧里的电压、电流、功率数据一般不是直接的十进制小数值而是一个与满量程相关的原始码值。以电压为例手册里通常会给出类似这样的换算关系物理量 原始码值 × 电压系数这里的电压系数由芯片内部参考电压和外部电阻分压比共同决定不同的硬件设计会得到不同的系数。开发时你不需要自己推导完整公式但要养成一个习惯把手册里的所有换算系数提取成常量集中放在头文件里后续校准只需要修改一个系数宏而不用满代码找魔法数字。下面给一段演示用的帧布局说明解析逻辑实际型号的帧长和字段排列一定以你手里的手册为准#define FRAME_LEN 10 typedef struct { uint8_t head; // 帧头例如 0x55 uint8_t voltage_h; // 电压原始值高字节 uint8_t voltage_l; // 电压原始值低字节 uint8_t current_h; // 电流原始值高字节 uint8_t current_l; // 电流原始值低字节 uint8_t power_h; // 功率原始值高字节 uint8_t power_m; // 功率原始值中字节 uint8_t power_l; // 功率原始值低字节 uint8_t status; // 状态寄存器 uint8_t checksum; // 校验和 } hlw8112_frame_t;3.3 参考代码状态机收帧与解析打印MCU 侧解析帧推荐用状态机写法代码可读性和稳定性都更好static uint8_t rx_buf[FRAME_LEN]; static uint8_t rx_idx 0; static uint8_t sync_flag 0; void uart_rx_isr(uint8_t data) { if (sync_flag 0) { // 等待帧头 if (data 0x55) { sync_flag 1; rx_idx 0; rx_buf[rx_idx] data; } } else { rx_buf[rx_idx] data; if (rx_idx FRAME_LEN) { sync_flag 0; if (checksum_ok(rx_buf)) { process_frame(rx_buf); } } } } static void process_frame(uint8_t *f) { uint16_t voltage_raw (f[1] 8) | f[2]; uint16_t current_raw (f[3] 8) | f[4]; uint32_t power_raw (f[5] 16) | (f[6] 8) | f[7]; float voltage voltage_raw * VOLTAGE_COEF; float current current_raw * CURRENT_COEF; float power power_raw * POWER_COEF; printf(U%.2fV I%.3fA P%.2fW\n, voltage, current, power); }这段代码不是让你直接复制成最终产品它演示的是收帧、校验、提取、换算这四个核心步骤。实际项目里我会把VOLTAGE_COEF这些系数做成可校准的变量存在 MCU 内部 Flash 里量产出厂时每台写入自己的校准值。4. 校准和滤波让读数从“有”变“准”4.1 为什么出厂读数不能直接用很多人把芯片例程跑通看到电压 220.1、电流 0.998 就觉得完事了其实这个数值大概率不是准的。原因是芯片内部基准存在器件偏差同一型号不同个体之间有离散。外部采样电阻本身有精度误差1% 精度的电阻就会直接带来 1% 的读数偏差。电阻分压网络的比例误差、线路压降、PCB 走线阻抗也会叠加进去。所以对于做智能插座、计量插排这类带计费或统计功能的产品端到端校准是必须的一步。校准的意思是用标准仪器和标准源作为参考反过来修正设备自身的读数误差。4.2 单点校准系数的完整计算过程最常见的校准方法是单点增益校准。拿一个精度足够高的功率计或标准源给设备接一个固定负载记录标准值和芯片未校准读数然后算系数假设标准功率计读数是 1000.0W此时芯片解析出来的未校准功率是 978.3W那么校准系数 K 标准值 / 未校准值 1000.0 / 978.3 1.0222后续显示功率 未校准功率 × K 978.3 × 1.0222 ≈ 1000.0W对电压和电流也分别做同样的操作会得到三个系数电压系数、电流系数、功率系数。注意功率系数不一定要等于电压系数乘以电流系数因为你做的是端到端修正它已经包含了所有误差来源的综合影响。校准完再把系数存下来。我习惯的做法是在产测工位上用标准源给设备供电。设备进入校准模式自动采集 N 帧数据取平均。上位机把标准值发给设备设备内部算出系数写入 Flash。设备退出校准模式重新上电后读数即已修正。这里有个容易踩的坑校准时的功率因数会影响功率校准系数。如果产品需要覆盖不同性质负载阻性、感性、容性最好分别在纯阻负载和滞后的感性负载下校准和验证而不是只在一个功率因数下校完就完事。4.3 软件滤波与空载死区即使硬件和校准做完读数在轻负载或者电源质量不太好的情况下依然会有明显的跳动。这时候需要软件滤波。我常用的是一阶低通滤波y[n] (1 - α) × y[n-1] α × x[n]其中x[n]是当前采样值y[n-1]是上一次滤波输出α是滤波系数取值 0 到 1。α 越小滤波越平稳但响应也越慢α 取 0.2 左右在功率统计场景里通常兼顾了稳定性和响应速度。对于更新频率比较高的计量芯片也可以直接做滑动平均比如把最近 16 帧的功率值取平均效果很直接。还有一个细节空载时的零点漂移。芯片在无负载时理论上电流应为 0但因为 ADC 噪声和零点偏移可能会读到几毫安甚至几十毫安的“假电流”累积下来就是虚假电量。产品里一般要做死区处理当电流有效值小于设定阈值比如 30mA时电流显示为 0。当功率小于设定阈值比如 2W时功率显示为 0。死区阈值不要设太大否则小功率负载会被误判为空载这个值需要针对你的采样电阻和芯片实测噪声底来标定。5. 串口全是0xFF的一次完整排查从示波器到最终根因5.1 问题现象与第一判断有一次调试 HLW8112 方案板子贴片回来后上电MCU 串口打印出来的全是0xFF偶尔夹几个0x00完全看不到帧头。按经验这种问题有几种可能芯片供电不正常芯片根本没有工作。芯片在复位状态里没起来。TXD 引脚没有数据输出。串口接线错误把 TXD 和 RXD 接反了。MCU 串口配置不对波特率或者电平不匹配。但最忌讳的就是在没确认物理层的情况下反复改代码。我当时的第一步不是看代码而是拿示波器直接点在芯片 TXD 引脚上看波形。5.2 一步步缩小范围排查过程可以分成四个层次示波器点 TXD 引脚如果 TXD 引脚上没有任何波形说明问题在芯片侧不在 MCU 代码侧。量 VDD 电压和纹波示波器看 VDD 是否稳定在 3.3V有没有明显的跌落或振铃。检查焊接和引脚连接用万用表蜂鸣档逐个量芯片供电引脚和 GND 是否确实连到了对应网络。用逻辑分析仪抓原始波形如果波形存在但 MCU 读不到抓一帧下来看起始位、数据位、停止位和波特率是否正常。那次实战中问题出在供电上。芯片 VDD 引脚旁边有一颗 0.1uF 电容但位置离引脚远了大约 1cm走线上又绕了一圈导致开关电源上电瞬间在 VDD 上产生了明显的振铃芯片上电复位没有完成TXD 引脚一直保持高电平MCU 收到的自然全是0xFF。处理方式并不复杂把退耦电容移到靠近 VDD 引脚的位置同时在 MCU 初始化里增加了 20ms 的上电等待延时问题就消失了。5.3 其他容易翻车的点调试计量芯片时还有几个问题我几乎每次都能在论坛或者群里看到芯片方向焊反。SOP 封装的小芯片一脚方向错了上电后芯片发烫数据肯定出不来赶紧断电检查。TX/RX 接反。芯片 TXD 要接 MCU 的 RX反过来接是收不到数据的。共地问题。用 USB 转 TTL 调试时TTL 模块的 GND 和板子的 GND 必须连在一起不然数据链路是断的。波特率偏差过大。芯片内部振荡器精度有限如果手册建议 9600实际使用 9600 没问题但如果你图省事用了与推荐值偏差过大的波特率比如 4800 或 19200容易产生误码。强干扰导致帧错乱。继电器吸合、大功率负载切换瞬间如果串口线过长且没有保护数据帧会被打乱。串口线上串联一个 33Ω 到 100Ω 的电阻以及加 TVS 管能明显改善。6. 资料包里不会写、但我现在离不开的几个量产细节6.1 PCB布局的三个顺手建议在画 HLW8112 方案时PCB 布局直接决定后期调测是否顺利我总结了三个原则采样网络靠近芯片输入引脚。锰铜电阻或电流互感器到电流通道引脚的走线尽量短避免在 PCB 走线上引入额外电阻和噪声。模拟地与数字地单点连接。采样地、芯片 GND 与 MCU 系统地之间用一个小电感或者 0Ω 电阻单点连接能减少数字噪声对计量精度的影响。电源线加宽。芯片 VDD 走线不要太细至少 10mil 以上并在芯片附近做π型滤波能明显降低开关电源纹波带来的读数波动。6.2 量产一致性校验HLW8112 芯片本体的精度离散其实不大但外围采样电阻、分压电阻的误差会直接反映到最终读数上。所以量产时我强烈建议做整机校准而不是只校准芯片采样链路。具体做法是生产测试工位上给每台设备通标准源上位机自动读取设备上报的电压电流功率计算出每台设备的校准系数然后通过串口或烧录器写入设备的 Flash。虽然增加了产测时间但能换来整机精度的稳定对做计量类产品来说非常值。6.3 双路计量通道间的串扰如果用 HLW8112 做双路计量通道间串扰是一个需要验证的指标。简单说就是一路在带大负载时另一路空载读数会不会被带偏。我见过实验室单路测试精度很好但双路同时满载时轻载那一路出现几十毫安读数的情况。验证方法不难A 路接额定负载、B 路空载对比 B 路的零漂然后反过来再看 A 路。如果串扰超标首先要看 PCB 布局两路采样信号的走线是否距离太近其次确认两路采样网络的地是否合理分开。排除了布局问题再考虑芯片本身的指标限制。最后分享一个小经验调试这种带串口主动上报的计量芯片别急着写复杂的 UI 和存储逻辑先把原始帧用串口助手打出来确认数据链路稳定了再开始做解析、校准、滤波这些上层工作。数据链路一天不通后面所有工作都会在假象上叠楼查起来非常痛苦。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价