
1. 项目缘起与整体设计思路做嵌入式这行十来年电子秤这个题目我前前后后碰过不下五次。有帮朋友做的毕业设计有给小型商超做的定制方案也有纯粹自己手痒想验证某个称重芯片的。说实话电子秤看起来简单——无非是传感器采集、单片机处理、屏幕显示——但真正要做到“计价准确、长期稳定、交互顺手”里面的门道比想象中多得多。这次我拿一个完整的基于STM32的智能计价电子秤方案来拆从选型逻辑到电路细节从代码架构到调试踩坑全部摊开讲。这个项目适合谁看如果你是嵌入式方向的学生正在找毕业设计或者课程设计的完整思路这篇可以直接当参考蓝本如果你是刚转行做硬件产品的工程师想了解一个量产级称重设备到底要考虑哪些因素这里面的选型逻辑和避坑经验同样适用哪怕你只是玩过51单片机、想往STM32平台进阶这个项目也是一个非常好的练手载体——它涉及ADC采样、GPIO控制、串口通信、定时器、外部中断、LCD驱动、按键状态机几乎把STM32的常用外设都摸了一遍。核心关键词先摆出来STM32做主控HX711做称重采集ESP8266做数据上云再加上LCD显示和矩阵按键做交互。整套方案的成本控制在百元以内但功能覆盖了称重、计价、去皮、校准、数据上传这几个核心模块。下面我从设计思路开始一层一层往下拆。1.1 为什么选STM32而不是51单片机很多人做电子秤第一反应是用51单片机便宜、简单、资料多。但实际做下来你会发现几个硬伤第一51的RAM和Flash太小跑一个带浮点运算的计价逻辑加上LCD驱动和串口协议栈代码空间非常紧张第二51的ADC精度和速度都有限虽然HX711是外部24位ADC但主控处理采样数据的速度直接影响响应体验第三51没有硬件SPI和硬件UART驱动LCD和ESP8266都得软件模拟CPU占用率高遇到多任务场景容易卡顿。STM32F103C8T6这颗芯片是我最常用的方案。72MHz主频、64KB Flash、20KB RAM带硬件SPI、硬件UART、多个定时器和外部中断价格也就十块钱出头。用它来做电子秤性能绰绰有余而且后续要加蓝牙、加WiFi、加打印模块都有足够的资源余量。更重要的是STM32的生态成熟标准外设库和HAL库都有大量参考代码调试工具链也完善ST-Link和J-Link随便选。1.2 称重传感器的选型逻辑电子秤的核心是称重传感器市面上常见的有电阻应变式、电容式、电磁力平衡式几种。电阻应变式成本最低、应用最广精度做到1/3000到1/10000没问题足够应付商用计价秤的需求。我选的是5kg量程的铝合金悬臂梁式称重传感器输出灵敏度1mV/V配合HX711做24位ADC采集。这里有个关键计算传感器满量程输出是1mV/V假设激励电压是5V那满量程输出信号就是5mV。HX711的PGA可编程增益放大器有32、64、128三档我通常选128倍增益这样满量程输入范围是±20mV5mV的信号刚好落在最佳采集区间。HX711内部24位ADC的有效精度大约在21位左右换算下来理论分辨率是5kg除以2的21次方约等于0.0024克实际受噪声和机械结构影响稳定分辨率做到0.1克完全没问题。1.3 整体架构与数据流整个系统的数据流是这样的称重传感器把重量转换成微弱的差分电压信号HX711负责放大和ADC转换通过两线串行接口把24位数据发给STM32。STM32拿到原始ADC值后经过滤波、去皮、校准系数换算得到实际重量。然后根据预设的单价计算总价把重量、单价、总价一起显示在LCD上。同时按键模块负责处理去皮、校准、单价设置等操作ESP8266模块负责把称重数据上传到云平台做记录和远程监控。电源部分我用的是12V适配器输入经过LM2596降压到5V给HX711和LCD背光供电再经过AMS1117-3.3降到3.3V给STM32和ESP8266供电。这里要注意模拟电源和数字电源的隔离HX711的模拟供电最好加LC滤波否则数字电路的噪声会串到称重信号里导致读数跳动。2. 硬件电路核心细节与实操要点硬件这部分我踩过的坑最多尤其是HX711的电路设计和PCB布局。很多人原理图照着抄能跑通但一做PCB就出问题读数跳得厉害或者温漂严重。下面我把关键电路逐个拆开讲。2.1 HX711称重采集电路的设计要点HX711的典型应用电路不复杂但有几个细节决定了最终精度。首先是激励电压的选择HX711的AVDD和DVDD可以共用5V也可以用3.3V。用5V激励时传感器输出信号更大信噪比更好但功耗略高。我一般用5V因为电子秤通常有适配器供电不差这点功耗。其次是参考电压的稳定性。HX711内部有稳压电路但对外部电源的纹波抑制有限。我在AVDD引脚旁边并了10uF钽电容和100nF陶瓷电容再串一个10欧姆电阻做RC滤波。实测下来不加这个滤波读数末位会跳3到5个字加上之后末位基本稳定在1到2个字以内。第三是模拟地和数字地的处理。HX711的AGND和DGND在芯片内部是分开的PCB上我通常用0欧姆电阻单点连接或者在芯片下方铺一块独立的模拟地铜皮再通过一个过孔连到主地。这个做法看起来有点玄学但实际对比过单点接地方案的温漂明显更小。第四是输入端的共模滤波。传感器信号进入HX711之前我加了两个100nF电容分别对地再串两个100欧姆电阻做限流。这个组合可以滤掉高频干扰同时对低频信号几乎没有影响。注意电阻要用高精度的温漂系数低于50ppm否则会引入额外的温度误差。2.2 STM32最小系统与外围接口分配STM32F103C8T6的最小系统包括晶振电路、复位电路、BOOT选择电路和SWD调试接口。晶振用8MHz无源晶振配两个20pF电容复位电路用10k上拉电阻加100nF电容BOOT0通过10k电阻下拉到地保证从Flash启动。引脚分配上我做了这样的规划HX711的SCK和DOUT分别接PB0和PB1用GPIO模拟时序读取LCD用SPI1接口CS接PA4DC接PA5RESET接PA6背光控制接PA7ESP8266用USART2TX接PA2RX接PA3矩阵按键用PB4到PB7做行扫描PB8到PB11做列读取蜂鸣器接PC13用定时器PWM驱动。这里有个容易忽略的点HX711的SCK引脚在不需要采集时应该保持低电平否则芯片会一直处于工作状态功耗增加不说还可能引入额外的噪声。我在代码里初始化时先把SCK拉低每次采集前再拉高采集完立即拉低。2.3 电源管理与抗干扰设计电源部分我用了三级降压12V输入经过LM2596降到5V再经过AMS1117-3.3降到3.3V。LM2596的开关频率是150kHz输出纹波大约50mV对于HX711来说还是偏大。所以我在5V输出后面加了一级LC滤波用10uH电感和100uF电容组成把纹波压到10mV以内。ESP8266的供电要特别注意它在发射数据时瞬间电流可以冲到300mA以上如果电源响应跟不上会导致电压跌落STM32可能复位。我在ESP8266的VCC引脚旁边并了一个470uF的低ESR电解电容和一个100nF陶瓷电容实测下来可以稳住瞬态电流。PCB布局上我把模拟部分HX711和传感器接口放在板子左侧数字部分STM32、ESP8266、LCD接口放在右侧中间用地线隔开。HX711的晶振和数字信号线保持至少5mm距离避免耦合。这些细节看起来琐碎但每一条都是实际调试中总结出来的。2.4 按键与显示模块的选型考量按键我用了4x4矩阵键盘16个按键足够覆盖数字输入、功能切换、确认取消这些操作。矩阵键盘的好处是占用IO少8个引脚就能读16个键。但要注意按键消抖硬件上每个按键并一个100nF电容软件上再用20ms的定时器做状态机扫描双重保险。LCD我选的是2.4寸TFT彩屏驱动芯片ILI9341分辨率240x320SPI接口。选它的原因是显示内容丰富可以同时显示重量、单价、总价、单位、状态提示等信息比段码LCD直观得多。ILI9341的SPI最高支持40MHzSTM32的SPI1可以跑到36MHz刷屏速度完全够用。这里插一句网上有人问“STM32使用ILI9341读ID是A1A1”的问题这其实是正常的。ILI9341的读ID命令返回0xA1A1说明芯片识别正确。如果读到0x0000或者0xFFFF那就要检查SPI接线和初始化时序了。3. 软件架构与核心代码实现软件部分我采用的是前后台架构主循环负责UI刷新和按键处理定时器中断负责HX711采样和ESP8266数据发送。没有上RTOS因为对于电子秤这个场景裸机跑起来更简单、更可控资源占用也更少。如果你后续要加更多功能比如多机联网、OTA升级再考虑上FreeRTOS也不迟。3.1 HX711驱动与滤波算法HX711的驱动本身不复杂核心就是按照时序读取24位数据。但原始数据跳动很大必须做滤波。我试过几种方案均值滤波、中值滤波、滑动平均滤波、卡尔曼滤波。最终选的是滑动平均加中值滤波的组合。具体做法是连续采样10次去掉最大值和最小值剩下的8个取平均。这个算法计算量小对脉冲干扰的抑制效果好而且响应速度可以接受。采样率方面HX711支持10Hz和80Hz两种模式我选的是10Hz因为80Hz模式下噪声明显增大对于计价秤来说10Hz的刷新率已经足够。代码实现上我用定时器TIM2每100ms触发一次采样在中断里读取HX711数据并存入环形缓冲区。主循环从缓冲区取数据做滤波和换算。这样做的目的是把采样和显示解耦避免UI刷新影响采样时序。// HX711读取24位数据的核心代码 uint32_t HX711_Read(void) { uint32_t data 0; uint8_t i; HX711_DOUT_Init(); // 配置DOUT为输入 HX711_SCK_LOW(); delay_us(1); while(HX711_DOUT_READ()); // 等待DOUT变低 for(i 0; i 24; i) { HX711_SCK_HIGH(); delay_us(1); data data 1; HX711_SCK_LOW(); delay_us(1); if(HX711_DOUT_READ()) data; } // 第25个脉冲选择增益 HX711_SCK_HIGH(); delay_us(1); HX711_SCK_LOW(); delay_us(1); // 补码转换 if(data 0x800000) data | 0xFF000000; return data; }这段代码里有个细节第25个脉冲用来选择下一次的增益。我选的是128倍增益所以发一个脉冲。如果要切换增益就发两个或三个脉冲。很多人读出来的数据不对就是因为忘了处理这个脉冲。3.2 计价逻辑与去皮校准实现计价逻辑本身很简单总价等于重量乘以单价。但实际做的时候要考虑几个问题。第一是重量单位我统一用克做内部计算显示时再转换成千克。第二是单价输入通过矩阵键盘输入支持小数点后两位。第三是去皮功能按下去皮键后当前重量被记录为皮重后续显示的都是净重。校准是电子秤最关键的一步。我的做法是在初始化时先采集一次空载ADC值作为零点然后放上标准砝码采集带载ADC值用两点法计算校准系数。公式是实际重量等于当前ADC值减去零点ADC值除以校准系数。校准系数等于带载ADC值减去零点ADC值除以标准砝码重量。这里有个经验校准砝码的重量最好接近满量程的2/3。比如5kg量程的秤用3kg砝码校准最合适。如果用太小的砝码比如500g那大量程段的线性度可能不好。另外校准时要等读数稳定后再确认一般等3到5秒。3.3 ESP8266数据上云与通信协议ESP8266我用的AT固件通过USART2和STM32通信。STM32发AT指令配置ESP8266连接WiFi和云平台然后定期发送称重数据。这里要注意AT指令的响应超时处理ESP8266有时候会返回ERROR或者超时代码里必须做重试机制。通信协议我设计得很简单每条数据包含重量、单价、总价、时间戳用JSON格式封装通过MQTT协议发布到云平台。MQTT的好处是轻量、支持断线重连适合这种低功耗、低带宽的场景。// ESP8266发送数据的简化流程 void ESP8266_SendData(float weight, float price, float total) { char json_buf[128]; sprintf(json_buf, {\weight\:%.1f,\price\:%.2f,\total\:%.2f}, weight, price, total); ESP8266_SendAT(ATCIPSEND0,, strlen(json_buf)); delay_ms(100); ESP8266_SendString(json_buf); delay_ms(500); }实际调试时ESP8266最容易出问题的地方是供电和串口电平匹配。ESP8266的IO是3.3V电平STM32的USART2也是3.3V可以直接连。但如果用5V的USB转串口工具调试一定要加电平转换否则会烧掉ESP8266的RX引脚。3.4 LCD界面布局与按键状态机LCD界面我分成了三个区域顶部显示状态栏包括WiFi连接状态和时间中间显示重量和单价用大字体底部显示总价和操作提示。刷新策略是局部刷新只更新变化的区域避免全屏刷新导致的闪烁。按键处理我用的是状态机每个按键有按下、释放、长按、连按四种状态。短按用于数字输入和功能切换长按用于进入校准模式连按用于快速调整数值。状态机的核心是定时器每10ms扫描一次按键记录每个按键的当前状态和持续时间。// 按键状态机核心逻辑 typedef enum { KEY_IDLE, KEY_PRESSED, KEY_LONG_PRESS, KEY_REPEAT } KeyState; void Key_Scan(void) { static uint8_t key_last 0; uint8_t key_now Read_MatrixKey(); if(key_now ! key_last) { if(key_now ! 0) { key_press_time 0; key_state KEY_PRESSED; } else { if(key_state KEY_PRESSED key_press_time 50) Key_ShortPress(key_last); key_state KEY_IDLE; } key_last key_now; } else if(key_now ! 0) { key_press_time; if(key_press_time 100 key_state KEY_PRESSED) { key_state KEY_LONG_PRESS; Key_LongPress(key_now); } else if(key_press_time 20 key_state KEY_LONG_PRESS) { key_state KEY_REPEAT; Key_Repeat(key_now); } } }这个状态机的好处是逻辑清晰扩展方便。后续要加新按键功能只需要在对应的处理函数里添加代码就行。4. 调试过程中的典型问题与排查实录调试阶段是最考验耐心的时候。我把这次项目中遇到的问题整理成了一张速查表方便你遇到类似情况时快速定位。4.1 称重读数跳动与漂移问题现象空载时读数在±5克范围内跳动放上砝码后读数缓慢漂移。排查过程首先检查电源纹波用示波器看HX711的AVDD引脚发现纹波有80mV明显偏大。在AVDD引脚增加LC滤波后纹波降到15mV但读数仍然跳动。接着检查PCB布局发现HX711的模拟地和STM32的数字地通过一条细线连接地电流噪声耦合到了模拟部分。改成单点接地后跳动范围缩小到±2克。最后发现传感器信号线没有屏蔽周围有电机干扰换成屏蔽线后读数稳定在±1克以内。解决方案电源加LC滤波、模拟地数字地单点连接、传感器信号线用屏蔽线并单端接地。4.2 ESP8266连接超时与断线重连现象ESP8266发送AT指令后返回“timed out”或者连接WiFi后频繁掉线。排查过程先检查供电发现ESP8266的VCC在发射瞬间跌落到2.8V低于最低工作电压3.0V。在VCC引脚并470uF电容后电压稳定在3.2V以上。然后检查AT指令的波特率发现STM32的USART2配置为115200但ESP8266出厂固件默认是74880两者不匹配。修改波特率后通信正常。最后发现WiFi信号强度只有-75dBm属于弱信号区域把ESP8266的天线远离金属物体后信号强度提升到-60dBm掉线问题解决。解决方案电源加储能电容、确认波特率匹配、天线远离金属和干扰源。4.3 LCD显示花屏与SPI通信失败现象LCD上电后花屏或者显示内容错位。排查过程首先检查SPI接线发现CS和DC引脚接反了调换后显示正常。然后发现刷屏速度慢一帧要200ms检查SPI时钟配置发现只跑了9MHz改成36MHz后刷屏时间降到30ms。最后发现显示内容偶尔错位检查发现是SPI和HX711共用了一个中断导致时序冲突把HX711的采集放到定时器中断里SPI刷屏放到主循环问题解决。解决方案检查接线、提高SPI时钟、分离中断和主循环的任务。4.4 常见问题速查表问题现象可能原因排查方法解决方案读数跳动大电源纹波大示波器测AVDD加LC滤波读数漂移地线干扰检查接地方式单点接地ESP8266超时供电不足测发射时电压加储能电容LCD花屏接线错误检查CS/DC调换引脚按键不灵敏消抖不够测按键波形加电容和软件消抖校准不准砝码太小检查校准流程用2/3量程砝码4.5 几个容易被忽略的实操心得第一个心得HX711的采样率不要盲目选80Hz。虽然80Hz听起来更快但噪声也更大对于计价秤来说10Hz的稳定读数比80Hz的跳动读数有用得多。我实测过10Hz模式下读数波动在±1克80Hz模式下波动在±5克。第二个心得校准系数要存在Flash里。很多人校准完就完了下次上电又得重新校准。STM32的Flash可以模拟EEPROM把校准系数和皮重存进去上电时读出来直接用。第三个心得ESP8266的AT固件版本要确认。不同版本的AT指令集有差异比如NonOS版本和RTOS版本的指令就不完全一样。我建议用AT固件1.7以上的版本稳定性好很多。第四个心得矩阵键盘的扫描频率不要太高。我一开始用1ms扫描一次发现按键偶尔会误触发。改成10ms扫描一次后配合20ms的消抖时间按键响应既灵敏又稳定。5. 功能扩展与后续优化方向这个项目做完之后我又陆续加了一些功能也思考了后续可以优化的方向。如果你已经跑通了基础版本下面这些扩展思路可以供你参考。5.1 增加蓝牙打印与手机App联动在现有的USART接口上挂一个HC-05蓝牙模块就可以实现蓝牙打印功能。把称重数据通过蓝牙发给便携打印机直接打出小票。手机App方面可以用ESP8266的透传模式把数据转发到手机端用App做数据记录和统计分析。这个扩展不需要改动核心代码只需要在通信协议里增加打印指令和App指令的解析。5.2 多机联网与云平台数据管理如果要做商超场景的多台电子秤联网可以把ESP8266的MQTT主题设计成按设备ID区分云平台订阅所有设备的主题做集中管理和数据汇总。这样老板在后台就能看到每台秤的实时称重记录和销售统计。云平台的选择上我用过巴法云和OneNet两者都支持MQTT接入难度不大。巴法云的优点是免费额度够用OneNet的设备管理功能更完善。5.3 低功耗设计与电池供电方案如果要做便携式电子秤低功耗是必须考虑的。STM32F103在睡眠模式下电流可以降到10uA以下HX711也有掉电模式。我的思路是无操作30秒后进入睡眠按键中断唤醒。ESP8266在不需要上传数据时进入深度睡眠定时唤醒。电池方面用18650锂电池配TP4056充电管理2000mAh的电池可以撑一周左右。5.4 从裸机到FreeRTOS的架构升级如果功能继续增加比如同时处理称重、显示、按键、WiFi、打印、存储裸机的前后台架构会越来越吃力。这时候可以考虑上FreeRTOS把每个功能做成独立任务用队列和信号量做任务间通信。FreeRTOS在STM32F103上跑绰绰有余RAM占用大约5KBFlash占用大约10KB。任务优先级分配上称重采集任务优先级最高显示和按键次之WiFi和打印最低。5.5 精度提升的进阶思路如果要把精度做到1/30000以上就需要考虑更多因素了。首先是传感器的选型要用更高精度的应变片和更好的弹性体材料。其次是ADC的选型HX711虽然够用但如果有更高要求可以考虑ADS1232或者CS5530。第三是温度补偿称重传感器的输出会随温度变化需要加温度传感器做补偿。第四是机械结构的设计传感器的安装方式、秤盘的刚度、限位结构都会影响最终精度。这个项目我从画原理图到打板调试前后花了大约三周时间。中间踩过的坑、烧过的芯片、调不出来的夜晚现在回头看都是经验。嵌入式这行就是这样理论看再多不如亲手焊一块板子、写一遍代码、调一次参数。希望这篇分享能帮你少走一些弯路把项目顺利跑起来。