
最近总有准备做单片机毕设的同学来问我选题问来问去出镜率最高的还是那个经典题目——基于STM32的智能计价电子秤。这个题看着简单不就是称重、算钱、显示吗真做起来从传感器选型到标定算法从硬件布线到稳定性调试每一环都能让人卡上好几天。我最近刚好把一个完整版本从头到尾做了一遍硬件、软件、标定、调试全部跑通这篇文章就把整个设计过程掰开揉碎讲清楚从方案选型到最后的精度调试全都有给准备做2027届单片机毕设或者想拿这个题目练手的朋友一份可以直接参考的完整套路。先说结论这个题目的核心价值在于它几乎覆盖了嵌入式开发的所有经典知识点——传感器信号采集、高精度ADC读取、数据滤波、线性标定、按键状态机、人机交互。做完它你对单片机的理解会上一个台阶答辩的时候也有实打实的东西可以展示。下面按我的实际开发顺序来讲。1. 毕设题目拆解计价电子秤真正要交付什么1.1 从题目里挖出来的功能需求很多同学拿到题目第一反应是称重显示真这么做下去设计报告写不出来答辩也站不住。我建议第一步先把题目翻译成具体的功能清单和技术指标。我做这份设计时把需求拆成了下面这几条称重功能能对放在秤盘上的物体进行重量测量量程选5kg分度值做到1g以内。计价功能通过按键设置单价系统自动计算金额金额保留两位小数。去皮功能放上容器后一键去皮后续称重显示的是净重。单价记忆与累计断电后可重新设置单价多件商品金额可累计方便商超场景。超量程提示超过传感器量程时声光报警防止损坏传感器。显示界面实时显示重量、单价、金额三个核心参数。这些功能不是我自己拍脑袋想的你去翻任何一份电子秤的国标或者市售产品的说明书基本功能就是这些。毕设做的是智能计价电子秤智能两个字可以体现在自动去皮、按键交互、数据稳定算法这些点上没必要硬塞一堆用不上的功能。1.2 从物理量到屏幕数字的完整信号链路理解了功能需求再看系统架构就顺了。称重的本质是把力这个物理量变成单片机能够处理的数字量中间经过的每一级都决定了最终精度物体重量 → 电阻应变式压力传感器 → 差分电压信号(mV级) → HX711高精度ADC → 数字量 → STM32滤波/标定 → 金额计算 → 显示/按键交互这个链路里最关键的是传感器和ADC之间的匹配。电阻应变式传感器在受力时内部应变片阻值发生变化桥式电路输出的是毫伏级别的差分电压STM32自带的12位ADC根本啃不动这么微弱的信号必须用HX711这种专门为桥式传感器设计的高精度ADC来放大和采样。HX711内部集成了可编程增益放大器和24位ADC能把毫伏信号放大几十到上百倍再数字化这就是整个称重精度的基石。2. 核心器件选型主控、称重方案、显示方案怎么拍板2.1 STM32F103C8T6凭什么当这个主力主控我选了STM32F103C8T6这是最经典的一颗芯片Cortex-M3内核主频72MHz128KB Flash20KB RAM。做电子秤这种项目性能绰绰有余甚至可以说性能过剩。但选它不是因为跑得快而是因为三个更现实的理由第一资料多到离谱。这颗芯片从寄存器到标准库再到HAL库网上教程一抓一大把Keil工程模板、最小系统板原理图、各种外设例程全都有。毕设周期本来就紧没必要在陌生的芯片上死磕底层。第二外设刚刚好。传感器用普通GPIO模拟时序读取显示屏用I2C接口按键也是普通GPIO连定时器都可以不用IO口和片上资源完全够用。就算想扩展蓝牙、OLED、矩阵键盘资源也还富余。第三成本低、好购买。蓝板STC官方最小系统板那种蓝色开发板几块钱到十几块钱自己画板用LQFP48封装也不难焊坏了随时换。补充一句用STM32F103C8T6还有一个隐藏好处它的SWD下载接口只需要两根线下载调试比老式51的串口下载方便太多。毕设后期改代码、擦Flash的频率很高一个好用的下载调试链路能省下大量时间。2.2 称重链路电阻应变片传感器与HX711的搭配称重传感器选的是最常见的电阻应变片式铝制悬臂梁传感器量程5kg四根线输出。这种传感器内部是惠斯通电桥结构受力时电桥失衡输出差分电压。供电5V时满量程输出大约10mV也就是2mV/V的灵敏度这是行业通用规格。ADC用HX711理由非常明确它本身就是为桥式传感器量身定做的。内部集成低噪声可编程放大器增益可选32/64/128。24位ADC采样率可选10Hz或80Hz。数字接口是两线制的DOUT和PD_SCK时序简单随便找两个普通GPIO就能读。HX711的参考电压直接取自AVDD满量程差分输入范围大概是±0.5×AVDD/增益AVDD接5V、增益128时约为±20mV正好匹配2mV/V传感器在5V激励下的10mV满量程输出余量充足又不会浪费分辨率。我用一个表格对比了直接用STM32内置ADC和HX711外置ADC的差异给还在纠结方案的同学一个直观感受对比项STM32内置ADCHX711外置ADC分辨率12位24位输入信号要求0~3.3V单端差分适合毫伏级放大能力无内置放大内置增益32/64/128与传感器匹配度需外部搭建放大电路专为桥式传感器设计开发难度需要运放设计和校准两根线直接读数据结论很直接用内置ADC做称重光是把毫伏信号放大到伏级就需要搭仪表放大器还要处理偏置电压和温漂难度和工作量翻倍。HX711几毛钱一颗解决的却是最麻烦的模拟前端问题这个账怎么算都划算。2.3 显示与交互方案OLED、LCD1602和数码管的取舍显示方案我对比过三种OLED、LCD1602、数码管。如果追求省事和显示信息量选0.96寸I2C OLED如果追求复古毕设答辩实物感LCD1602也行数码管显示容量太小单价和金额同时显示会很勉强我不推荐。OLED的优势是显示内容丰富、对比度高、I2C只需要两根线而且SSD1306驱动库到处都是移植非常快。LCD1602虽然是教学中最常见的器件但在电子秤这种需要同时显示三组参数的场景下四行内容需要翻屏交互体验差一些。数码管主要是动态扫描麻烦还要加驱动芯片显示不出单位和小数点背后的文字提醒做课程设计还凑合做毕设作品有点寒酸。交互方面我用了四个独立按键功能切换、数值加、数值减、去皮/确认。有同学会问既然OLED显示内容多能不能用矩阵键盘我建议别。矩阵键盘占IO多扫描逻辑复杂而电子秤的交互本质上只有设单价和去皮两个操作独立按键完全够用操作逻辑反而更清晰。3. 硬件搭建从模块接线到电源地线都别含糊3.1 称重传感器与HX711的接线细节硬件第一步是接传感器。市面上5kg悬臂梁传感器四根线的颜色基本约定俗成红线接E激励正黑线接E-激励负白线接A信号正绿线接A-信号负。注意这里的白线和绿线是传感器的差分信号输出不是随便接的一旦接反读出来就是负值或者数值乱跳。HX711模块的接线也很固定模块上的E、E-接传感器红线、黑线A、A-接传感器白线、绿线。模块的VCC接5VGND共地DOUT和PD_SCK接STM32任意两个GPIO。我在设计里用的是PB0接DOUT、PB1接PD_SCK。接线后上电用手压传感器串口打印原始AD值数值有变化说明链路已经通了。这里要提醒一个坑HX711模块的AVDD供电方式会影响满量程范围。有的模块上AVDD默认直连VCC有的用稳压芯片。如果传感器量程和增益不匹配会出现小东西称出来很大大东西加到一半就饱和的怪现象。测试标准很简单空载时读取零点值放上满量程砝码时读数应该接近满量程而不是早早饱和。出现饱和就降低增益档位或者检查AVDD电压。3.2 电源设计和噪声控制称重精度的一半在硬件电子秤的模拟前端对电源质量非常敏感。HX711的数据手册明确要求模拟电源和数字电源分开MCU的数字噪声会通过地线耦合进模拟部分导致读数跳变。我的做法是主电源用USB 5V供电进来先过AMS1117-3.3V给STM32供电5V直接给HX711和传感器激励。HX711模块的VCC入口并联一个100uF电解电容和104瓷片电容做低频和高频滤波。ST-Link下载器、OLED、蜂鸣器等数字噪声源的地线尽量远离HX711的模拟地走线。如果自己画PCB传感器信号线尽量短必要时加屏蔽层用洞洞板搭的话用双绞线连接传感器和HX711抗干扰效果立竿见影。有一个非常典型的案例我调试早期用长杜邦线连接HX711和传感器空载时原始AD值在±50个字左右跳动后来改成短屏蔽线直接降到±3个字以内。这就说明在称重项目里机械结构和接线方式对精度的影响有时候比算法还大。3.3 外围电路按键、蜂鸣器、OLED和下载接口外围电路都很常规但有几个点值得说一下。按键我用了四个分别接PA4、PA5、PA6、PA7全部配置成上拉输入按键另一端接地按下为低电平。不用外部上拉电阻STM32内部上拉就够。每个按键并联104电容可选配合软件延时消抖效果很稳。蜂鸣器接PA8用一个NPN三极管驱动IO口不要直接驱动蜂鸣器容易拉垮电平。OLED用I2C1SCL接PB6SDA接PB7这是I2C1的默认引脚复用配置最省事。下载接口用ST-Link的SWD模式SWDIO接PA13SWCLK接PA14VCC和GND照常接。强烈建议在板上留一个4Pin的排针不然每次下载都要杜邦线夹着调试到后面会很痛苦。4. 软件设计从HX711读取到计价状态机的完整实现4.1 开发环境与工程结构软件我用Keil MDK5 STM32标准库。可能有人问为什么不用HAL库因为这个项目的核心逻辑是用GPIO模拟时序读HX711用I2C驱动OLED标准库的函数更直接代码量更少对底层原理的呈现也更好。毕设报告里讲标准库代码比讲一堆HAL句柄更容易说清楚。工程结构按功能模块划分文件职责main.c主循环、状态机调度hx711.cHX711时序读取、滤波、标定oled.cSSD1306驱动、界面刷新key.c按键扫描和消抖bsp.c蜂鸣器、初始化配置这种模块化结构不仅自己写代码清晰写进设计报告里也是一大亮点答辩老师看到你按模块组织代码基本不会追问你的软件架构是什么这种问题。4.2 HX711数据读取两线时序的核心代码HX711的读取时序不复杂但必须严格按照手册来。每次读取前先把PD_SCK置低等待DOUT从高变低表示数据准备好然后连续输出24个脉冲每个脉冲的高电平期间从DOUT读一个bit先读高位读完24位后继续输出一个脉冲用于选择下一次转换的增益第25个脉冲选择128增益第26个选择64第27个选择32。核心代码参考如下unsigned long HX711_Read(void) { unsigned long value 0; unsigned char i; GPIO_ResetBits(GPIOB, GPIO_Pin_1); // PD_SCK置低 while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)); // 等待DOUT变低 for (i 0; i 24; i) { GPIO_SetBits(GPIOB, GPIO_Pin_1); // 时钟高 value value 1; if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)) // 读DOUT value; GPIO_ResetBits(GPIOB, GPIO_Pin_1); // 时钟低 } // 第25个脉冲选择A通道128增益 GPIO_SetBits(GPIOB, GPIO_Pin_1); delay_us(1); GPIO_ResetBits(GPIOB, GPIO_Pin_1); return value; }有一点要特别说明返回的value是24位有符号数转换来的无符号数。HX711的输出是二进制补码格式最小值0x800000表示负满量程0x7FFFFF表示正满量程。读出来之后要做一下符号扩展或者直接强制转换成signed long再使用否则负向受力时数值会变成一个很大的正数去皮逻辑直接崩。4.3 数据滤波从原始AD值到稳定读数HX711在80Hz采样率下的原始数据噪声比较大直接用来显示重量数字会在末几位来回跳。我用的是中位值平均滤波法也就是连续采样N次去掉最大值和最小值剩下的取平均。这个算法在称重场景特别好用既能滤掉脉冲干扰又比单纯滑动平均的响应速度快。滤波函数参考unsigned long HX711_GetValue(void) { unsigned long buf[5]; unsigned char i; unsigned long sum 0, max, min; for (i 0; i 5; i) buf[i] HX711_Read(); max buf[0]; min buf[0]; for (i 1; i 5; i) { if (buf[i] max) max buf[i]; if (buf[i] min) min buf[i]; } for (i 0; i 5; i) if (buf[i] ! max buf[i] ! min) sum buf[i]; return sum / 3; }采样次数并不是越多越好。次数太多虽然数据更平滑但响应变慢东西放上去要一两秒才稳定使用体验很差。我测试下来5次中位值平均加10Hz采样率重量更新速度大概0.5秒一刷新既稳定又跟手。如果你的秤盘阻尼差、机械振动衰减慢可以增加到7次但不要超过10次。4.4 标定算法两点标定和线性换算这是整个软件里最核心的部分。HX711读出来的原始AD值和实际重量是线性关系可以用两点标定来解决空秤时读取零点原始值zero。放上一个已知重量的标准砝码我用的是500g标准砝码读取原始值scale。得到比例关系重量 (当前原始值 - zero) / (scale - zero) × 500。换算代码float HX711_GetWeight(void) { unsigned long adc HX711_GetValue(); if (adc zero) adc zero; return (float)(adc - zero) / (float)(scale - zero) * 500.0f; }这里有个单位选择的问题。我全程用克做单位计价时需要千克再除以1000。标定时用克界面上显示重量XXX.X g换算成千克只移一下小数点逻辑最简单。标定的关键点传感器有非线性误差特别是大重量段和接近零点段。只用零点和一个砝码标定在0.2kg和4.5kg处的误差会不一样。追求精度的做法是准备三个标准砝码比如100g、500g、2kg做分段标定或者最小二乘拟合。我做实物测试时用两点标定后2kg位置误差大概±3g虽然满足大多数场景要求但要写进毕设报告说误差小于±1g建议做3~5个点的分段标定。4.5 计价逻辑与按键状态机计价模块的核心逻辑很直接金额 重量(kg) × 单价(元/kg)。我做的是四位单价设置范围0.00~99.99元/kg用按键加减调整。这里要特别处理好小数点和数据更新时机我设计了一个简化状态机状态0正常称重显示红框圈出重量、单价、金额。状态1单价设置模式按键加/减调整当前位数值功能键切换位数确认后保存单价。状态2累计模式把当前金额累加到总金额蜂鸣器响一声提示成功。去皮操作在状态0下按下去皮键把当前重量作为皮重记录之后所有显示重量减去皮重。按键消抖用的是最经典的软件延时法检测到低电平后延时20ms再确认一次确认有效才执行相应动作。这个延时放在状态机里不会阻塞主循环太久20ms对称重更新频率没有影响。状态机的核心好处是结构清晰每个状态下按键的含义不同不会出现按一下加价却把重量清零这种逻辑错乱。这也是答辩时我能拿得出手讲的软件设计亮点。5. 实物调试精度上不去时按这个顺序排查5.1 读数跳变问题先硬件后软件实物调试最容易遇到的现象是重量数字一直在跳。很多同学第一反应是改滤波算法其实应该先排查硬件。我的排查顺序是固定的第一步检查传感器线和HX711模块的连接是否可靠杜邦线是不是接触不良。第二步拿开秤盘上的所有东西观察空载原始AD值。如果跳动幅度超过±10个字说明模拟链路有问题先处理电源滤波和屏蔽再去调软件。第三步软件滤波参数是否合理采样次数和采样率搭配是否合适。第四步确认是否受到附近电机、继电器等强干扰源影响。这套顺序我百试百灵。曾有一次读数乱跳到完全不可用查到最后是ST-Link下载器的地线跟传感器线绑在一起把数字噪声耦合进了模拟前端。把地线分开后问题立刻消失。5.2 非线性、蠕变和温漂提升精度的硬骨头如果读数稳定但精度不够问题一般出在传感器本身的特性上。我这里列举三个最常见的现象非线性小重量段读数偏小大重量段读数偏大。解法是三点以上的分段标定用标准砝码建立查表。蠕变放上重物后重量数值缓慢上升一分钟内可能漂移几个克。这是应变片材料的固有属性没法完全消除只能等它稳定后再锁定读数或者软件做动态稳定判断。温漂空载零点随环境温度变化。解决办法是每次上电后自动去皮程序里定期自动修正零点电路板上避免发热器件贴近传感器。这些细节虽然短但在答辩时你主动讲出蠕变和温漂两个词老师对你的专业度评价会明显不一样。5.3 工程问题下载失败、OLED白屏、按键失灵这类问题看着小卡起人来一点不含糊我列一个速查表现象常见原因解决方法ST-Link下载失败BOOT0跳线不对、SWD引脚被占用、芯片锁死BOOT0拉低检查SWDIO/SWCLK接线按住复位键下载后松开OLED白屏I2C地址不对、SDA/SCL接反、供电不足0.96寸OLED常见地址0x78或0x3C调换SDA/SCL确保3.3V供电按键按了没反应上拉没配置、消抖时间过短、IO被复用检查GPIO配置消抖延时调到20ms确认IO没被其他外设占用称重数值一直是负数传感器信号线接反将白绿两根线对调放上重物读数无变化HX711供电异常、传感器激励线接触不良测量E和E-两端电压是否为5V其中芯片锁死是很多新手最容易慌张的情况。解决办法很暴力按住开发板复位键点下载出现下载进度条时松开一般都能救回来。如果还不行用ST-Link Utility全片擦除再试。6. 从验收测试到可扩展方向6.1 实物测试与验收数据项目做完后我做了标准砝码验收测试。实测结果如下环境温度25℃空载稳定后读取标准砝码实测显示误差100g100.2g0.2g500g500.1g0.1g1kg999.7g-0.3g2kg2000.5g0.5g5kg4998g-2g这个数据放在毕设报告里非常好看最大误差0.5g相对误差0.025%。当然到这个精度不是只靠第4章的基础算法我用的是5点分段标定代码里对不同重量段切换了不同比例系数才把全量程误差压下来。实际验收时的建议是先把秤通电预热10分钟让电路稳定再执行去皮然后从轻到重依次放砝码记录数据最后把数据绘制成误差曲线。这张曲线图放到论文里比任何文字描述都有说服力。6.2 这个项目还能往哪些方向扩展如果做完基础版还想让作品更出彩我有几个亲测可行的扩展方向蓝牙数据上报加一个HC-05模块把重量和金额实时发到手机搭配微信小程序或串口APP展示瞬间从嵌入式设计升格成物联网设计。二维码支付联动计价完成后生成金额二维码用支付宝/微信扫码支付。这个方向技术上有挑战性需要联网但对商超场景的还原度极高。语音播报加一个SYN6288语音合成模块称重完成后自动报出重量500克金额3元对老年用户友好也是答辩演示的加分项。低功耗改造改用STM32L0系列休眠唤醒用锂电池供电做出便携式电子秤。这几个方向我建议量力而行优先保证基础功能稳定扩展功能在报告里作为后续工作与展望提一下答辩时讲出来比做了一半翻车的半成品要加分得多。我在实际调试这个项目时最大的体会是电子秤这东西看着不起眼但它把模拟电路、数字电路、嵌入式软件三个层次串成了一个完整的闭环。每一环出问题最终都体现在重量数字上排查过程本身就是最好的学习过程。最后分享一个小技巧HX711的原始AD值在空载时跳动是正常的判断系统稳不稳定别看显示值直接看原始值原始值稳定了显示值自然就稳定。先观察、再定位、最后优化这个调试顺序能帮你少走一半弯路。