尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
STM32与HX711电子秤开发:从驱动移植到标定滤波的完整指南
简介STM32与HX711组合的高精度电子秤工程源码面向电子、嵌入式方向初学者及有称重项目需求的开发者。资源基于STM32F4系列实现HX711驱动覆盖SCK/DOUT接口时序控制、数据读取与限幅平均滤波并附带去皮和比例调整功能可直接移植到电子秤产品中也适合改装现有称重模块。压缩包共98个文件以44个C源码和44个头文件为主搭配Keil工程文件、启动文件、配置文件及readme说明目录划分为FWLIB、SYSTEM、HARDWARE等模块便于按功能查找、对照实验和二次开发。代码中既有GPIO初始化与配置函数也有滤波和校准逻辑帮助理解HX711工作模式、限幅平均滤波去噪、去皮和标定的完整流程启动文件和工程配置还可减少环境搭建成本。已有2985人学习下载适合快速搭建STM32电子秤原型也适合课程设计或毕业设计参考。1. 把 STM32 和 HX711 做成电子秤先解决标定再谈精度做 STM32 电子秤新手最容易高估硬件难度而低估标定工作量。HX711 本身就是一个 24 位高精度 ADC 芯片专门为桥式传感器设计MCU 只需要两根 IO 线就能读出重量数据接线简单到不能再简单。但真正让项目卡住的往往是零点漂移、温漂和标定系数不准——这些靠程序里的滤波算法和标定流程解决而不是靠换芯片。这份 STM32 hx711 电子称程序的核心价值在于它把数据采集、均值滤波、标定和串口输出一条链路走通了你拿到手改一下引脚定义和量程系数就能出数。适合正在做称重、张力、压力检测的开发者也适合想用 HX711 学桥式传感器采样的入门者。2. HX711 还是 ADS1232为什么选它以及时序和接线的硬约束2.1 HX711 的硬件特性与选型理由HX711 是国产海芯微推出的 24 位高精度 ADC专为桥式传感器设计。它最突出的几个参数24 位无失码、内置 PGA 放大器可选增益 32、64 或 128、内部振荡器不需要外部晶振、输出采用串行 25 个脉冲的时序协议。相比 ADS1232HX711 的硬件电路更简单电源要求也更宽松2.6V5.5V但缺点是输出速率固定10Hz 或 80Hz 可选不支持 SPI 标准时序只能靠 GPIO 模拟。实际选型时我的习惯是做静态称重电子秤、料位检测选 HX711性价比高5 元以内搞定做动态称重皮带秤、灌装过程重量反馈选 ADS1232它的输出速率能到 80SPS 且内部滤波更陡HX711 在 80Hz 模式下噪声明显偏大只能靠软件滤波兜底。2.2 引脚分配与传感器接线HX711 模块最常见的封装是带排针的 breakout 板引脚就六个VCC、GND、SCK、DOUT部分模块还有 PD_SCK 和 RATE。其中 SCK 是时钟输入DOUT 是数据输出RATE 引脚控制输出速率——接高电平选 80Hz接低电平选 10Hz。测量精度和噪声是矛盾的10Hz 模式内部数字滤波更强适合稳定称重80Hz 模式响应快但噪声大适合动态场景。传感器那边常规称重传感器是四线制红E、黑E-、白S、绿S-。部分六线制传感器多了屏蔽线和反馈线反馈线通常和信号线并联不用接。接线错误最常见的后果是读数为负或满量程翻转——这不是程序问题是传感器激励和信号接反了。引脚对应关系以某常用四线制传感器为例 HX711 VCC → 5V HX711 GND → GND HX711 SCK → 单片机任意 GPIO示例PA0 HX711 DOUT → 单片机任意 GPIO示例PA1 传感器 E → HX711 VCC 传感器 E- → HX711 GND 传感器 S → HX711 A 传感器 S- → HX711 A-提示如果传感器线序不确定用万用表量一下——激励线之间的电阻通常几百欧信号线之间的电阻等于桥臂并联值约为激励电阻的一半。2.3 25 脉冲时序每一次转换都要重新拉高拉低HX711 的时序协议是整个驱动的灵魂。DOUT 在转换完成前保持高电平转换完成后拉低这时 MCU 发送 25 个时钟脉冲前 24 个脉冲依次读出 24 位数据从最高位到最低位第 25 个脉冲决定下一次转换的增益通道一个低脉冲选择通道 A 增益 128两个低脉冲选择通道 B 增益 32三个低脉冲选择通道 A 增益 64。这条时序最容易被忽略的是你必须在 DOUT 变低后立刻开始读而不是先做别的初始化任务。而且读完后要保持 SCK 低电平等 DOUT 再次拉低才能开始下一次读取。如果 SCK 高电平持续时间超过 60μsHX711 会进入 power down 状态这是很多人 debug 半天没找到原因的坑。io 模式的时序实现如下注意每个脉冲之间要有延时——虽然 HX711 的时钟最高能到 5MHz但 GPIO 翻转速度太快反而容易产生毛刺信号。 DOUT 下降沿触发while(DOUT1) 等待 for(i0;i24;i){ SCK1; delay_us(2); SCK0; delay_us(2); data (data1)|DOUT; } // 第25个脉冲选择增益 SCK1; delay_us(2); SCK0; delay_us(2);这段代码的核心逻辑是24 位数据按位串行移入变量每次 SCK 拉高后延时稳定再拉低DOUT 上的电平在 SCK 下降沿后才会更新所以必须在 SCK 为高电平时读引脚。第 25 个脉冲完成后芯片自动进入下一次转换约 100ms10Hz 模式后 DOUT 再次拉低。3. 驱动实现从底层读取到稳定称重数值的完整代码3.1 底层 GPIO 初始化与延时精度STM32 这边我倾向于用标准外设库或 HAL 库做 GPIO 配置关键在于延时函数的精度。HX711 的 SCK 高电平最小宽度约 0.2μsDOUT 建立时间约 0.1μs只要不是用 SysTick 做毫秒级延时基本都来得及。但如果你用的开发板主频很低比如 8MHz 的 STM8 或者软件仿真器直接跑建议把延时加大到 5μs稳定性优先。void HX711_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_0; // SCK GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; // 推挽输出 GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; // DOUT GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPD; // 下拉输入 GPIO_Init(GPIOA, GPIO_InitStructure); }GPIO 配置里有一个细节DOUT 引脚最好开启内部下拉。HX711 的 DOUT 是开漏输出内部有弱上拉但如果你用的是外部模块模块上一般都自带上拉电阻。如果 DOUT 悬空时会跳动加上下拉输入模式反而能减少干扰引发的误触发。3.2 读取原始值的函数封装与补码处理HX711 输出的 24 位数据是二进制补码形式正数直接左移得到负数需要手动取反加一。这个处理不做对空载时读数可能是 16777215 这种满量程值而不是 0。int32_t HX711_Read(void) { uint32_t buf 0; int32_t val; while(HX711_DOUT); // 等待 DOUT 拉低 for(int i 0; i 24; i) { HX711_SCK 1; delay_us(2); buf buf 1; if(HX711_DOUT) buf; HX711_SCK 0; delay_us(2); } HX711_SCK 1; // 第25个脉冲默认通道A增益128 delay_us(2); HX711_SCK 0; delay_us(2); if(buf 0x800000) { // 判断最高位处理负数补码 val (int32_t)(buf | 0xFF000000); } else { val (int32_t)buf; } return val; }补码处理的逻辑是24 位数据最高位bit23为符号位如果为 1 则说明是负值需要把这个值扩展成 32 位有符号整数方法就是按位或 0xFF000000。这一步不做负数读数直接变成几十万的正数标定根本无从谈起。3.3 均值滤波与毛刺剔除HX711 最头疼的问题是读数在 10Hz 模式下大约有 ±3 个码的跳动在 80Hz 模式下能到 ±15 个码。直接把这个值换算成重量显示会抖到没法看。常见做法是连续采样 1020 次取平均但这里有一个容易被忽略的细节均值滤波能压白噪声但对偶发毛刺无能为力——比如电机启动瞬间的电磁干扰会让某一次采样偏离正常值几千个码一次异常值就能把平均值抬高几十码。我一般会做一个「排序取中值 均值」的复合滤波取 5 次采样排序后去掉最大最小剩下 3 次取平均。代价是取一次稳定值需要 5 × 100ms 500ms但称重场景本来就不需要高速响应。int32_t HX711_Get_Stable_Value(void) { int32_t samples[5]; int32_t buf; int i, j; for(i 0; i 5; i) { samples[i] HX711_Read(); delay_ms(10); // 等待下一次转换完成 } // 冒泡排一次序 for(i 0; i 4; i) { for(j i1; j 5; j) { if(samples[i] samples[j]) { buf samples[i]; samples[i] samples[j]; samples[j] buf; } } } // 去掉最大最小值剩余3个取平均 buf (samples[1] samples[2] samples[3]) / 3; return buf; }排序取中值的思路是用一个简单冒泡把 5 个样本排好然后写死去掉首尾两个极端值。这个策略对毛刺的抑制效果非常明显——即使一次采样被干扰打到十万级被剔除后另外四次正常值也能保住均值不受污染。3.4 串口输出与数据格式化调试阶段最实用的套路是先把原始码值直接输出到串口看空载和满载的码值变化范围再决定标定系数。不要一上来就换算成克数——你连原始码值的变化规律都没确认换算出来的克数也不可信。printf(raw: %ld\r\n, HX711_Get_Stable_Value());没有重定向 printf 的工程直接用串口发送十六进制或者十进制字符数组都行。关键是输出频率别太高——HX711 稳定值出来一次要 500ms 左右串口打印每 500ms 一次就够。打印太频繁反而会干扰主循环里的时序比如你的主循环里有按键扫描或者 OLED 刷新串口阻塞发送会卡住整个流程。4. 重量换算与标定流程系数怎么来、怎么验、怎么稳4.1 标定的数学原理与两步法HX711 的输出码值和重量是严格的线性关系所以标定的本质就是求一条直线 y kx b 的两个参数。k 是比例系数每克对应的码值变化量b 是零点偏移空载时的码值。最靠谱的标定方式是两步空载时读取稳定值记为 zero。放一个已知重量的砝码读取稳定值记为 value。计算系数 k (value - zero) / weight。这里有个工程上的讲究标准砝码的重量尽量选在量程的 50%80% 之间。比如 5kg 量程的秤用 3kg 或 4kg 砝码标定比用 500g 砝码标定准得多——因为砝码本身有公差小砝码的相对误差更大而且传感器的非线性在低载荷段更明显。// 标定参数存储结构 typedef struct { int32_t zero; // 空载码值 int32_t scale; // 每克对应的码值变化量 uint32_t max_weight; // 最大量程克 } CalibParam; // 重量换算 int32_t HX711_Get_Weight(CalibParam *calib) { int32_t raw HX711_Get_Stable_Value(); return (raw - calib-zero) / calib-scale; }标定参数建议存储在 Flash 里比如 STM32F103 的最后一个扇区掉电不丢失。每次上电先读 Flash 恢复参数而不是重新标定——否则用户换了电池就要重新校准体验很差。4.2 标定命令和交互设计实际项目中标定不能做成编译的时候写死数值而是要给一个运行时触发方式。最常见的是通过串口发送指令触发标定比如CAL Zero记录零点CAL 1000表示放上 1000g 砝码并记录当前读数。void Handle_Calibration_Command(const char *cmd) { if(strcmp(cmd, zero) 0) { calib.zero HX711_Get_Stable_Value(); Save_Calib_To_Flash(calib); printf(zero saved: %ld\r\n, calib.zero); } else if(sscanf(cmd, value %d, weight) 1) { int32_t raw HX711_Get_Stable_Value(); calib.scale (raw - calib.zero) / weight; Save_Calib_To_Flash(calib); printf(scale saved: %ld\r\n, calib.scale); } }这个设计的好处是产线上批量校秤的时候不用重新编译固件只要接串口发两条指令就完成标定。如果产品不带串口就需要留按键触发——长按进入标定模式短按确认空载/加砝码LED 闪烁提示状态。4.3 避免标定误差的三个实操点标定过程有几个容易翻车的细节。第一标定时要等读数完全稳定再记录——HX711 上电后前 2 秒读数漂移很大起码要等 3 秒以上才开始标定。第二称重平台上不能有风或者振动源——空调出风口直吹就能让 1000g 的读数波动 3g 以上。第三传感器需要预热——很多低成本传感器在刚上电时桥臂电阻没稳定输出会缓慢漂移放置 5 分钟后再标定效果会好很多。5. 避坑与排查HX711 开发中的五个高频踩坑点5.1 读数为零或恒定不变现象程序运行后 DOUT 引脚一直是高电平读取函数死循环在 while 等待。原因一般是 HX711 没有正常上电——VCC 引脚电压低于 2.6V或者传感器没接到激励端导致无输出。解决先量 HX711 的 VCC 引脚电压再量传感器激励端 E 和 E- 之间的电压应等于电源电压最后示波器看 SCK 引脚是否有时钟信号输出。5.2 读数为负且绝对值很大现象空载时读数是 -8388608 左右或者放上重物后读数反而减小。原因大概率是传感器信号线 S 和 S- 接反了。解决交换 A 和 A- 两个引脚读数就会变为正。注意有些颜色线序的传感器比如黑白黄蓝线需要查手册确认不同厂家的线序定义不一致。5.3 读数漂移刚开机和十分钟后相差几十克现象上电后读取的重量不断变大或变小几分钟后趋向稳定。原因有两个一是传感器自身温漂桥臂电阻随温度变化二是 HX711 内部参考电压没稳定。解决做软件上上电后延时 35 秒才开始正常采样做硬件上在传感器和 HX711 模块之间加一个低通滤波电容0.1μF 并 10μF。5.4 标定后量程内读数非线性现象小重量时显示偏大大重量时显示偏小或者反过来。原因传感器在载荷接近满量程时输出有非线性而 HX711 本身的线性度很好。解决如果只是简单应用可以接受 ±0.5% 误差如果要求高就做分段标定——取 30%、60%、90% 三个点分别记录系数程序里按区间插值。工程里 90% 的情况用单段线性标定就够了。5.5 断电后标定参数丢失现象重新上电后重量显示完全不对需要重新标定。原因标定参数存在 RAM 里复位后清零。解决写完 Flash 存储后上电读取时加一个校验——比如存两个副本做异或校验防止 Flash 操作中途掉电导致参数损坏。读出错就重新进入标定状态提示用户重新校秤。6. 进阶自动零点追踪与动态称重的软件优化零点追踪是电子秤产品里几乎必做的功能——传感器和结构件都会老化变形零点会缓慢漂移。实现思路是开机后先记录初始零点然后在运行过程中持续监测——如果当前读数在某个小范围内比如 ±3g维持了一段时间且没有超过设定阈值就把这个值更新为零点。注意不能在没有负载的时候误判所以要有逻辑判断稳定且接近当前零点才更新。#define ZERO_TRACK_RANGE 5 // 允许追踪的范围克 #define ZERO_TRACK_TIME 30 // 持续稳定时间秒 #define STABLE_THRESHOLD 2 // 读数波动阈值克 uint8_t Zero_Track_Update(int32_t current_weight, uint32_t sys_second) { static uint32_t last_stable_time 0; if(current_weight ZERO_TRACK_RANGE) { if(abs(current_weight) STABLE_THRESHOLD) { last_stable_time; if(last_stable_time ZERO_TRACK_TIME) { calib.zero HX711_Get_Stable_Value(); Save_Calib_To_Flash(calib); last_stable_time 0; return 1; } } else { last_stable_time 0; } } return 0; }动态称重这块如果需要在传送带上测重量HX711 的 10Hz 模式完全不够用——每次读数间隔 100ms一个物体在秤台上停留时间可能只有 200ms只能采到两次数据。这时候必须切到 80Hz 模式RATE 引脚接高然后配合峰值检测算法连续采样取最大值作为称重结果。但 80Hz 模式噪声大建议用滑动平均窗口连续 8 次做移动平均后再取峰值。最后讲一个习惯。搞 HX711 称重有一段时间后我养成了每次上电强制跑一遍「空载读数 — 砝码读数 — 校验线性度」的三步验证流程用一块 1kg 砝码走一遍确认读数在预期范围内才让程序进入正常显示。这套流程后来帮我查掉了好几个因为机械结构变形导致的称量异常——很多问题不是出在代码上而是出在秤台被人踢了一脚、螺丝松了、传感器变形了这类物理原因上。如果你也是第一次做称重项目建议把原始码值打印留到量产前再关掉调试时盯着码值做判断会比盯着换算后的重量更直观。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

S32K3xx CAN FD硬件邮箱过滤驱动开发实战

S32K3xx CAN FD硬件邮箱过滤驱动开发实战

1. 项目概述:为什么在S32K上手写CAN FD邮箱过滤驱动是件“不得不做”的事在汽车电子和工业控制领域摸爬滚打十多年,我经手过几十个基于NXP S32K系列MCU的项目——从车身域控制器原型到电池管理系统BMS的量产固件。每次遇到CAN FD通信需求,团队…

📅 2026/10/15 16:43:31
Python条码识别实战:zxing库从环境配置到生产级应用

Python条码识别实战:zxing库从环境配置到生产级应用

简介:针对需要在Python项目中集成二维码、条形码识别能力的开发者,这份基于Java版ZXing(Zone Xing)的Python zxing库资源提供了一条无需从零实现图像处理算法的清晰路径。资源以zxing库的安装与使用为主线,先明确了Jav…

📅 2026/10/15 16:38:29
Cassandra大数据挖掘实践:特征存储与管道设计

Cassandra大数据挖掘实践:特征存储与管道设计

1. 先定调:Cassandra在大数据挖掘里的角色不是数据库,而是“特征枢纽”说起在大数据里做数据挖掘,很多人第一反应是搭一个Spark作业去读Hive或者Parquet,跑完把结果存到MySQL。这个思路本身没问题,可一旦业务进入实时或…

📅 2026/10/15 16:38:29
MORE NEWS

更多资讯

📰

重言式判别程序课程设计:从语法树到真值表算法的Python实现

简介:重言式判别程序课程设计是面向数据结构课程实践的小型项目资料,适合计算机及相关专业学生参考布尔表达式与二叉树算法。资源围绕重言式(逻辑恒等式)判别问题,讲解如何用二叉树表示逻辑表达式,并以后序…

📰

OpenCV模型训练实战:轻量级机器学习在边缘设备的落地

1. 这不是“调个库就能跑”的模型训练——OpenCV的模型训练到底在训什么?很多人看到“OpenCV模型训练”这个标题,第一反应是:OpenCV不是做图像处理的吗?它还能训练模型?是不是搞错了?是不是该用PyTorch或Te…

📰

数组与字符串题:架构师的底层建模能力训练场

1. 为什么架构师必须亲手写透数组和字符串题——不是考你背题,是考你建模的肌肉记忆“想当架构师,数据结构与算法不过关可不行”——这句话在技术圈被反复提起,但很多人误以为它只是HR筛简历的门槛标签,或者面试官用来“压一压应届…

📰

普元EOS7.5生成Restful接口实战指南

1. 项目概述:为什么一个老派企业级平台还在认真做Restful接口? “普元EOS7.5生成RestFul接口服务”——这个标题乍看像一句内部系统文档里的操作备注,甚至有点过时感。毕竟现在聊微服务、云原生、低代码,动辄就是Spring Cloud Al…

📰

如何读懂 LycheeMem:动作感知四级语义检索流水线源码级拆解指南

【免费下载链接】LycheeMem Lightweight Long-Term Memory for LLM Agents. 项目地址: https://gitcode.com/gh_mirrors/ly/LycheeMem 点击查看 免费下载 LycheeMem 是面向 LLM Agent 的轻量级长期记忆框架(Lightweight Long-Term Memory for LLM Agent…

📰

使用Dify做一个客服对话记录分析

windows中搭建dify,请见上一篇。本篇介绍使用Dify做一个客服对话记录分析工作流1.1 创建工作流首先,在 Dify 平台中创建一个新的工作流,命名为「客服对话记录分析」。创建完成后,工作流概览如下所示。工作流概览如下:1…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬