资讯动态

基于STM32与HX711的电子秤设计:从信号链到滤波标定实战

发布时间:2026/10/19 5:11:28 来源:尧图企业网站定制
简介这份资源面向嵌入式初学者与电子设计课程实践者提供一套基于STM32单片机的电子秤完整设计方案帮助读者理解从传感器信号采集到重量显示的全链路实现。压缩包共225个文件约18.89MB以C源码与头文件为核心辅以工程配置、原理图、PCB文件、物料表、项目报告及编译产物覆盖程序、硬件设计与文档资料。内容涉及STM32的GPIO、中断、定时器与ADC配置HX711高精度称重传感器的驱动与通信平均值与滑动平均等滤波算法以及LCD显示驱动和电源管理并包含Keil工程文件与烧录配置便于直接编译调试。目前已有3093人学习下载适合作为课程设计、毕业设计或自学嵌入式开发的参考案例读者可据此复现硬件电路、移植代码并掌握信号处理与排错思路。1. 从菜市场到实验室为什么一个电子秤项目值得你花时间拆去年帮一个做烘焙的朋友改商用配方她抱怨店里那台电子秤每次称完面粉再称酵母读数要飘好几秒才稳急得人想砸秤。我当时顺手拆了一台几十块的厨房秤发现里面就是一颗 STM32 加一片 24 位 ADC电路简单到令人发指但代码里滤波和标定写得稀烂。这件事让我意识到基于 STM32 单片机的电子秤设计几乎是嵌入式入门到进阶最划算的练手项目它同时踩中了传感器采集、模数转换、数字滤波、人机交互、校准算法这几个核心技能点而且做出来立刻能用不是点个灯就完事的玩具。这份资源适合两类人一类是刚学完 STM32 GPIO 和定时器、想找个完整项目把知识串起来的新手另一类是做工业称重或智能硬件的开发者想看看别人怎么处理称重传感器的小信号和温漂问题。它不涉及复杂的 RTOS 或网络协议但把模拟前端到数字输出的链路讲透了你拿过去改一改就能变成计价秤、配料秤或者实验室天平的原型。2. 硬件架构与信号链从应变片到 ADC 的每一微伏2.1 称重传感器与惠斯通电桥的选型逻辑电子秤的核心是称重传感器最常见的是电阻应变式。它的原理不复杂金属弹性体受力变形贴在表面的应变片阻值跟着变四片应变片接成惠斯通电桥输出一个差模电压。这个电压非常小满量程通常只有几毫伏到几十毫伏比如一个 5kg 量程、灵敏度 1mV/V 的传感器在 5V 激励下满量程输出才 5mV。如果你直接把它接到 STM32 的 ADC 引脚12 位分辨率下 3.3V 参考电压的最小刻度是 0.8mV意味着满量程只有 6 个有效刻度根本没法用。所以信号链的第一站必须是仪表放大器。常见做法是用一颗低失调、低漂移的运放搭差分放大比如 INA333 或 AD620把差分信号放大 100 到 500 倍同时抑制共模干扰。放大后的信号再送进 ADC。这里有个血泪经验放大倍数不是越大越好要留出传感器偏置和温漂的余量。我一般会把满量程信号放大到 ADC 量程的 60% 到 80%剩下的空间留给零点漂移和过载。2.2 STM32 内部 ADC 与外部 ADC 的取舍STM32 自带的 12 位 SAR ADC 在低速称重场景下够不够用答案是看精度要求。如果你做的是分度值 1g、量程 5kg 的厨房秤满量程 5000 个分度12 位 ADC 理论上有 4096 个码值看似勉强够但实际有效位数受噪声影响可能只有 10 位左右分度值会跳。这时候有两个选择一是用 STM32 的过采样功能通过硬件平均把有效分辨率提到 14 到 16 位二是外挂一颗 24 位 Σ-Δ ADC比如 HX711 或 ADS1232。HX711 是电子秤圈子里绕不开的芯片它把仪表放大器和 24 位 ADC 集成在一起直接差分输入内置稳压和振荡器通过两个 GPIO 就能读数据。成本低、电路简单缺点是输出速率慢一般 10Hz 或 80Hz不适合动态称重。如果你用 STM32 的 SPI 或 I2C 外挂 ADS1232可以做到 2kHz 采样适合检重秤或动态配料。这份资源里用的是 HX711 方案因为它的资料最全新手最容易跑通。2.3 电源与基准电压的噪声控制称重系统里电源噪声直接决定读数稳不稳。HX711 内部有模拟电源和数字电源引脚常见做法是在模拟电源脚旁边放 10uF 钽电容加 100nF 陶瓷电容数字电源脚单独走线最后在总入口处用磁珠隔离。基准电压方面HX711 内部有 1.25V 基准但它的精度受温度影响如果做高精度秤可以外接一颗 REF3033 之类的基准源。PCB 布局上模拟地和数字地要分开铺铜最后在 ADC 下方单点连接。传感器引线要用屏蔽线屏蔽层接模拟地。这些细节听起来玄学但我在实验室里对比过同样的代码布局好的板子零点漂移能控制在 ±2 个码值以内布局差的能飘 ±50 个码值直接决定你的秤能不能稳定显示到 0.1g。3. 固件实现HX711 驱动、滤波与标定算法3.1 HX711 时序驱动与数据读取HX711 的通信协议是自定义的同步串行没有标准 SPI 或 I2C。它有两个引脚PD_SCK 和 DOUT。当 DOUT 为低电平时表示数据准备好此时给 PD_SCK 发送 25 到 27 个时钟脉冲前 24 个脉冲在上升沿输出 24 位数据第 25 个脉冲用来选择下一次的通道和增益。下面是一段基于 STM32 HAL 库的读取代码用 GPIO 模拟时序。// HX711 引脚定义根据实际接线修改 #define HX711_DOUT_PIN GPIO_PIN_0 #define HX711_DOUT_PORT GPIOA #define HX711_SCK_PIN GPIO_PIN_1 #define HX711_SCK_PORT GPIOA // 读取 HX711 原始数据返回 24 位有符号整数 int32_t HX711_ReadRaw(void) { int32_t value 0; uint8_t i; // 等待 DOUT 变低表示数据就绪 // 实际项目中应加超时防止传感器断线死循环 while (HAL_GPIO_ReadPin(HX711_DOUT_PORT, HX711_DOUT_PIN) GPIO_PIN_SET); // 读取 24 位数据MSB 在前 for (i 0; i 24; i) { HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_SET); value value 1; HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_RESET); if (HAL_GPIO_ReadPin(HX711_DOUT_PORT, HX711_DOUT_PIN) GPIO_PIN_SET) { value; } } // 第 25 个脉冲选择通道 A 增益 128 HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_SET); value value ^ 0x800000; // 补码转换24 位有符号 HAL_GPIO_WritePin(HX711_SCK_PORT, HX711_SCK_PIN, GPIO_PIN_RESET); return value; }这段代码的关键点有三个。第一等待 DOUT 变低的地方必须加超时否则传感器没接好时程序会卡死我一般会用一个计数器超过 100ms 就返回错误码。第二24 位数据是补码格式最高位是符号位所以读完后要异或 0x800000 转成标准 int32。第三第 25 个脉冲的时序不能少它决定下一次转换的通道和增益如果你接的是通道 B 或者增益 64这里要发 26 或 27 个脉冲。3.2 数字滤波滑动平均、中值滤波与卡尔曼的取舍原始数据读出来之后你会发现它跳得厉害。HX711 在 10Hz 输出速率下噪声大概有几十个码值直接显示就是最后一位乱蹦。这时候需要滤波。最简单的滑动平均取 10 到 20 个样本平均能把噪声压到 1 到 2 个码值但代价是响应变慢称重时读数要等一两秒才稳。中值滤波对脉冲噪声特别有效比如你放上去一个砝码瞬间的机械振动会产生几个异常值中值滤波能直接把它们剔掉。我一般会把中值滤波和滑动平均串起来用先取 5 个样本排序取中间值再对连续 10 个中间值做平均。这样既有抗脉冲能力又能平滑随机噪声。如果你做的是动态称重比如传送带上快速过包卡尔曼滤波会更合适。它用状态方程预测下一时刻的重量再用观测值修正响应快且平滑。但卡尔曼的参数调起来比较玄学过程噪声和观测噪声的协方差矩阵需要根据实际系统试凑。新手建议先用滑动平均跑通再考虑升级。#define FILTER_WINDOW 10 // 滑动平均滤波器 int32_t MovingAverage_Filter(int32_t new_sample) { static int32_t buffer[FILTER_WINDOW] {0}; static uint8_t index 0; static int32_t sum 0; int32_t average; // 减去最旧样本加上最新样本 sum - buffer[index]; buffer[index] new_sample; sum new_sample; index; if (index FILTER_WINDOW) { index 0; } average sum / FILTER_WINDOW; return average; }这个滑动平均实现用了一个小技巧维护一个累加和每次只减旧值加新值避免每次循环都重新求和在 STM32 这种没有 FPU 的 M3 内核上能省不少时间。注意 sum 要用 int64 或者确保窗口内总和不会溢出 int3224 位数据乘以 10 已经接近 int32 上限了。3.3 标定两点法、多点法与温度补偿滤波后的数据还是 ADC 码值要变成克数必须标定。最常用的是两点法空载时读一个零点码值放上已知砝码读一个满量程码值然后线性插值。公式很简单重量 (当前码值 - 零点码值) * 砝码重量 / (满量程码值 - 零点码值)。但实际传感器不是完全线性的尤其是大量程传感器在小重量段误差大。如果你做计价秤建议用多点标定比如 0%、25%、50%、75%、100% 五个点用分段线性或者最小二乘拟合。我一般会在代码里存一个标定表上电时从 Flash 读取这样产线标定一次就行不用每次改代码。温度补偿是另一个坑。应变片的灵敏度随温度变化HX711 内部基准也有温漂。如果产品要在 0 到 40 度环境工作最好加一颗温度传感器比如 DS18B20在标定时记录不同温度下的零点码值和满量程码值运行时根据当前温度做插值补偿。不做补偿的话夏天和冬天读数可能差几十克客户会投诉。4. 避坑与常见问题排查4.1 读数一直为零或满量程现象上电后 HX711 读出来一直是 0 或者 0x7FFFFF怎么放砝码都不变。原因通常是接线错误或者时序不对。先检查 DOUT 和 SCK 有没有接反再确认传感器四根线有没有接对激励正、激励负、信号正、信号负。惠斯通电桥的激励和信号是分开的接反了输出就是饱和。如果接线没问题用示波器看 SCK 有没有脉冲DOUT 在等待时是不是高电平。还有一种可能是第 25 个脉冲的增益选择错了通道 A 增益 128 对应 25 个脉冲通道 B 增益 32 对应 26 个发错了就读不到正确数据。4.2 零点漂移严重空载读数慢慢往上爬现象空秤放那里读数每隔几秒涨几个字半小时能漂几百克。原因一般是电源噪声或者热漂移。先摸一下 HX711 和运放烫不烫如果发烫说明电源电压过高或者短路。然后检查模拟电源的滤波电容10uF 钽电容加 100nF 陶瓷电容是标配少了陶瓷电容高频噪声会串进来。如果硬件没问题在代码里加一个自动零点跟踪当读数在零点附近且变化缓慢时慢慢把零点码值往当前值靠但注意称重时不能跟踪否则会把重量也跟掉。4.3 称重时读数跳变超过分度值现象放上砝码后显示值在目标值上下跳 5 到 10 个分度。原因可能是滤波窗口太小或者机械结构有振动。先把滑动平均窗口从 10 加到 20 试试如果还跳检查传感器安装有没有拧紧秤盘有没有碰到外壳。另一个常见原因是 HX711 的输出速率设成了 80Hz噪声比 10Hz 大很多如果不需要快速响应把 RATE 引脚拉低用 10Hz。还有STM32 的 GPIO 模拟时序如果被中断打断会导致读出来的数据错位建议在读 HX711 时关掉全局中断读完再开。4.4 标定后线性度差小重量准大重量偏现象用 100g 砝码标定后称 100g 很准但称 5kg 差了 20g。原因是两点标定假设了理想线性但实际传感器和 ADC 都有非线性。解决办法是改用多点标定至少在 20% 和 80% 量程各加一个点。如果还不行检查传感器量程是不是选大了用 50kg 传感器称 5kg 的东西信噪比太低非线性也会放大。选型时让常用重量落在传感器量程的 30% 到 70% 之间最准。4.5 程序跑一段时间后死机或读数卡住现象连续运行几小时后读数不再更新复位后又正常。原因可能是 HX711 等待 DOUT 的 while 循环没有超时传感器偶尔丢一次数据就死等。解决方法是加超时计数器超时后复位 HX711 或者重新初始化。另外如果用了 FreeRTOS注意 HX711 读取任务和显示任务之间的优先级读取任务优先级太低会被饿死。我一般把 HX711 读取放在定时器中断里每 100ms 读一次主循环只负责显示和按键这样最稳。5. 二次开发从裸机到计价秤的改造思路如果你已经跑通了基础称重下一步大概率是想把它变成能算钱、能打印、能联网的计价秤。这里分享几个我实际改过的方向以及验证方法。第一个改造点是计价逻辑。基础版本只输出重量计价秤需要单价输入和总价计算。我会在 Flash 里存一个单价表用矩阵键盘或者旋转编码器输入 PLU 码然后重量乘以单价得到总价。注意金额计算要用整数分避免浮点误差。验证方法很简单输入单价 12.5 元/公斤放上 2 公斤砝码看总价是不是 25.00 元连续称十次看有没有累计误差。第二个改造点是数据记录。商用秤需要存交易记录我用 STM32 内部 Flash 模拟 EEPROM每条记录 16 字节存重量、单价、总价、时间戳。Flash 擦写寿命有限常见做法是开一个环形缓冲区写满一页再擦除这样能撑几十万次。验证时连续存 1000 条记录断电重启后逐条读出来对比看有没有丢数据或者乱码。第三个改造点是通信接口。很多场景需要把重量传到电脑或者 PLC最简单的是加一个 CH340 转 USB 串口每 100ms 发一帧数据格式可以是 ASCII 字符串或者 Modbus RTU。如果距离远换成 RS485 加 MAX485 芯片。我一般会定义一个简单的协议帧头 0xAA、重量 4 字节、校验和 1 字节、帧尾 0x55。验证时用串口助手抓包看数据是不是稳定丢包率能不能控制在万分之一以内。第四个改造点是低功耗。如果是电池供电的便携秤把 STM32 设成 STOP 模式HX711 设成掉电模式按键中断唤醒。实测下来2000mAh 电池能撑三个月以上。注意唤醒后要重新初始化 HX711 并等待稳定我一般会等 500ms 再读第一个数。最后一个技巧是关于标定数据的保护。我吃过一次亏产线标定好的秤客户误操作进了标定菜单把零点覆盖了整批货返工。从那以后我每次写标定功能都强制走一遍流程标定入口需要长按组合键 5 秒标定过程中每一步都要确认标定完成后把数据写两遍到 Flash 的不同地址读取时校验一致性不一致就报警。这个习惯帮我省了至少两次批量事故。希望这些经验能帮到你少走点弯路。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑