简介这份资源面向嵌入式初学者与电子设计爱好者提供一套基于STM32单片机的电子秤完整设计方案帮助读者理解从传感器信号采集到重量显示的全流程实现。压缩包共225个文件约18.89MB以C源码与头文件为核心辅以工程配置、原理图、PCB文件、物料表、项目报告及编译中间文件覆盖软件、硬件与文档三类资料。已有3093人学习下载说明该方案在同类项目中具有较高的参考价值。读者可从中获取STM32的GPIO、中断、定时器等外设配置代码HX711高精度称重传感器的驱动与通信实现以及平均值滤波、滑动平均滤波等数据采集与处理思路同时可参考原理图与物料表完成硬件搭建借助报告了解设计步骤、测试结果与常见问题排查方法适合作为课程设计、毕业设计或自学嵌入式开发的实践素材。1. 从一次称重漂移说起这套电子秤方案到底解决什么问题做过电子秤的人大多遇到过同一个场景砝码放上去读数稳如泰山过十分钟再称同一件东西数值却悄悄漂了几个字。很多人第一反应是传感器坏了换一个还是一样。问题往往不在硬件本身而在从应变片到 LCD 这一整条链路上——激励电压稳不稳、ADC 采样窗口对不对、滤波算法有没有把工频干扰吃干净、标定系数是不是只做了一次单点校准。这套基于 STM32 单片机的电子秤设计要解决的就是这条链路的完整闭环用电阻应变式传感器采集重量经 HX711 这类 24 位专用 ADC 转换成数字量再由 STM32 做滤波、标定、单位换算最后驱动显示并响应按键。它适合正在做单片机课程设计、电子类毕设的学生也适合需要快速搭一台小量程称重样机的开发者。整套方案围绕“称得准、读得稳、标得动”三个目标展开下面从需求、选型、硬件、软件一路讲到怎么验收。2. 需求拆解与技术选型量程、精度、采样率怎么定电子秤看起来简单真正动手前如果不把需求量化后面选型全是拍脑袋。这一章先把指标定死再倒推器件和方案。2.1 先把三个核心指标写进需求文档任何称重系统都绕不开量程、分辨率、采样率这三个参数它们互相牵制必须一起定。量程决定传感器和结构件的选型。做厨房秤一般是 05kg做快递秤是 030kg做实验用微量秤可能只有 0500g。量程定小了超载会永久损坏应变片定大了小重量段的分辨率又不够。通常的做法是按实际最大称重再留 20% 余量比如日常称 2kg 以内就选 5kg 量程的传感器。分辨率是能分辨的最小重量变化。一个 5kg 量程、24 位 ADC 的系统理论分辨率远高于实际因为机械结构和噪声会吃掉大部分有效位。工程上更关心“有效分辨率”也就是稳定读数能到多少克。厨房秤做到 1g、快递秤做到 5g 是比较合理的预期别一上来就写 0.1g那需要完全不同的传感器和屏蔽方案。采样率决定读数刷新快慢。HX711 默认 10Hz 或 80Hz 两档10Hz 适合静态称重80Hz 适合需要快速响应的场合。如果只是称东西10Hz 足够还能顺便把 50Hz 工频干扰滤掉一部分。把这三个指标写清楚后面每一步选型都有依据答辩时也能说清“为什么这么选”。2.2 主控与 ADC 的选型逻辑主控选 STM32 而不是 51 或 Arduino核心原因是它自带多路定时器、DMA 和足够的 Flash能同时跑采样、滤波、显示和按键不用在资源上抠抠搜搜。具体型号上F103C8T6 这类经典型号性价比高、资料全做课程设计完全够用如果要做低功耗手持秤可以换 L 系列。ADC 这块有个关键决策用 STM32 内置的 12 位 ADC还是外挂 HX711 这类专用芯片。内置 ADC 便宜、省事但 12 位分辨率对应 5kg 量程理论最小分辨约 1.2g再叠加电源噪声和参考电压漂移实际稳定读数可能只有 5g 左右做厨房秤勉强做更高精度就吃力。HX711 是 24 位 ΔΣ 型 ADC内置可编程增益放大器直接对接桥式传感器差分输入抗共模干扰强是电子秤领域的事实标准。代价是多一颗芯片、多两根线但精度提升是数量级的。我一般会这样建议课程设计如果重点是“把 STM32 用起来”内置 ADC 也能交差如果重点是“把秤做准”直接上 HX711省掉大量调参时间。2.3 传感器与显示方案的搭配传感器选电阻应变式称重传感器常见的有悬臂梁式、S 型、轮辐式。小量程厨房秤多用悬臂梁式结构简单、成本低大量程或需要抗偏载的场合用轮辐式。选型时重点看三个参数额定载荷、灵敏度一般是 1mV/V 或 2mV/V、综合误差。灵敏度越高同样重量输出的差分电压越大对 ADC 越友好。显示方案有 LCD1602、OLED、数码管几种。LCD1602 便宜、字符清晰适合显示“重量 单位”OLED 可视角度好、能显示图形适合做带菜单的界面数码管在强光下可读性最好但只能显示数字。课程设计里 LCD1602 和 OLED 用得最多前者偏基础后者偏体验。如果要做带去皮、累计、单位切换的交互OLED 加按键的组合会更顺手。供电也顺带定一下传感器和 ADC 对电源纹波敏感建议用 LDO 单独给模拟部分供电数字部分和模拟部分的地在单点汇合别让电机或继电器这类负载把地弹起来。3. 硬件总体设计从桥式电路到 STM32 最小系统硬件是这套方案的骨架画错一根线软件怎么调都白搭。这一章按信号流向拆成三块传感器与激励、ADC 与基准、主控与外围。3.1 称重传感器与桥式电路电阻应变式传感器内部是惠斯通电桥四个桥臂的应变片随受力变形阻值变化导致电桥失去平衡输出一个与重量成正比的差分电压。以 5kg、2mV/V 灵敏度的传感器为例激励 5V 时满量程输出只有 10mV每克对应的电压变化约 2μV这就是为什么必须用高增益、低噪声的 ADC。接线一般是四线制E、E- 是激励S、S- 是信号。有些传感器带屏蔽线屏蔽层接模拟地不要接数字地。传感器安装时要注意受力方向悬臂梁的固定端和受力端不能装反否则输出反向软件里还得取负号属于典型的血泪经验。激励电压的稳定性直接决定读数稳定性。如果用 STM32 的 3.3V 直接激励数字负载一波动激励就跟着抖读数自然漂。通常的做法是用一颗低温漂的基准源或 LDO 单独给传感器供电比如 5V 基准这样 ADC 的参考和激励同源比例式测量能抵消一部分漂移。3.2 HX711 接口与基准设计HX711 与 STM32 之间是两根线SCK 和 DOUT属于类 SPI 的时序但不是标准 SPI需要软件模拟或配置成普通 GPIO 翻转。它的通道 A 带 128 倍增益正好匹配传感器输出的毫伏级信号通道 B 是 32 倍增益一般用于检测电池电压之类的辅助量。关键点在于 HX711 的参考电压取自它的供电 AVDD所以激励和参考同源时电源的绝对精度不影响结果只影响噪声。这也是为什么 HX711 方案对电源要求没想象中那么苛刻但纹波一定要小。去耦电容要贴近芯片引脚AVDD 和 DVDD 分开走线模拟地和数字地单点连接。下面是一段 HX711 读取原始值的驱动代码用 GPIO 模拟时序注释里标了每个延时的作用// HX711 驱动GPIO 模拟时序STM32F103 平台 #define HX711_SCK_PIN GPIO_Pin_0 #define HX711_DOUT_PIN GPIO_Pin_1 #define HX711_PORT GPIOA // 读取一次 24 位原始值gain 选择通道与增益 // gain128 - 通道A 128倍gain32 - 通道B 32倍 long HX711_Read(unsigned char gain) { long value 0; unsigned char i; // 等待 DOUT 变低表示转换完成 while (GPIO_ReadInputDataBit(HX711_PORT, HX711_DOUT_PIN) 1); for (i 0; i 24; i) { GPIO_SetBits(HX711_PORT, HX711_SCK_PIN); // 短延时保证 SCK 高电平被 HX711 采样到 __nop(); __nop(); value value 1; GPIO_ResetBits(HX711_PORT, HX711_SCK_PIN); if (GPIO_ReadInputDataBit(HX711_PORT, HX711_DOUT_PIN)) value; } // 第 25~27 个脉冲设置下一次的通道与增益 for (i 0; i gain; i) { GPIO_SetBits(HX711_PORT, HX711_SCK_PIN); __nop(); __nop(); GPIO_ResetBits(HX711_PORT, HX711_SCK_PIN); } // 24 位有符号数补码转成 32 位 if (value 0x800000) value | 0xFF000000; return value; }这段代码里前 24 个时钟读出 24 位数据第 25 到 27 个时钟决定下一次转换用哪个通道和增益。延时不能省SCK 高电平太窄 HX711 可能采不到表现为读数乱跳或恒为某个值。如果发现读出来一直是 0xFFFFFF 或 0x800000先查 DOUT 有没有正常拉低再查 SCK 频率是不是太快。3.3 STM32 最小系统与外围电路STM32 最小系统包括晶振、复位、BOOT 配置、电源去耦。做电子秤不需要太复杂的外围但有几个细节值得注意。晶振用 8MHz 外部晶振倍频到 72MHz给定时器和串口留足余量。复位电路用 10k 上拉加 100nF 电容别省。BOOT0 下拉到地从 Flash 启动。显示接口按选型来LCD1602 用 4 位或 8 位并口占 6 到 11 个 IOOLED 用 I2C只占 2 个 IO更省引脚。按键至少三个去皮、单位切换、校准。如果要做菜单再加两个上下键。电源部分如果整机用 5V 适配器供电STM32 需要 3.3V用 AMS1117 这类 LDO 降压。传感器激励如果也用 5V注意和 STM32 的 3.3V 逻辑电平隔离HX711 的 DVDD 接 3.3VAVDD 接 5V这样两边都能正常工作。提示PCB 布局时模拟部分和数字部分分区HX711 尽量靠近传感器接口走线短而等长减少共模干扰。4. 软件架构与核心算法滤波、标定、单位换算硬件搭好只是能读到数读到“准数”靠的是软件。这一章按数据流讲采样、滤波、标定、换算、显示。4.1 采样与数字滤波HX711 出来的原始值带着噪声直接换算成重量会跳得没法看。滤波的目标是在响应速度和稳定性之间找平衡。常用的有三种均值滤波、中值滤波、滑动平均。均值滤波取 N 次采样求平均N 越大越稳但响应越慢。中值滤波取 N 次排序后的中间值能有效剔除脉冲干扰比如按键瞬间的抖动。滑动平均维护一个队列每次新数据进、旧数据出兼顾稳定和响应。工程上我一般用“中值 滑动平均”组合先取 5 次采样做中值剔除野值再进 8 点滑动平均。这样既不会被单次干扰带偏读数也足够平滑。// 组合滤波先中值再滑动平均 #define MEDIAN_N 5 #define AVG_N 8 long median_buf[MEDIAN_N]; long avg_buf[AVG_N]; unsigned char avg_idx 0; // 简单插入排序取中值 long median_filter(long new_val) { unsigned char i, j; long tmp; for (i MEDIAN_N - 1; i 0; i--) median_buf[i] median_buf[i - 1]; median_buf[0] new_val; long sort_buf[MEDIAN_N]; for (i 0; i MEDIAN_N; i) sort_buf[i] median_buf[i]; for (i 1; i MEDIAN_N; i) { tmp sort_buf[i]; for (j i; j 0 sort_buf[j-1] tmp; j--) sort_buf[j] sort_buf[j-1]; sort_buf[j] tmp; } return sort_buf[MEDIAN_N / 2]; } long moving_average(long new_val) { long sum 0; unsigned char i; avg_buf[avg_idx] new_val; avg_idx (avg_idx 1) % AVG_N; for (i 0; i AVG_N; i) sum avg_buf[i]; return sum / AVG_N; }中值滤波负责抗脉冲滑动平均负责平滑。MEDIAN_N 和 AVG_N 越大越稳但响应越慢实际调试时可以先设小一点看读数跳动情况再加大。如果发现去皮后零点还在缓慢漂移多半是温漂需要加温度补偿或定期自动归零。4.2 标定从原始值到重量的映射标定是电子秤最核心的一步做不好前面全白费。原理很简单重量和 ADC 原始值近似线性用两点确定一条直线。第一点空载记录零点原始值raw_zero第二点放已知砝码比如 500g记录raw_span。斜率k 500 / (raw_span - raw_zero)之后任意原始值raw对应的重量就是(raw - raw_zero) * k。// 两点标定 float cal_k 0.0f; // 斜率单位 g/count long cal_zero 0; // 零点原始值 void calibrate_zero(void) { // 空载时多次采样取平均作为零点 long sum 0; for (int i 0; i 20; i) { sum HX711_Read(128); delay_ms(50); } cal_zero sum / 20; } void calibrate_span(float known_weight) { long sum 0; for (int i 0; i 20; i) { sum HX711_Read(128); delay_ms(50); } long raw_span sum / 20; cal_k known_weight / (float)(raw_span - cal_zero); } float get_weight(void) { long raw moving_average(median_filter(HX711_Read(128))); return (raw - cal_zero) * cal_k; }标定时砝码要放在秤盘中心避免偏载引入误差。known_weight 建议选接近满量程的值比如 5kg 量程用 2kg 或 3kg 砝码这样斜率更准。如果只有小砝码也可以但误差会放大。标定系数通常存在 Flash 里掉电不丢。STM32 的 Flash 读写要注意先擦后写按页操作别频繁写否则寿命很快耗尽。4.3 单位换算、去皮与显示刷新单位换算就是克和盎司、磅之间的乘除注意用浮点还是定点。STM32F103 没有硬件浮点浮点运算靠软件模拟慢但够用。如果对速度敏感可以把重量放大 10 倍用整数运算显示时再插小数点。去皮功能记录当前重量作为皮重显示值减去皮重。实现上就是存一个tare_offsetdisplay weight - tare_offset。去皮后如果零点漂移可以加一个“自动归零”逻辑当重量小于某个阈值且持续一段时间就把当前值当作新零点。显示刷新不要每采一次就刷一次LCD 刷新慢刷太勤会闪。通常 100 到 200ms 刷一次人眼看起来连续又不闪。刷新时只更新变化的数字别整屏重写。注意浮点运算在中断里要谨慎中断服务函数尽量只做采样和标志位滤波和换算放到主循环避免中断时间过长影响其他任务。5. 避坑与常见问题排查读数漂、跳、不准怎么查电子秤调试阶段的问题高度集中这一章按“现象 → 原因 → 解决”列几条最容易翻车的点都是实际项目里反复出现的。现象一读数持续缓慢漂移几分钟漂几个字。原因通常是温漂或激励不稳。应变片对温度敏感HX711 的基准也随温度变化。解决方法是加温度补偿或者用比例式测量让激励和参考同源软件上加自动归零在空载稳定时定期把当前值设为零点。如果漂移方向固定也可以查一下传感器安装有没有预紧力。现象二读数跳变剧烈放上去稳不下来。先查电源纹波用示波器看 AVDD 上有没有几十毫伏的波动。再查 SCK 时序延时不够会导致 HX711 采样错误。软件上加大滤波窗口能压住一部分但如果是硬件问题滤波只是掩盖。另外检查传感器屏蔽线有没有接好附近有没有电机、继电器这类干扰源。现象三标定后小重量准大重量偏差大。这是典型的非线性或量程不匹配。先确认砝码是否准确再检查传感器是否接近满量程时进入非线性区。如果传感器本身非线性大可以多做几个标定点做分段线性拟合而不是只用两点。另外检查机械结构有没有摩擦或卡滞受力不真实也会导致偏差。现象四去皮后显示负值或零点乱跑。去皮逻辑里皮重和零点混在一起了。正确做法是皮重单独存零点单独标定显示值 原始重量 - 皮重。如果去皮后零点漂说明零点本身不稳回到现象一去查。还有一种情况是按键抖动导致重复去皮加 20ms 消抖。现象五HX711 读出来恒为 0xFFFFFF 或 0x800000。前者通常是 DOUT 一直高转换没完成或没接好后者是负满量程可能传感器接反或激励没上电。先量 E 和 E- 之间有没有激励电压再量 S 和 S- 之间空载时是不是接近 0mV。如果激励正常但信号不对检查传感器四根线有没有接错E 和 S 别搞混。这几条覆盖了大部分调试场景遇到问题按顺序排查别一上来就改代码。6. 验收与答辩怎么证明这台秤真的合格方案做完最后一步是验收。很多人把秤往桌上一放称个手机显示 180g 就说完成了答辩时被问“精度多少、怎么证明”就卡壳。验收要拿数据说话。先列验收指标做成表格逐项测、逐项记验收项测试方法合格标准零点稳定性空载连续观察 10 分钟漂移不超过 ±2 个最小分度线性度从 10% 到满量程取 5 个点正反行程各测一次各点误差不超过满量程的 ±0.5%重复性同一砝码反复加载卸载 10 次读数极差不超过 2 个最小分度去皮功能放容器去皮后再加砝码显示值等于砝码重量误差同上单位切换克、盎司来回切换算正确无累积误差超载保护加载 120% 量程显示超载提示卸载后恢复正常测试时砝码要轻拿轻放等读数稳定再记录。线性度测试从空载开始逐级加载到满量程再逐级卸载记录每个点的读数画成曲线看回程误差。重复性测试最能暴露机械结构问题如果极差偏大先查秤盘有没有松动、传感器安装有没有应力。答辩时老师最爱问三个问题为什么选 HX711 不选内置 ADC、标定怎么做的、误差来源有哪些。前两个前面章节已经讲清楚误差来源可以从传感器非线性、温漂、电源噪声、机械摩擦几个角度答能说出“我测过零点漂移是 X 个字”比空谈原理有说服力。我自己的习惯是每次做完一台样机先不急着写报告而是把上面这张表完整跑一遍数据记在本子上有问题当场改。有一次线性度怎么都过不了最后发现是秤盘和传感器之间垫了一片太软的橡胶受力被吸收了一部分换成硬连接立刻就好了。从那以后我每次装完机械结构都强制走一遍空载和满载对比确认受力路径干净再往下调软件。希望这套方案能帮你把电子秤从“能显示数”做到“敢拿去验收”。本文还有配套的精品资源点击获取