基于STM32的电子秤设计:从HX711采集到标定算法全解析 简介这套基于意法半导体STM32单片机的电子秤设计资料主要面向嵌入式初学者、电子设计竞赛备赛者以及课程设计学生。项目围绕称重应用以STM32为控制核心配合12864规格的液晶屏幕实时显示重量数值完整覆盖称重传感器信号采集、模数转换、数据处理、显示驱动及用户交互等主要环节。压缩包共146个文件以C语言源文件与头文件为主同时包含MDK工程配置文件、编译生成的十六进制与可执行文件、链接映射文件以及辅助脚本与备份文件整体容量约1.64MB目录结构简洁便于按模块查阅。目前已有3227人学习或下载。读者可以获得可直接打开的工程代码并借助其中的注释与配置说明理解STM32的GPIO、ADC、定时器以及液晶显示驱动等外设的编程方法同时资料中也提供了提高称量精度的改动思路如滤波与标定方法。无论是用于入门实践还是竞赛方案参考均具有较强的参考价值。 最近有个朋友让我帮忙搭一个基于STM32单片机的电子秤从传感器选型、HX711采集、到软件标定一步步调通。做完之后我有个很明显的感受这类项目在STM32的入门题里属于“看着简单做精细难”的典型校内课程设计和毕业设计里出现频率特别高很适合用来把单片机外设、信号采集、数据处理这几块知识串起来。先说清楚它能做什么称重、去皮、超量程报警是最基础的往上加蓝牙模块就能把数据同步到手机加个ESP8266就能上传到云端甚至做成智能快递秤、厨房营养秤。这个项目适合谁刚学完51单片机想转STM32的同学、正在为课程设计选题发愁的人以及想搞懂电子秤标定原理的爱好者都可以拿这篇文章当参考。下面我直接把整套方案的选型逻辑、硬件接线、软件代码和避坑经验都摊开讲。1. 整体方案与核心选型逻辑1.1 为什么选STM32而不是51单片机很多人一看到电子秤第一反应是“51单片机就能做何必上STM32”。这话没毛病如果只是单纯称重显示51完全够用。但我的建议是如果条件允许优先选STM32原因有三个。第一个是精度和稳定性优势。STM32的ADC是12位虽然也够看但真正干活的其实是HX711这颗24位ADC芯片它和单片机之间走的是简单的GPIO模拟时序用51还是STM32差别不大。不过STM32的主频高、内部资源丰富做滤波算法、处理按键消抖、驱动OLED这些任务时代码写起来更从容。第二个是外设和扩展空间。电子秤做好之后几乎所有人都会想加功能蓝牙上传、WiFi联网、触摸屏显示、语音播报。STM32的USART、I2C、SPI、DMA这些外设全都现成后续扩展不用换主控。如果用51加个蓝牙模块可能就要折腾很久。第三个是开发环境和生态。STM32有HAL库、标准库有Keil、STM32CubeIDE有铺天盖地的教程和例程。出现一个编译报错或者下载失败搜索一下基本都有答案。对于初学者来说这种“被踩过的坑都有人踩过”的生态本身就是巨大的效率加成。1.2 系统架构设计与器件清单整个系统用一句话概括就是称重传感器把重量变成微弱的差分电压信号HX711负责放大和模数转换STM32读取数据后做滤波和标定换算最后把重量显示在OLED上同时根据按键输入实现去皮和校准。器件清单直接照抄即可模块型号/规格作用主控板STM32F103C8T6最小系统板核心处理称重传感器5kg压力传感器半桥/全桥将重量转换为电压信号采集HX711模块红色PCB板差分放大 24位ADC显示0.96寸OLEDI2C接口显示重量、状态按键轻触按键 x2去皮、校准报警有源蜂鸣器超量程报警电源USB 5V供电或3.7V锂电池系统供电这套方案的核心器件成本大概在三十到四十元性价比很高。F103C8T6最小系统板现在十几块钱就能拿下HX711模块四五块钱OLED屏幕八九块钱5kg传感器七八块钱整体预算非常亲民。2. 硬件连接与关键原理2.1 传感器为什么必须配上HX711称重传感器的内部结构是惠斯通电桥简单理解就是四个电阻组成一个桥式电路受力时电桥不平衡输出电压随之变化。以5kg量程、灵敏度1mV/V的传感器为例如果用5V电压激励满量程时的输出只有5mV。STM32的ADC输入范围是0到3.3V12位分辨率下最小分辨电压大约是3.3V除以4096约等于0.8mV。理论上5mV的信号能采出几个台阶但问题是传感器输出的5mV本身就是满量程小重量时可能只有几百微伏直接接单片机ADC根本区分不出来。HX711解决的就是这个问题。它内部集成了低噪声放大器增益最高128倍5mV信号经过放大后变成640mV再用24位ADC去量化分辨率一下子提升了几个数量级。算一下就知道假设参考电压5V经过128倍增益后的信号范围是640mV24位ADC的码值范围是8388608那么满量程对应的ADC读数约为107万左右也就是每克重量大约对应214个码值这个精度对于普通电子秤来说绰绰有余。2.2 接线表与实物连接要点传感器的接线要特别注意颜色对应关系不同厂家颜色定义略有差异但大多数情况如下红线E接HX711模块的E黑线E-接HX711模块的E-白线S接HX711模块的A绿线S-接HX711模块的A-HX711模块和STM32之间的接线更简单HX711引脚STM32引脚说明VCC5V模块自带稳压给传感器和芯片供电GNDGND共地SCKPB0时钟信号推挽输出DTPB1数据输出浮空输入这里有个容易被忽略的细节HX711模块的VCC不要接到3.3V除非你买的模块明确支持3.3V供电。传感器在5V激励下的输出范围才是标准参数电压不够会直接影响测量精度。STM32这边如果用的是最小系统板板载的稳压电路可以直接从5V输入得到3.3V所以电源共地之后整个系统只有一路5V输入就行。2.3 OLED显示与按键电路OLED用的是I2C接口的0.96寸屏常见的SSD1306驱动芯片。SCL和SDA分别接到STM32的PB6和PB7这两个引脚是I2C1的默认引脚配合HAL库可以直接用软件I2C或者硬件I2C驱动。关于OLED有一个常见坑屏幕的I2C地址可能是0x3C也可能是0x3D买来先确认一下否则初始化时屏幕一直不亮排查半天发现地址错了。另外OLED模块一般自带I2C上拉电阻无需外加。按键设计上我习惯用内部上拉加外部下拉电容的方式按键按下时引脚读到低电平松手恢复高电平。每一个按键在硬件上并联一个104电容可以显著减少抖动比单纯靠软件延时消抖更可靠。两个按键的功能分配是按键1短按去皮长按进入校准模式按键2在校准模式下切换校准点。3. 软件核心实现与算法解析3.1 Keil工程搭建需要注意的几个点这个项目的软件部分我建议直接用标准库或者HAL库都行关键是把你用到的外设初始化配置清楚。用HAL库的话记得在STM32CubeMX里把GPIO、I2C、USART调试用都配好生成工程后再添加HX711的驱动代码。用Keil新建工程时有几个细节容易出现问题。芯片型号要选对STM32F103C8是64K Flash、20K RAM的型号如果误选了CBT6这样的高容量型号Flash地址配置和启动文件都不匹配。启动文件要选startup_stm32f10x_md.s这是中等容量型号对应的启动文件。另一点是ST-Link下载器的配置在Options for Target的Debug选项卡里选ST-Link Debugger然后进入Settings确认能识别到芯片如果这里就报错后面所有调试都无从谈起。如果你之前装了Keil5兼容C51的版本又装了STM32的芯片包使用时要注意工程配置里Device选项卡必须选到STM32F103C8否则编译器会按照51的环境去编译ARM代码满屏报错。3.2 HX711驱动时序与核心代码HX711的通信协议只有两根线但时序细节必须搞对。数据输出的过程是这样的DT引脚平时是高电平当芯片完成一次转换后DT拉低表示数据准备好。单片机检测到DT变低后每给SCK一个高脉冲DT引脚就输出一位数据共24位高位先出。读完24位后再补一个脉冲这个脉冲决定下一次转换的通道和增益补1个脉冲就是A通道128倍增益。下面是一个基于HAL库的读取函数实测可用uint32_t HX711_Read(void) { uint32_t data 0; uint8_t i; // 等待数据就绪DT拉低表示转换完成 while (HAL_GPIO_ReadPin(HX711_DT_GPIO_Port, HX711_DT_Pin)); for (i 0; i 24; i) { HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_SET); data data 1; if (HAL_GPIO_ReadPin(HX711_DT_GPIO_Port, HX711_DT_Pin)) { data; } HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_RESET); } // 第25个脉冲选择A通道、增益128 HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_RESET); return data; }读取到的24位数据是二进制补码形式需要转换为有符号数才能参与后续运算int32_t raw; if (data 0x800000) { raw (int32_t)data - 0x1000000; // 符号扩展 } else { raw (int32_t)data; }3.3 数据滤波与标定算法HX711虽然精度高但裸数据直接用会让人抓狂重量值轻微跳动是常态。我常用的做法是滑动平均滤波维护一个长度为10的缓冲区每来一个新数据就覆盖最旧的一个然后对缓冲区整体求平均。这个算法的优点是响应速度快、实现简单而且能有效抑制高频抖动。如果环境干扰特别严重还可以升级成去极值平均滤波先对10个数据排序去掉最大值和最小值再对剩下的8个求平均。这样可以把偶然的毛刺直接剔除。代价是代码量增加一点但稳定性提升明显。标定是整个程序里最关键的算法。电子秤的标定原理是线性拟合假设重量和ADC读数成正比那么只要知道两个点的坐标就能确定整条直线。标定流程是这样的空秤状态下读取稳定ADC值记为adc_zero。放上一个已知重量的砝码比如1kg读取稳定ADC值记为adc_1kg。计算比例系数scale (adc_1kg - adc_zero) / 1000.0f单位是ADC码值每克。实时重量计算weight_g (current_adc - adc_zero) / scale。float Get_Weight_Gram(void) { int32_t current_adc Get_Filtered_ADC(); float weight_g (float)(current_adc - adc_zero) / scale; return weight_g; }标定参数adc_zero和scale必须掉电保存。可以用STM32内部的Flash也可以用外接EEPROM比如AT24C02。我习惯把参数存在内部Flash的最后几页通过一个自定义的写入函数在标定完成后刷新这样不依赖额外硬件成本最低。3.4 主循环逻辑去皮、报警与显示主程序的逻辑其实不复杂关键在于状态管理。我建议用一个简单的状态机来区分正常称重、去皮、校准这三个场景。正常称重状态下每200ms读取一次滤波后的ADC值换算成重量后刷新OLED显示。如果重量超过设定阈值打开蜂鸣器报警。去皮功能的实现很直接按下去皮键时把当前ADC值更新为adc_zero相当于重新校准零点。比如放上一个容器按下去皮之后显示的重量就是容器内物体的净重。校准状态需要更谨慎的控制逻辑。长按按键1进入校准模式后OLED显示当前ADC值此时先确保秤台上没有物品按按键2确认记录零点然后放上已知砝码等待读数稳定再按按键2记录满量程点自动计算scale后写入Flash退出校准模式。整个过程中建议增加蜂鸣器提示音每成功一步响一声操作体验会好很多。4. 调试实录与常见问题排查4.1 下载失败error: no stm32 target foundSTM32开发中最让人崩溃的就是下载程序时提示找不到芯片。常见情况是第一次使用ST-Link驱动没装好或者接线错误。排查顺序是这样的先看ST-Link的指示灯是否正常再看电脑设备管理器里能不能识别到调试器最后检查目标板的SWD接口是否连接牢固。还有一个很容易忽略的原因STM32的SWD接口和复位引脚之间如果接了电容或者二极管会影响下载时序。我之前遇到过一次下载失败排查了半天最后发现是目标板的复位引脚被一个按键电路占用了导致SWD协议里复位那一步出错。解决办法是把按键从复位引脚挪到其他GPIO上或者下载时按住按键。4.2 称重数值跳变严重数值跳变是电子秤项目里最常遇到的问题。首先检查供电是否稳定HX711的模拟电源对纹波非常敏感如果用开关电源供电建议在模块电源引脚并联一个100uF电解电容和104陶瓷电容。其次检查传感器和HX711之间的连线是否过长或者被其他电线干扰尽量把这段线缩短。软件层面也可以做优化。除了前面提到的去极值平均滤波还可以增加一个“数据稳定判断”逻辑连续几次读数的差值都小于某个阈值才认为重量稳定再更新显示。这样可以避免OLED上的数字频繁闪烁体验会好很多。4.3 标定不准或线性度差标定不准的原因往往是砝码重量和实际值不符或者机械结构没有放平。我踩过的一个坑是传感器安装时没有和受力面保持水平导致小重量时读数偏小、大重量时读数偏大整条曲线都不是直线。后来把传感器固定在硬质亚克力板上托盘四角均匀受力线性问题立刻缓解。另外注意传感器的量程选择。如果只是称厨房食材5kg量程够了如果要做人体秤至少得选50kg甚至100kg的传感器。量程选大了小重量时输出信号太小精度受影响量程选小了稍微超重就损坏传感器。4.4 其他环境相关的坑开发过程中还遇到过两类比较典型的问题。一类是OLED屏幕不显示排查后发现是I2C地址写错0x3C写成了0x3D。另一类是项目后期需要连接电脑上位机查看数据但STM32的虚拟串口在设备管理器里显示感叹号这是驱动没有正确安装导致的重新安装驱动后恢复正常。还有一点想提醒Keil5如果同时装了51和STM32两个平台创建工程时一定要仔细确认Device选项卡里选的是不是STM32F103C8。我朋友之前一个程序编译报错找不到core_cm3.h就是因为Keil里默认的GNU编译器路径和ARM编译器路径冲突后来在Manage Project Items里重新添加了CMSIS路径才解决。5. 扩展方向与个人实操心得这个项目做完之后如果你想继续往深处走有几个很自然的扩展方向。最简单的是加一个HC-05蓝牙模块通过串口把重量数据发送到手机App做一个智能体重秤想再进阶一点就加ESP8266模块把数据上传到云平台实现远程查看如果想挑战更高难度可以换成带触摸屏的版本把按键操作全部搬到屏幕上体验会上升一个档次。我自己实际操作完这个项目最大的体会是电子秤这个东西电路设计只占一半另一半在机械结构和标定细节上。很多人觉得传感器接上就能用实际上传感器的安装方式、受力均匀度、环境震动、电源纹波每个环节都会偷走一点精度。这也是为什么很多厂商造的秤看着硬件一样实际精度差异却很大的原因。最后分享一个调试利器在初始版本里我建议通过串口把ADC原始值打印到电脑上先不要急着接OLED。这样你能直观地看到传感器在不同状态下的输出变化排查问题效率会高很多。等数据稳定了再接上显示模块做交互整个开发过程会顺畅不少。本文还有配套的精品资源点击获取