☰
基于STM32的智能计价电子秤设计:从传感器到量产全解析
2026/10/2 17:47:33 网站建设 项目流程

做嵌入式这些年,经手的称重类项目不少,但真正从称重传感器一路做到量产文件齐套的,还是最近这套基于STM32的智能计价电子秤。很多朋友问我嵌入式项目怎么练手,我觉得计价电子秤就是一个特别典型的综合项目:它要有模拟前端、有滤波算法、有按键状态机、有标定流程,还要考虑实际使用的可靠性和用户操作体验。这篇文章就把这套方案完整拆开讲清楚,从需求分析、硬件选型、软件实现到标定排障,整个过程一步不落。想做毕业设计、想入门嵌入式、或者想给产品做原型验证的同学,都可以直接参考。

1. 项目需求分析与整体方案设计

1.1 需求拆解:智能计价电子秤到底要解决什么问题

计价电子秤和普通体重秤最大的区别,是它要同时完成“称重”和“算钱”两件事,并且要在几秒钟内给出准确结果。商用场景里的典型流程是:商品放上秤盘 → 操作员输入单价 → 系统显示净重和应付金额,整个过程要快、要准、要直观。所以核心功能可以拆成五个:实时重量显示、去皮重、单价输入与修改、金额自动计算、累计金额管理。

精度是这类项目的灵魂。家用秤精度做到1g已经够用,但商用计价秤通常要把精度控制在量程的1/3000以上。我做的这台设计量程是10kg,最小分度1g,目标是在整段量程内误差不超过正负1.5g。这意味着从传感器到ADC到软件滤波,每一环都不能掉链子。如果哪个环节偷懒,最后显示出来的数字就会飘、会跳、会忽大忽小,用户一用就会投诉。

另外一个容易被忽略的需求是“易用性”。电子秤的操作者可能是菜市场摊主、生鲜店员,不会像咱们工程师一样调参数。所以界面必须简单清晰,按键反馈必须明确,操作出错时要有声音或文字提示。我在设计时反复提醒自己:这个项目不是在实验室里跑通就完事,而是要让人一天按几百次都不会烦。

1.2 为什么选STM32:算力、外设与成本的平衡点

选主控这件事,我见过不少争论。有人说51单片机便宜够用,有人觉得随便上个Cortex-M都行。但真正做过类似产品的人会告诉你,计价秤需要的不是“跑得多快”,而是“外设顺手、资源不紧、开发效率高”。以市面最常见的STM32F103C8T6为例,72MHz主频,64KB Flash,20KB RAM,片上有I2C、SPI、UART、定时器、ADC,一片批发价几块钱。称重信号采集用外部HX711,显示用I2C的OLED,按键扫描用GPIO,资源刚好够用,而且还有余量。

对比一下其它方案就明白了。51单片机外设太基础,一个I2C都要软件模拟,做显示、按键、传感器三件事时,代码和主循环会变得很难维护。树莓派那种Linux方案,虽然图形界面方便,但成本高、启动慢、实时性受系统调度影响,商用电子秤完全不需要这么重。STM32卡在中间这个位置,性能和成本最匹配,加上HAL库和CubeMX的加持,你会发现几行代码就能把一个外设配置起来,前两周的进度能赶上别的方案一个月。

1.3 系统架构:四个模块组成一台完整的秤

整体思路我习惯从上往下拆,物理上一台智能计价电子秤可以分成四个部分:称重传感器负责把重力变成微弱的电信号,HX711放大并数字化这个信号,STM32作为大脑读取数据、滤波标定、计算金额,最后通过OLED显示和按键完成人机交互。电源部分则给所有模块提供稳定的电压。

数据流是单方向的:重力 → 电桥输出差分电压 → HX711内部PGA放大 → 24位ADC转换 → STM32读取原始值 → 数字滤波与标定 → 重量数据 → 业务逻辑计算金额 → 显示刷新。理解这条链路很重要,后面所有调试都是沿着这条链找问题。如果你看到读数不对,先不要急着怀疑算法,从传感器开始一级一级排查,往往能快速定位。

2. 硬件设计:传感器、模拟前端与最小系统

2.1 称重传感器的选型与原理

计价秤用得最多的是电阻应变式称重传感器,核心结构是惠斯通电桥。简单说,传感器内部贴了四片应变电阻,受力时电桥失去平衡,输出一对差分电压信号。这个电压非常小,常见灵敏度是1mV/V到2mV/V,也就是说如果给传感器加5V供电,满量程时输出也只有5到10mV。这种毫伏级的信号,普通单片机内置ADC根本没法直接分辨,所以必须外接高分辨率ADC或者仪表放大器。

选型时要重点看三个参数:量程、灵敏度、综合精度。量程选多少取决于使用场景,我做的是10kg秤,选的是10kg量程的传感器,留了10%过载余量。如果硬要拿5kg传感器去称10kg的东西,时间一长弹性体就会永久变形,精度报废。灵敏度决定了信号大小,1mV/V还是2mV/V会直接影响后级电路的噪声表现。综合精度一般写着0.02%F.S.,意思是满量程误差大概是2g,这个数值基本决定了一台秤的精度上限。

实际项目里还有一个很多人会踩的坑:传感器的机械安装。传感器要通过螺栓固定在结构件上,受力方向必须垂直且均匀。拧螺栓的力度不同、秤盘的支点分布不均匀,都会造成“偏载误差”,也就是同样重量放在秤盘不同位置,读数不一样。这属于结构设计问题,纯软件无法解决,只能在安装时反复调整到四角误差合格。

2.2 HX711:专为电子秤设计的24位ADC

HX711是仪表类项目里的常客,一颗芯片就把放大和AD转换全包了。片内集成了可编程增益放大器,增益可设为32、64、128,还集成了稳压电源和振荡器,外围电路只需要几个电容电阻就能跑起来。它和主控之间只有两根线:PD_SCK是时钟输入,DOUT是数据输出,属于典型的串行通信。

这里必须解释一下为什么不用STM32自带的12位ADC。其实思路很简单,12位ADC在5V参考电压下理论分辨率就是5V除以4096,大约1.22mV。而传感器满量程输出才5mV,即便放大一百倍,也只能勉强分辨零点几克,想要稳定到1g精度太难了。HX711的有效分辨率可以做到20位以上,配合PGA放大,能把微伏级的信号变化清晰分辨出来。用一个芯片的外围电路换整体精度,这笔账非常划算。

HX711和使用者之间的物理接口,在实际项目里我推荐这样接:PD_SCK接STM32的一个普通输出引脚,DOUT接一个输入引脚。DOUT是开漏输出,所以外部要接上拉电阻,否则读不到正确电平。上拉我选4.7kΩ。另外HX711的模拟电源和数字电源要分开退耦,模拟电源引脚处至少放一个10uF钽电容加一个100nF陶瓷电容,这能显著减少读数跳变。

2.3 STM32最小系统与HX711的连接细节

STM32最小系统没什么神秘,常规六件套:8MHz晶振、两个20pF负载电容、复位电路、BOOT0和BOOT1引脚配置、每个电源引脚的100nF去耦电容、和一个1uF左右的 bulk 电容。很多人画板子时为了省事把去耦电容省了,短期没问题,但遇到强干扰或电磁兼容测试就会莫名其妙复位。这类问题最难查,所以在原理图阶段就要守规矩。

具体引脚分配,以STM32F103C8T6为例,我这样安排:PA0接HX711的PD_SCK,PA1接HX711的DOUT;I2C1的PB6和PB7接OLED;按键用PB0到PB5;蜂鸣器用PB8。把传感器相关引脚独立放在一组,按键和显示放在另外一组,布局上尽量避免数字信号和模拟信号交叉。开发阶段用杜邦线飞线没问题,但一旦要做PCB,模拟区域和数字区域的地要单点连接,避免数字地噪声窜进HX711的参考地。

还有一个小细节容易被新手忽略:HX711的DOUT在每次上电后会有一个自检过程,需要等待它稳定,不要在刚上电时反复读取。我的处理方式是在初始化函数里延时200ms,然后连续丢弃前几次读取结果,等到DOUT开始正常出数据再进入工作循环。这个习惯现在保留在每一个用到HX711的项目里。

2.4 显示、按键与提示电路的设计

显示器件我强烈推荐I2C接口的OLED,驱动芯片是SSD1306,尺寸0.96寸或1.3寸都行。I2C只占两个IO,代码库也很成熟,而且OLED可以自由分区显示,不像LCD1602那样只能显示固定位置的ASCII字符。在128x64的分辨率下,我通常把上半部分用来大字显示重量,中间显示单价,下半部分显示金额和累计状态,一眼就能看清当前核心信息。

按键这块,计价秤的数字键和功能键加起来至少十二三个。全用独立GPIO太浪费IO,所以我用矩阵键盘结构,4行4列,可以挂16个键。行线配置成推挽输出,列线配置成带上拉的输入,扫描时逐行拉低,读取列的状态。如果没有硬件上拉,STM32内部也可以开上拉,但为了稳定,我还是在列线上外接了一排10k排阻。按键消抖放在软件里做,检测到电平变化后延时10ms再确认,实测很稳。

再说蜂鸣器。计价秤按键应该有声音反馈,输入金额后也有确认提示。蜂鸣器我用NPN三极管驱动,GPIO输出高电平通过电阻驱动基极,集电极接蜂鸣器,发射极接地。注意蜂鸣器需要并联一个续流二极管,不然关断时会产生反向电动势,轻则影响电源,重则损坏IO口。这个细节在原理图阶段就要画进去。

2.5 电源设计:稳定是称重精度的前提

电子秤对电源纹波非常敏感。HX711的参考电压由内部稳压提供,但如果前级电源噪声大,这些噪声会通过电源引脚耦合进模拟前端,造成读数漂移。我在实际测试中对比过:用一个质量差的12V适配器供电,空载读数每分钟会上下跳2到3克;换成线性电源或者加了滤波电路之后,尾数纹丝不动。这个差别,比任何软件滤波算法都明显。

成熟的方案是外接12V适配器,先经过一个开关电源模块降到5V,再给传感器和HX711供电。STM32这路单独用AMS1117-3.3线性稳压。传感器供电和数字部分供电尽量不要从同一段线上走,PCB上可以用0欧电阻做模拟地和数字地单点连接。如果产品需要电池供电,还要在输入端加防反接和过压保护,比如一个肖特基二极管加一个TVS管。这些设计看起来增加成本,但能避免后续一大堆可靠性问题。

3. 软件设计:从驱动到业务逻辑的完整实现

3.1 开发工具链与工程搭建流程

现在做STM32开发,我推荐STM32CubeMX加Keil MDK这套组合。CubeMX负责图形化配置时钟、引脚和外设,Keil负责写代码和调试。新建工程时,在CubeMX里选择STM32F103C8Tx,配置RCC为外部晶振,设置时钟树让主频跑到72MHz。然后把需要用到的引脚都选好:HX711的两个引脚设为GPIO,OLED的I2C引脚设为开漏输出,按键引脚设为输入模式。

工程生成之后,我通常按模块划分代码目录。HX711驱动单独成一个hx711.c和hx711.h,里面提供读原始值、去皮、获取稳定重量几个接口;OLED用网上成熟的开源库,改一下I2C地址就能用;按键扫描和状态机放在key.c;业务逻辑放在main.c或独立的app.c。这样后续调试时思路清晰,哪一块出问题就直接进哪个文件。

一个实操上的建议:从最开始就打开Keil的微库(MicroLIB),并把堆栈设置到足够大。OLED显示需要不少栈空间,状态机里也有局部变量。我在早期测试时遇到过莫名死机,最后查到是栈溢出把变量冲掉了,把栈从默认值调到0x1000之后问题消失。这类问题一旦发生,非常隐蔽,所以宁可一开始留足余量。

3.2 HX711数据读取与滤波算法详解

HX711的读取时序逻辑不复杂,但细节容易出错。正确流程:先把PD_SCK拉低,然后等待DOUT变低,DOUT变低表示一次转换完成。接着产生25个正的时钟脉冲,前24个用于读出24位数据,采样规则是在每个SCK上升沿读取DOUT的电平。第25个脉冲用于选择下一次转换的通道和增益,脉冲个数不同对应的增益也不同。如果只需要默认配置(通道A,增益128),每次读完后补一个脉冲即可。

读出来的24位数据是二进制补码格式,最高位是符号位。代码里我会用一个int32_t变量接收它,然后左移8位再算术右移8位,完成符号扩展。很多新手在这里直接赋值给unsigned long,结果就是负重量显示成巨大的正数,清零后读数不对。这个问题在电子秤上特别致命,因为去皮和负值显示都依赖正确的符号。

单纯的单个读数没有意义,必须做滤波。我用的是“中位值平均滤波法”:连续采集15个原始值,去掉一个最大值和一个最小值,剩下13个取平均。这个算法对付瞬间冲击特别有效,比如商品放上秤盘那一下,传感器会产生明显抖动,取平均后重量能在0.5秒内收敛。比起简单滑动平均,它不会让干扰值一直滞留在窗口里,稳定性好很多。

3.3 重量标定与换算逻辑:从ADC值到克数

原始ADC值不是重量,两者之间必须建立线性换算关系。理论上传感器是线性的,所以在理想情况下,两个点就能标定:先空载采样,得到零点对应的ADC值ZERO;再放一个已知重量的标准砝码,得到满量程对应的ADC值FULL。那么比例系数K就等于“ADC变化量除以重量变化量”,未知重量就可以通过“当前ADC减ZERO再除以K”算出来。

实际标定中,我建议至少做三个点校验:20%量程、50%量程、80%量程。如果这三个点的误差都在允许范围内,说明传感器线性度不错;如果中间偏差很大,说明安装有应力或者传感器本身非线性,这时候只靠两点标定就不够准,得考虑分段线性插值。分段标定的做法是,把量程切成几段,每段用各自的斜率和截距,软件里多存几组参数。对于商用计价秤,这种分段方案能有效弥补机械和传感器的系统误差。

标定参数一定要掉电保存。我放在STM32内部Flash的某个扇区,用结构体存ZERO、K以及校验用的CRC。每次开机时读出参数并校验,如果CRC不对就进入“未标定”状态,界面提示重新标定。这个机制在量产时特别重要,因为每一台秤的传感器特性都不完全一样,必须在校验台上逐台标定并写入参数,否则产品没法出厂。

3.4 计价逻辑与按键状态机:稳定精确的核心

电子秤的金额计算要做好,细节全在数据格式里。我强烈建议避免用浮点数做业务计算,而是全部用整数。金额以“分”为单位,重量以“克”为单位。比如单价15.8元/斤,其实是15.8元每500克,那么每克的价格就是1580分除以500,等于3.16分。金额的计算公式就是“重量(克)乘以每克单价(分)再除以100转换成元分”。全程用整数乘除,不会出现浮点误差,代码也更简洁。

按键状态机是另一块容易写乱的地方。我按场景定义了四态:空闲态、单价输入态、称重计价态、累计显示态。每次按键扫描周期为10ms,读取矩阵键盘后,经过消抖确认,生成一个按键事件,主循环里的状态机根据当前状态决定事件如何处理。比如在单价输入态,数字键输入数字、确认键保存并回到称重态;在称重计价态,去皮键清零、累计键累加金额。

状态机的好处是逻辑清晰,不会再出现“按键响应混乱”这种问题。我早期用标志位方式写得这段逻辑,功能也能跑,但一旦按键连按、长按,就会进入奇怪的状态。改成状态机后,每个状态都有明确的入口和出口,边界情况全部有定义。这才是产品代码该有的样子。

3.5 显示界面与用户体验优化

显示分区要按照人的阅读习惯来:重量最重要,放最上面,字号最大;单价在中间;金额和累计在最下面。我用OLED的SSD1306驱动库,在内存里画好整个显示缓冲,再一次性刷到屏幕,避免刷新闪烁。每次重量变化时不要全屏刷新,而是只更新对应区域,OLED虽然有缓冲不闪烁,但频繁全刷还是会拖慢主循环。

体验上有一个关键点:重量稳定之后才算钱。因为顾客刚把商品放上去时,重量一直在变,如果每时每刻都把当前重量乘以单价,金额会跟着跳,非常不专业。我的做法是连续500ms内重量采样差值小于2g才判定为“稳定”,稳定后锁定当前重量并计算金额。如果之后重量又发生较大变化,说明商品被移动或加减,则重新回到“不稳定”状态。

此外,从用户使用角度,我还在界面上加了状态提示:稳定后用一个小圆点或文字标识,去皮后显示净重标志,累计有总金额时在底部显示。OLED能显示中文,这些提示对实际使用者帮助很大。项目做到这个阶段才算真正从“能运行”走向“好用”,这也是我反复和硬件搭档强调的一层价值。

4. 标定、测试与实战排障记录

4.1 标定流程实录:从裸数据到准确重量

标定不是把砝码放上去就完事,它有严格的操作顺序。我参考了计量器具校准的通用做法,结合嵌入式设备的实际情况,整理出四步流程:

第一步,把秤放在水平、无震动的台面上,通电预热5分钟。预热这一步特别重要,传感器弹性体和内部电阻需要时间达到热平衡,否则零点会持续漂移。第二步,清空秤盘,执行零点采样,记录50次滤波后的平均ADC值,写入ZERO。第三步,放上满量程标准砝码(我用的10kg,但建议用标称砝码或经过认证的重量块),同样采样并记录,算出比例系数K。第四步,用50%量程的砝码回验,如果误差在允许范围,标定结束,否则检查机械结构和传感器安装。

实际操作中,标准砝码的分级决定了标定精度。如果只是做课程项目,用几瓶矿泉水凑个大概重量也可以,但严谨的产品标定必须使用M1级以上砝码。我在工作室备了一套500g、1kg、2kg、5kg的标准砝码,几百块的成本,换来的是每次标定都能复现的安心。最后把ZERO和K写入Flash,断电重启后自动加载,这一步做完秤的基本功能就闭环了。

4.2 读数跳变、漂移与干扰的排查思路

如果你发现读数持续跳变,第一反应别去改滤波代码,先看硬件。用示波器量HX711电源引脚的纹波,如果超过几十毫伏,那就是电源问题。我在测试中遇到过一次很典型的情况:适配器供电下,重量值有规律地跟着负载电流波动,最后查到是传感器供电和蜂鸣器供电共用了一段线路,蜂鸣器一响,ADC值就跳。后来把传感器供电单独接LC滤波,问题立即消失。

零点漂移则多半是温度造成的。传感器弹性体对温度非常敏感,早上开机和运行两小时后的零底值能差好几克。处理办法有两个层面:硬件上,PCB布局时让HX711尽量远离发热元件;软件上,加零点跟踪功能。零点跟踪的思路是,当检测到连续一段时间内重量读数接近零点并且变化非常小时,自动微调零底值。但阈值要设得足够小,比如小于2g才触发,否则秤上放了轻东西会被误判成“零”给忽略掉。

还有一类隐藏问题是机械蠕变。称重后把东西一直放秤上,读数会随时间缓慢变化,这是传感器弹性体的特性。解决它最有效的办法是缩短“重量读取到金额锁定”的时间,不要让系统一直盯着重量计算,商品放上去后尽快锁定数值。这又在另一个角度印证了“稳定判定”逻辑的必要性。

4.3 常见异常现象与解决方案速查

我在调试这套基于STM32的智能计价电子秤时,把高频问题整理成了一个速查表,后来给几个做类似项目的朋友参考,大家反馈排查效率提升明显:

现象可能原因排查与处理方式
读数一直为零HX711DOUT上拉缺失检查外部上拉电阻,确认引脚配置为输入
读数跳变剧烈电源纹波、模拟地处理不当独立供电,加LC滤波,单点接地
读数负值异常符号扩展错误用int32_t接收并做算术右移
标定后称重不准砝码不标准、量程不匹配换标准砝码,核对传感器量程
OLED白屏或花屏I2C地址错误、上拉电阻过小扫描I2C地址,更换上拉值
按键偶尔没反应缺少消抖、行列扫描太快增加10ms消抖,扫描周期设为10ms
蜂鸣器干扰称重感性负载反向电动势蜂鸣器并联续流二极管,分开供电
掉电后标定丢失Flash写入未完成或无校验写完后读取校验,CRC错误自动提示重标定

这张表里的问题我基本都亲手踩过。尤其是“蜂鸣器干扰称重”这一条,如果不做测量,很多人根本想不到秤值会跟着声音跳。嵌入式系统里所谓“软硬不分家”,就是在这些细节里体现出来的。

4.4 工程化可靠性与量产经验

功能跑通之后,如果这个方案要真正交付或量产,还得补几道工序。首先是看门狗,我用STM32内部独立看门狗,喂狗周期1秒,程序异常卡死时能自动复位。其次是Flash参数的自愈机制,每次开机先检查标定参数CRC,如果发现被改写,就恢复默认值并进入待标定状态,避免产品带着错误参数运行。

量产测试阶段要做的检查项很多:静态电流是否超标、每个按键是否灵敏、OLED显示是否有坏点、满量程回零误差是否在允许范围、以及连续通电老化48小时后数据是否稳定。我在这个项目里吃过一个亏:一批屏在老化时偶尔白屏,最后定位到是I2C上拉电阻偏大,信号上升沿太慢。换成4.7kΩ之后,连续老化一周再没出现过问题。这类问题只有靠老化测试才能暴露,所以量产前一定要留足测试时间。

我个人的习惯是每一块板子在出厂前都跑一遍“自动测试脚本”,通过串口打印每个模块的检测结果。这个脚本不用太复杂,但能大幅降低售后返修率。测量数据、标定参数、测试日期全部记录在Flash里,后续如果出现品质问题,可以很快筛选出对应的批次,排查方向非常清晰。

做这个智能计价电子秤项目,最大的体会是“产品级的东西,功夫都在细节里”。传感器、ADC、单片机这些大方向选型谁都清楚,但最后拉开差距的是电源走线、滤波处理、零点跟踪、按键消抖这些容易被忽略的环节。我自己沉淀下来的几个习惯:一是硬件和软件并行设计,先用模块验证算法,再定PCB;二是标定流程一定要规范化,否则后面查问题非常痛苦;三是任何交互都要从使用者角度多问一句“这样会不会难受”。这套方案整体难度适中,又覆盖了嵌入式开发的大半知识点,非常适合用来建立完整的项目思维。后续如果时间允许,我还会把PCB布局、结构件安装和量产检测的更多细节整理出来,到时候再和大家继续聊。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询