news 2026/9/2 12:23:34

HX711称重程序设计:从硬件接线到零点追踪的完整实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HX711称重程序设计:从硬件接线到零点追踪的完整实战指南

简介:一份基于51单片机的HX711高精度称重程序工程包,面向嵌入式从业者、电子爱好者及实验室场景,用于解决称重传感器的微弱信号采集与稳定测量问题。程序围绕HX711芯片(24位Σ-Δ型ADC)编写,涵盖初始化配置、数据读取与累计平均、增益调整、软件滤波等核心模块,可直接编译烧录,也可借鉴其轮询逻辑与校准思路。压缩包共15个文件,仅22KB,以C语言源码、HEX烧录文件、STARTUP.A51启动代码及Keil UV2工程文件为主,另有LST列表文件、OBJ目标文件等编译辅助产物,便于查看编译过程与调试信息。目前已有1338人学习下载,程序在多数场合下基本可用,但需要根据传感器量程和灵敏度微调校准系数、时钟延时等参数,适配后即可用于工业配料、实验室称重等场景。整体来看,这套工程轻巧实用,文件组织清晰,既适合新手入门HX711驱动开发,也为二次修改提供了可直接运行的工程基础。 HX711 这个芯片在电子秤、小量程测力、压力检测这些项目里太常用了。不管你是做 Arduino 小玩具、STM32 工控板,还是树莓派扩展模块,只要涉及应变式压力传感器,基本绕不开它。我最初接触 HX711 是为了做一个仓储用的简易称重终端,当时被零点漂移这东西折腾得不轻,后面才彻底搞懂了它的底层逻辑和程序层面的补偿思路。这篇博文就围绕 HX711 称重程序的完整落地流程来写,从硬件接线到代码框架,再到零点追踪的实现细节,最后附上实际调试中遇到的典型坑和排查方法,给正准备做称重功能的朋友一份能直接照着干的参考。

1. 整体设计与选型思路

1.1 为什么选 HX711 而不是其他 ADC

做称重方案时,第一反应可能是直接用单片机自带的 ADC 去采集传感器信号。我最初也是这么想的,省一片芯片,板子还能做小一点。但实际测下来就会发现,单片机的 12 位或 16 位 ADC 在称重这种低速高精度场景下有几个硬伤:一是内部参考电压温漂明显,数据会随着板温变化慢慢跑偏;二是信号输入端没有专用的低噪声增益级,毫伏级别的微弱信号直接会被噪声淹没;三是没有专门的稳定激励源,电桥传感器的供电波动会直接转化为测量误差。

HX711 这类专用的桥式传感器 ADC 芯片,本质上是把“稳压供电激励 + 可编程增益放大器 + 高精度 Δ-Σ ADC + 数字滤波”打包在了一起。它内部集成了稳压电路,能给电桥传感器提供稳定的 5V 或 2.6V 激励;PGA 增益支持 32、64 和 128 倍选择,能把传感器输出的毫伏级差分信号放大到 ADC 能分辨的水平;核心的 24 位 Δ-Σ ADC 保证了分辨率;而通过简单的串行时序读数据,也让程序驱动变得相当直白。对于称重这种每秒采样几十次就够用的场景,HX711 在成本、性能和开发难度上是最平衡的选择。

1.2 完整方案组成

一个可靠的称重系统,不只是一片 HX711 加一个传感器那么简单。我的建议是把整个项目拆成几个模块来看:

  • 传感器部分:常见的是铝制或钢制悬臂梁式应变传感器,量程根据项目选,100g、1kg、5kg、20kg 都有。选型时注意灵敏度参数,一般是 1.0mV/V 或 2.0mV/V,这决定了 HX711 的增益档位选择。
  • 信号调理与采集:就是 HX711 芯片及其外围电路,包括去耦电容、电源滤波、传感器接口。
  • 主控逻辑:单片机负责配置 HX711、读取原始值、做数字滤波、执行零点追踪和标定计算,最终把 ADC 原始码换算成重量值。
  • 交互输出:OLED/LCD 显示、串口输出、蓝牙上传、继电器控制等,按项目需求来。

软件层面,我习惯把代码分成三层:最底层是 HX711 的驱动层,只负责时序读写;中间是称重逻辑层,处理标定系数、零点、滤波算法;最顶层才是业务层,比如显示、报警、数据上报。这样分层的好处是换传感器或换主控时,只需要改驱动层或者重新标定,核心算法不需要大动。

2. HX711 硬件接线与关键信号解析

2.1 引脚功能与接线要点

HX711 常用的是 SOP-16 封装,引脚不算多,但接线时有几个细节容易踩坑。核心引脚包括:

  • VSUP、AVDD、DVDD:电源相关引脚。我用的是 Arduino 5V 供电方案,VSUP 接 5V,AVDD 通过一个 10Ω 电阻接到 VSUP,DVDD 直接用 3.3V 或 5V 都可以。
  • VFB、BASE、VREG:内部稳压输出引脚。习惯上把 VREG 和 BASE 之间接一个 0.1μF 电容,VFB 和 AVDD 之间接一个 1μF 电容,确保稳压环路稳定。
  • HX711 的模拟电源 AVDD 会通过 VFB 引脚和芯片内部稳压产生,接传感器电桥的激励正端。
  • E+、E-、S+、S-:传感器接口,分别接电桥的激励正、激励负、信号正、信号负。
  • PD_SCK 和 DOUT:数字接口,PD_SCK 是时钟输入,同时负脉冲还能控制芯片进入掉电模式;DOUT 是数据输出。

接线方面,我的经验和很多新手教程不太一样:传感器和 HX711 之间的连线尽量短,并且用双绞线或者屏蔽线。应变式传感器输出的是差分信号,好处是抗共模干扰,但如果两根信号线走了不同的路径,引入的差模噪声就会直接叠加到信号上。我实测过,用普通跳线长距离飞线,和用双绞线连接,同样滤波算法下数据稳定度差距能达到好几倍。

2.2 模拟电源去耦与接地策略

HX711 的数据手册里推荐了外围电路,但我实际做下来还有几个补充要点。第一,10μF 钽电容和 0.1μF 陶瓷电容并联放在 AVDD 对地,这组去耦电容的位置要尽量靠近芯片电源引脚,千万别图省事放得远远的。第二,数字地和模拟地最好单点汇合,如果板子上空间允许,可以在 HX711 芯片下方把 AGND 和 DGND 统一接在一个地平面区域。我最早打样时没太在意,结果读出来的数据有周期性的低频波动,查了很久才发现是地环路引入了干扰。

关于增益档位,HX711 支持 128 和 64 倍增益,其中 128 倍对应通道 A,64 倍可以切换到通道 B。称重场景用通道 A + 128 倍增益是默认配置,读数据时在 DOUT 拉低后的第 25 个脉冲上升沿之前,需要先输出 25 个脉冲,其中前 24 个是数据位,第 25 个决定下一次读取的增益和通道。具体来说:第 25 个脉冲为高电平时选择通道 A 的 128 倍增益,低电平时选择通道 B 的 32 倍增益。程序里必须严格按这个时序来,否则读出来的数据通道就乱了。

3. 称重程序核心逻辑拆解

3.1 数据读取时序理解

HX711 的串行接口非常简单,但实际上手时很多朋友会把时序搞混淆。整个读取流程是这样的:

  1. 等待 DOUT 引脚从高电平变为低电平,这个下降沿表示 ADC 转换完成,数据已经就绪。
  2. 在 PD_SCK 上产生 24 个脉冲,每个脉冲的上升沿读取 DOUT 引脚电平,从最高位(第 1 个脉冲)到最低位(第 24 个脉冲)依次组成一个 24 位二进制数。
  3. 产生第 25 个脉冲,用于设置下一次转换的通道和增益。

有一个很容易被忽略的点:第 25 个脉冲的上升沿或下降沿并不真正影响本次已经读出的数据,它影响的是下一次的转换。所以如果你的代码在第 25 个脉冲之后立即就去读数据,可能读到的还是旧数据,需要等待 DOUT 再次拉低。另一个大坑是:24 位数据是有符号的。当传感器受正压力时,数据是正数;无负载时接近零;如果传感器接反或者受到拉力,数据可能变成负数。如果程序里把它当成无符号数处理,负值就会变成很大的正数,整个标定就直接废了。

解释一下有符号问题:HX711 输出的是二进制补码格式。最高位是符号位,当最高位为 1 时表示负数。在 C 语言里,如果你把数据读入一个 unsigned long 类型的变量,再强制转成 long,编译器会按照变量类型的位宽来解释,通常不会出错。但如果你用的是某些脚本语言或平台,可能就要手动做符号扩展。

3.2 零点追踪的原理与必要性

最近不少朋友在搜“hx711 零点追踪”这个关键词,说明大家在实际项目里都遇到了同一个麻烦:传感器在空载时的读数不是固定的,而是会随时间缓慢漂移。这个漂移的来源主要有三个:

  • 温度漂移:应变片的电阻值随温度变化,即便没有任何负载,电桥的输出也会发生变化。
  • 机械蠕变:传感器弹性体在长时间受力后会产生微小的形变恢复过程,卸载后读数要过一段时间才能稳定回原来的零点。
  • 电路漂移:HX711 的模拟前端、参考电压、PGA 增益都会随温度和时间产生微小变化。

如果不做零点追踪,一个 1kg 量程的秤,早上开机可能显示 0.0g,到了中午可能就变成 +2.3g 或者 -1.7g。当然你可以用去皮功能在每次称重前手动清零,但很多应用场景是不允许每次都去按一下去皮键的。零点追踪(Zero Tracking)就是在软件中自动检测并修正这个漂移:当系统判断当前处于空载状态时,把当前的读数慢慢吸收到零点参考值中,使显示重量始终回到零附近。

这里有一个关键逻辑:什么时候算“空载”?如果重量一直稳定在一个值附近,比如 0.1g 以内,并且持续了几秒钟,就可以认为是空载。但如果你设定一个触发阈值,比如 0.3g,那么任何小于 0.3g 的负载都会被自动清零。这在称重精度要求高的场景下是绝对不能接受的。所以零点追踪的触发条件必须包含“稳定”和“持续时间”两个维度,而不能只看瞬间值。

3.3 数字滤波与平滑策略

HX711 原始数据其实是很吵的,即便在静态负载下,最低几位也会跳动。这个跳动幅度取决于传感器量程、激励电压、布线质量和电源干净程度。比如我那个仓储称重项目,5kg 量程的传感器在无负载时,原始 ADC 值跳动大概在 ±5 个码左右,换算成重量大约是 ±0.05g。这个跳动看起来不大,但如果直接显示到小数位,数字还是会来回跳,观感很差。

解决思路是数字滤波,但我建议不要一上来就上特别复杂的滤波算法。先搞清楚你的项目需要多高的响应速度:如果是静态称重,比如厨房秤、电子秤,那用滑动平均或一阶低通滤波就够了;如果是动态称重,比如在线分选设备,滤波就要适当减弱,否则动态响应会拖后腿。

我常用的组合是:先做一个 4 次采样的中位值滤波,去掉明显的毛刺;再做 8 点滑动平均,进一步平滑。中位值滤波能有效去除脉冲干扰,滑动平均则能压低随机噪声。这个组合计算量小,在 Arduino 这种 8 位单片机上跑也毫无压力。

4. 完整称重程序实现与标定流程

4.1 核心代码框架

这里给出一份可以在 Arduino 平台上直接跑通的程序,结构上做了分层,方便移植到其他平台。底层驱动部分我没有直接用现成的库,而是自己写,这样能更好地理解时序细节。

首先定义一下接线和常量:

#define PIN_DOUT 3 #define PIN_SCK 2 float calibration_factor = 106.0f; // 标定系数,由标定流程得出 float zero_offset = 0.0f; // 零点偏移,用去皮或者零点追踪更新

HX711 的底层读取函数如下:

long HX711_Read() { while (digitalRead(PIN_DOUT)); // 等待 DOUT 变低,表示数据就绪 long raw = 0; for (int i = 0; i < 24; i++) { digitalWrite(PIN_SCK, HIGH); delayMicroseconds(1); raw = (raw << 1) | digitalRead(PIN_DOUT); digitalWrite(PIN_SCK, LOW); delayMicroseconds(1); } digitalWrite(PIN_SCK, HIGH); // 第 25 个脉冲,设置下一次为通道 A 128 倍增益 delayMicroseconds(1); digitalWrite(PIN_SCK, LOW); delayMicroseconds(1); if (raw & 0x800000) { // 符号扩展,处理 24 位有符号数 raw |= 0xFF000000; } return raw; }

这里最关键的是符号扩展那一行。HX711 返回的 24 位数据,如果最高位是 1,说明是负数,需要把高 8 位全部补 1,才能得到在 32 位有符号整数中正确的负数值。很多库没有这一步,结果在测拉力或传感器反向安装时数据就错了。

4.2 标定流程与系数计算

拿到原始 ADC 值之后,怎么换算成重量?核心公式是:

重量 = (当前原始值 - 零点原始值) / 标定系数

其中零点原始值就是空载时的平均 ADC 读数,标定系数表示每产生 1g 重量对应的 ADC 码变化量。标定的目的是确定这个系数。

我的标定流程是这样的:

  1. 空载状态下,连续读取 50 次原始值,取平均作为零点原始值。
  2. 放上一个已知重量的标准砝码,比如 500g,等待读数稳定,连续读取 50 次取平均。
  3. 计算标定系数:系数 = (砝码平均原始值 - 零点原始值) / 砝码重量,单位是“ADC 码/g”。

以我的仓储称重项目为例,5kg 量程传感器在 128 倍增益下,空载零点原始值大约在 8388608 附近(24 位 ADC 的中心值),放上 500g 砝码后读数约 8898608,那么:

标定系数 = (8898608 - 8388608) / 500 = 102000 / 500 = 204 码/g

这个系数可以直接写死在程序里,也可以通过串口命令在线修改,方便后期校准。如果换了一个传感器,或者改变了激励电压、增益档位,这个系数一定要重新标定。

4.3 零点追踪的工程实现

零点追踪的代码实现,要小心不要在秤上有长期小负载时把真实重量慢慢“吃掉”。我采用的做法是:

  • 设定一个触发窗口,比如 ±5 个 ADC 码(对应约 0.025g)。
  • 只有当连续 2 秒内,滤波后的原始值都落在这个窗口内,才认为处于空载状态。
  • 在空载状态下,每个控制周期把当前读数以极小的步长逼近零点:比如每次只调整零点值的 0.1%,这样即使误判,修正速度也很慢,不会产生明显误差。
  • 一旦检测到读数超出触发窗口,立即冻结零点追踪,防止把负载吸收掉。

代码逻辑大致如下:

float filtered_value; // 滤波后的重量,单位g float display_weight; // 最终显示重量 float zero_ref = 0.0f; // 当前零点重量参考 bool zero_track_enabled = true; void updateZeroTracking(float current_weight) { if (!zero_track_enabled) { zero_ref = current_weight; // 手动去皮时直接更新 zero_track_enabled = true; return; } static int stable_count = 0; if (fabs(current_weight - zero_ref) < 0.05f) { // 在零点附近 stable_count++; if (stable_count > 100) { // 大约2秒稳定 zero_ref += (current_weight - zero_ref) * 0.01f; // 缓慢追零 } } else { stable_count = 0; } zero_offset = zero_ref; }

这种慢速追踪有几个好处:一是对真实漂移有良好的跟随性,二是即使判断失误也不会瞬间跳变,三是实现简单,不需要高深的控制理论。如果你做的是计重秤,还可以增加一个“半自动”零点追踪逻辑,也就是只在开机时和空载超过 5 秒时执行一次快速追零,中间不进行追踪,这样能兼顾响应速度与精度。

5. 常见问题与调试经验实录

5.1 数据跳动过大的排查

我遇到的最典型问题是:数据一直在较大范围内跳动,排查步骤如下:

第一步,确认传感器和 HX711 的电源是否干净。检查 HX711 的 AVDD 电源引脚处是否有明显的纹波,用万用表的交流档测量一下,如果超过 20mV,说明电源滤波不够。建议在 VSUP 和 AVDD 处分别增加 100μF 电解电容,并确认 0.1μF 陶瓷电容离芯片引脚足够近。

第二步,检查传感器信号线是否受到了数字信号干扰。PD_SCK 和 DOUT 线在翻转时会带来高频噪声,如果它们和 S+、S- 信号线平行走线过长,噪声会耦合到模拟信号上。我自己试过把信号线从主控板下面穿过,结果数据跳动明显增加,后来改成双绞线并远离数字线才恢复。

第三步,检查滤波算法的截止频率是否匹配你的采样速度。HX711 内置的滤波带宽大概在 10Hz,如果你的程序采样周期是 10ms,那采样速度已经接近内置滤波器带宽了,此时再叠加数字滤波要注意相位滞后。可以用示波器观察一下滤波前后的数据曲线,如果滤波后数据存在明显滞后,导致放上砝码后要等很久才稳定,说明滤波深度过大,需要平衡。

5.2 标定系数漂移问题

有些朋友反映,标定好的系数,过几天再测就不准了。这里面有几种可能:

  • 传感器本身受到过超范围冲击,导致弹性体产生永久形变,灵敏度发生了改变。这类情况只能换传感器。
  • 激励电压漂移。如果 AVDD 不稳,电桥输出电压和 ADC 参考电压可能会不成比例地变化,导致标定系数改变。检查方法是在标定前、后分别测量 E+ 对地的电压,如果偏差超过 5mV,就要检查供电。
  • 温度引起的灵敏度变化。应变式传感器的灵敏度温漂是物理特性,无法完全消除,但可以通过软件温漂补偿来优化。如果项目工作环境温度变化大,可以在系统中增加温度传感器,通过查表或拟合公式修正标定系数。

我在仓储项目里做过一个简单的温漂补偿:在 10℃ 到 40℃ 范围内做了一组标定实验,发现 5kg 量程传感器的系数大约每 10℃ 变化 0.3%,于是我在软件里加了温度查表修正,把最大误差从原来的 2.5g 降到了 0.6g。如果你的项目也在宽温环境下工作,这个方法可以参考。

5.3 零点追踪误判与应对

零点追踪最大的风险是“把重量吃掉”。为了验证这个问题,我专门做了一个实验:在秤面上放一个 50g 的重物,让程序连续运行 10 分钟,观察重量是否被逐渐修正掉。结果是:由于 50g 远大于 0.05g 的触发窗口,追踪逻辑会立即冻结,重量完全不会被改动。但如果放的是 0.1g 的轻物,并且秤的机械结构稳定,程序会判断为空载漂移并把它慢慢归零。这在某些高精度应用场景下是不允许的,所以如果你做的是实验室用秤或者微量秤,建议把零点追踪功能做成可配置的,默认关闭,或者把触发窗口设置为更小的档位。

另一个值得注意的坑是机械结构引起的零点回滞。比如秤盘被碰了一下,传感器受力后变形,之后虽然没有任何负载,但机械结构无法完全回到原来的状态,零点读数可能偏移了比较多。此时零点追踪因为触发窗口太小而无法自动修正,就需要用户手动去皮。我在程序里做了一个简单处理:如果空载状态的读数偏移超过 50 个 ADC 码,就自动执行一次快速去皮,相当于半自动的零点恢复。

6. 工程化落地时的一些额外心得

说实话,HX711 驱动本身不难,难的是把“能用”变成“好用”。我踩过几次坑之后,总结了几个小技巧:

第一,采样频率不要一味求快。HX711 内部 ADC 的最高输出速率可以设到 80Hz(速率由 PD_SCK 高电平时间控制),但实际称重场景,特别是静态称重,40Hz 就完全够用了。降低采样率可以更充分地发挥内置滤波器的效果,数据更平滑。如果项目需要动态响应,可以适当提高,但要在后端加更强的数字滤波器。

第二,在批量生产或长期运行的项目里,最好把标定参数、零点数据存在 EEPROM 或 Flash 中,避免每次断电后重新标定。开机时先读取保存的参数,并用一个简短的自检流程验证数据是否合法。比如标定系数如果超出合理范围,就说明存储区可能被写坏或者从未标定过,此时应提示用户重新标定,而不是带病运行。

第三,PCB 布局上,HX711 尽量靠近传感器接口,减少模拟信号走线长度。芯片底部的散热焊盘如果有,就接到地平面上去,能改善一点热稳定性能,对零点漂移有微小的正面帮助。

第四,如果用 HX711 做多路称重,比如一台设备上有 4 个称重点,一定要让每片 HX711 的 PD_SCK 独立控制,DOUT 可以共用总线,也可以分别接引脚。但要注意,SCK 时钟频率不宜太高,否则数字噪声会通过公共电源耦合到模拟部分,影响数据质量。

最后再分享一个我在实际项目中使用的调试技巧:在开发时,把原始 ADC 值、滤波后重量值、零点参考值、追踪状态全部通过串口打印出来,用曲线绘图工具(比如 SerialPlot 或 Arduino Plotter)实时观察。你会发现,很多看起来奇怪的“软件Bug”,本质上是硬件层面的干扰,通过这种方式能很快定位问题源头。

如果你正在做或者准备做称重相关项目,希望这篇内容对你有实际的帮助。HX711 只是一个基础模块,真正决定一个称重系统好不好用的,是电磁兼容处理、标定流程和长期稳定性的软件补偿策略。这些细节,往往比多写几行代码更重要。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 12:19:34

轻量级去中心化服务发现与任务协同框架实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 12:18:55

如何 3 步自托管 Tabby AI 编程助手:新手完整指南

如何 3 步自托管 Tabby AI 编程助手&#xff1a;新手完整指南 【免费下载链接】tabby Self-hosted AI coding assistant 项目地址: https://gitcode.com/GitHub_Trending/tab/tabby 本文带你从零跑起 Tabby——一个自托管的 AI 编程助手&#xff0c;提供代码补全、对话问…

作者头像 李华
网站建设 2026/9/2 12:18:10

STM32F429 HAL库 ADC+DMA多通道数据采集实战详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华