STM32+HX711电子秤仿真设计:从原理到Proteus实现 简介基于STM32单片机与HX711称重传感器的电子秤超重报警Proteus仿真资源包面向嵌入式初学者、电子设计爱好者及课程设计开发者。压缩包内含282个文件包括C/H语言源程序、Keil工程配置文件、Proteus仿真工程文件pdsprj、HEX固件以及PDF说明文档等整体大小18.44MB结构清晰便于快速查阅与二次开发。目前已有1367人学习下载可帮助理解高精度重量采集、阈值比较和声光报警的设计流程仿真环境能直观还原系统运行状态。通过完整源码与配套电路读者既能掌握STM32外设驱动与HX711数字滤波处理又能在Proteus中直接观察称重与报警联动效果为后续真实硬件调试和功能扩展提供清晰参考。1. 项目概述与整体设计思路1.1 电子秤仿真系统能做什么拿到这份资料先把它的功能摸清楚这是一个基于STM32单片机、配合HX711称重传感器专用ADC芯片实现的电子秤全流程项目区别在于它不需要实物电路板直接靠Proteus仿真软件跑通整个逻辑。系统支持实时重量读取、LCD屏幕显示、按键去皮、报警阈值设置以及超重时的声光报警。仿真环境里用电位器模拟称重传感器的微小差分电压变化调节电位器就相当于往秤盘上放东西读数会跟着变超过设定阈值后蜂鸣器响、LED亮。整个过程完整复现了一台工业电子秤的核心工作流。对于正在做课程设计、毕业设计或者单纯想搞懂“单片机怎么读取称重传感器数据”的开发者来说这套资料的价值很明显源代码是可编译、可烧录、可仿真的不是那种网上满天飞的残缺代码。你不需要先买一套HX711模块和称重传感器回来就能把整套测量逻辑、标定流程、报警机制全部跑通等理解了原理之后再转实物踩坑成本直线下降。1.2 为什么选STM32HX711Proteus这套组合先说说方案选型。电子秤这类项目市面上有很多实现路径比如用51单片机加个ADC0809、或者直接用STM32内部ADC采集。但这个项目偏偏选了HX711作为采集前端这里面的门道值得琢磨。称重传感器的输出信号是微伏到毫伏级别的差分电压如果用普通ADC直接采样分辨率根本不够。HX711是专门为称重应用设计的24位高精度ADC芯片内部自带低噪声可编程增益放大器PGA最多可以放大128倍直接把传感器出来的微弱信号放大到单片机能够稳定读取的范围。再加上它内置稳压电路可以直接为传感器提供稳定的激励电压外围电路极简一块小板子就能搞定。相比STM32内部12位ADCHX711在精度和抗干扰方面都是碾压级的优势。选择Proteus做仿真核心原因是成本低、调试效率高。实物方案需要买模块、焊板子、接线一旦出问题排查起来费时费力仿真环境里改一条线、换一个参数只需要几秒钟。而且Proteus对STM32F103系列的支持已经比较成熟可以加载Keil生成的hex文件直接运行配合虚拟示波器、虚拟终端调试程序非常适合学习阶段反复折腾。2. HX711测量原理与信号链路2.1 电阻应变片与电桥原理想弄懂这个项目先得明白称重传感器内部是怎么回事。市面上常见的单点式称重传感器里面核心部件是4片电阻应变片它们以全桥方式连接。桥路的供电端是E和E-信号输出端是S和S-。没有任何负载时电桥四个桥臂的电阻相等输出差分电压近似为零。当重物压在传感器弹性体上时弹性体发生形变贴在它表面的应变片跟着被拉伸或压缩电阻阻值发生变化——其中对臂的两片电阻增大另外两片减小。电桥平衡被打破后S和S-之间就会出现一个微小的差分电压。这个电压有多小呢一般来说额定负载下传感器的灵敏度在1mV/V到2mV/V之间。也就是说如果供电电压是5V满量程时输出差分信号大约只有5mV到10mV。这种级别的微弱信号如果不经过放大单片机ADC根本无法准确分辨。而这正是HX711存在的意义。2.2 HX711芯片关键特性HX711最核心的几个参数搞清楚了才算入门。第一它内部集成了24位Σ-Δ型ADC输出二进制补码格式的转换结果。第二可编程增益放大器支持A通道128倍或64倍增益、B通道32倍增益称重场景最常用的就是A通道128倍。第三片上稳压器可以输出稳定的模拟电源给传感器桥路供电大大简化了外围设计。第四数据输出速率可选10SPS或80SPS这个速率对电子秤这种对实时性要求不高的场景完全够用而且低速率本身就能起到一定的滤波效果。HX711和单片机之间是典型的串行通信方式只有两根线PD_SCK时钟和DOUT数据。但注意这种通信不是标准的SPI接口它没有片选线时序也需要严格按照芯片手册来实际上属于一种类似SPI的定制协议。很多初学者在这里栽跟头代码写不出来。放心后面的章节我会把时序讲透。2.3 数据读取时序与增益选择HX711的数据读取时序不复杂但细节非常多。芯片空闲时DOUT保持高电平当一次转换完成后DOUT会被拉低此时通知单片机“数据准备好了”。单片机检测到DOUT为低电平后开始产生时钟脉冲。每给PD_SCK一个高脉冲DOUT引脚上就输出一位数据先高位后低位连续24个脉冲正好读完24位数据。读完后还需要继续给1到3个额外时钟脉冲这决定了下一次转换的增益和通道第25个脉冲下一次使用A通道128倍增益第26个脉冲下一次使用B通道32倍增益第27个脉冲下一次使用A通道64倍增益称重项目基本上都选第25个脉冲也就是通道A、128倍增益。有一点特别容易踩坑读出来的24位数据是二进制补码格式最高位是符号位。如果你用无符号整数去接收当传感器受到拉力或零点附近负漂移时读数就会变成一个很大的正数整个显示逻辑就乱了。所以正确做法是累加时使用有符号类型int32_t或者读出无符号数后手动处理符号扩展。下面是HX711读取数据的核心函数这个函数可以直接抄进工程使用int32_t HX711_Read(void) { uint8_t i; int32_t value 0; // 等待DOUT拉低表示转换完成 while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)); // 读取24位数据高位在前 for (i 0; i 24; i) { GPIO_SetBits(GPIOB, GPIO_Pin_0); // SCK拉高 delay_us(5); value value 1; // 左移一位 if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)) { value; } GPIO_ResetBits(GPIOB, GPIO_Pin_0); // SCK拉低 delay_us(5); } // 第25个脉冲设置A通道128倍增益 GPIO_SetBits(GPIOB, GPIO_Pin_0); delay_us(5); GPIO_ResetBits(GPIOB, GPIO_Pin_0); delay_us(5); return value; }读取完成后还有一个重要操作延时。HX711完成一次转换需要一定时间即使是最高速的80SPS转换周期也有12.5ms。所以主循环里读取频率不要过高最好做一次读取间隔10ms以上的控制。否则可能出现DOUT还没拉低你就去等待转换完成结果卡死主程序。3. 硬件设计与接线3.1 Proteus元器件准备与选型仿真工程里涉及的核心元器件主要有STM32F103C8主控、HX711模块模型、LM016L字符液晶Proteus里1602的标准模型、蜂鸣器、LED、按键以及一个用于模拟称重传感器信号变化的电位器。这里重点说明一下传感器部分的处理思路。Proteus元件库中其实没有现成的“称重传感器”符号很多教程会选择用两个可变电阻串联搭一个桥路来模拟。如果你拿到的资料里已经画好了仿真电路直接打开用就行。如果你打算自己从零搭一个最省事的做法是在HX711的S和S-之间接一个精密电位器调节电位器改变输入电压差等效于传感器输出的微小变化。这种方式虽然不能完全反映电桥的动态特性但用来验证数据读取、标定、报警这条逻辑链路已经足够了。3.2 引脚分配与接线表为了后续对照代码理解这里把最常用的一组引脚分配整理成表格。不同版本的资料引脚可能略有差异但逻辑一致只要对应修改程序里的宏定义即可。HX711引脚STM32引脚说明VCC3.3V模块供电GNDGND共地SCKPB0时钟输入DOUTPB1数据输出E / E-传感器激励供桥电压外设STM32引脚说明1602 LCD RSPA0寄存器选择1602 LCD ENPA1使能信号1602 LCD D4-D7PA2-PA5四线数据蜂鸣器PA6超重报警LED指示灯PA7超重指示按键K1去皮PB8触发去皮按键K2阈值PB9增大报警阈值按键K3阈值-PB10减小报警阈值LCD选择四线模式而不是八线模式主要目的是节省GPIO资源。STM32F103C8虽然有足够多的引脚但省下来的IO可以留给后面的功能扩展而且四线接法布线也更简单实际效果完全不受影响。3.3 STM32电源设置与最小系统在Proteus里仿真STM32最容易被忽略的就是电源设置。很多人在原理图中放置了STM32F103C8芯片但芯片却无法正常工作排错半天发现是芯片根本没有供电。STM32F103C8的VDD和VSS引脚在Proteus模型中是默认隐藏的需要手动确保电源网络正确连接。具体操作建议在原理图编辑区放置POWER符号电压值设为3.3V放置GROUND符号接GND然后通过导线分别连接到芯片逻辑电路的电源网络。如果仿真跑不起来检查一下“System - Set Power Rails”里面的网络映射确认VDD网络对应3.3V、VSS网络对应GND。另外如果代码里配置了外部晶振做系统时钟仿真电路里也要放一个8MHz晶振接到OSC_IN和OSC_OUT引脚两侧各加一个20pF左右的电容到地。如果不想在仿真里折腾晶振也可以把代码改成使用内部HSI时钟这样最小系统连晶振都可以省略。4. 软件代码实现与关键逻辑4.1 初始化与数据读取函数软件部分我按功能模块拆开讲。首先是GPIO和启动初始化。HX711的SCK引脚配置为推挽输出DOUT引脚配置为上拉输入。上拉很重要因为HX711的DOUT是开漏输出结构虽然模块板上通常已经有上拉电阻但在代码层面配置输入的上下拉模式是一个保险操作可以避免浮空带来的误触发。主函数里还要做原子的延时初始化。本项目的延时函数主要用于HX711时序中的高电平保持时间以及主循环的采样间隔控制。HX711对时序要求不算苛刻但SCK高电平保持时间至少要有1微秒才算稳妥。所以延时函数的精度直接影响通信可靠性——这里建议不要用那种编译器优化掉的空循环延时最好用系统定时器或者DWT计数器来实现微秒级延时。如果你用的是标准库或者HAL库直接使用delay_us()这种现成函数即可。4.2 称重标定与重量计算原理用HX711读出来的原始值本身并不是重量它只是一个和输入差分电压线性相关的数字量。要想让显示值成为克或者千克必须做标定。标定本质上就是确定两个参数零点和缩放系数。第一步读取零点。在空秤状态下连续读取10到20次数据取平均值作为零点值zero_value。第二步读取标准重量。在秤盘上放置一个已知重量的标准砝码比如1kg同样读取多次数据取平均记为load_value。第三步计算缩放系数scale (load_value - zero_value) / 1000.0f; // 单位g这里的1000表示标准砝码的质量是1000克单位按克计算。之后任意时刻的重量计算公式为weight_g (current_raw - zero_value) / scale;需要特别提醒scale必须用浮点数保存否则整数除法会丢失精度。在实际工程里这个标定过程通常通过一个按键触发配合LCD提示“放上1kg砝码”。在仿真调试时可以先把电位器调到某个固定位置假装它是1kg标准负载标定完成后再去旋转电位器观察重量的线性变化。关键是要理解电位器旋转角度和“重量”之间不一定是线性关系但HX711读数和输入电压之间是严格线性的标定算法本身不关心前端是什么只需要知道“某个输入对应某个已知重量”这一点。4.3 零点追踪与数据滤波在真实电子秤里长时间使用后零点会漂移——温度变化、传感器蠕变、应变片老化都会导致空秤读数不再回到初始零点。如果零点不准后续所有重量计算都不准。最简单的零点追踪思路是每次检测到秤盘上的载荷长期接近零时自动把当前读数更新为新的零点。这里的难点在于如何判定“秤盘空载”。一个实用的做法是连续采集N次数据如果这N次数据的最大值和最小值之差小于某个阈值比如2g对应的原始读数且平均值也小于某个偏移量就认为当前处于空秤状态把平均值赋值给零点。需要注意的是零点追踪不能太激进否则用户正在加载物体但物体很轻时零点会被错误更新导致显示值被“吃掉”。较为稳妥的做法是增加一个持续判定比如连续500ms都满足空载条件才更新零点。在Proteus仿真中可以用电位器模拟小幅漂移来验证零点追踪是否生效。数据滤波方面最常用的是一阶滑动平均值。我这里使用窗口为8的滑动平均滤波既能抑制工频50Hz干扰带来的小幅波动又不至于让响应变得过于迟钝#define FILTER_N 8 int32_t filter_buf[FILTER_N]; uint8_t filter_index 0; int32_t filter_sum 0; int32_t Data_Filter(int32_t raw) { filter_sum - filter_buf[filter_index]; filter_buf[filter_index] raw; filter_sum raw; filter_index (filter_index 1) % FILTER_N; return filter_sum / FILTER_N; }这段代码的核心是滑动窗口求和把新值加入缓冲区、旧值移出用总和除以窗口长度得到平均结果。相比每次循环都重新求和的笨办法这种方式计算量恒定适合单片机这种资源有限的平台。4.4 超重报警与显示逻辑显示部分1602液晶初始化成4位模式后第一行显示实时重量单位g第二行显示当前报警阈值和状态。按键K2、K3用于调整报警阈值K1实现去皮功能。去皮的本质很简单把当前读数设为新的零点这样传感器上已有的容器重量就会被扣除显示的是容器内物品的净重。实现方式就是触发一个标志位在标定代码中把zero_value更新为当前滤波后的读数即可。超重报警逻辑放在主循环的末端执行if (weight_g limit_weight) { GPIO_SetBits(GPIOA, GPIO_Pin_6); // 蜂鸣器响 GPIO_SetBits(GPIOA, GPIO_Pin_7); // LED亮 } else { GPIO_ResetBits(GPIOA, GPIO_Pin_6); GPIO_ResetBits(GPIOA, GPIO_Pin_7); }实际产品中蜂鸣器不能一直长响最好用定时器产生2kHz左右的方波驱动并且在报警持续一定时间后自动关闭防止刺耳噪音。仿真阶段驱动蜂鸣器让引脚持续输出高电平即可。如果你手头工程里的蜂鸣器模型是有源蜂鸣器高电平触发是可行的如果是无源蜂鸣器需要切换GPIO输出方波。这一点在移植到实物板时一定要确认模块类型。5. Proteus仿真搭建与调试5.1 从零搭建STM32仿真工程的步骤如果你选择的是打开现成仿真文件跳到5.2继续看。如果你想自己从零复刻整个仿真电路可以照下面的步骤操作第一步新建Proteus工程在元件库中放置STM32F103C8、LM016L、HX711如果元件库里有没有的话可以用电位器电阻网络模拟输入、按键、蜂鸣器、LED和必要电阻电容。第二步按照3.2节的接线表连接电路。第三步双击STM32芯片在“Program File”中加载Keil编译生成的hex文件晶振频率填8000000对应外部8M晶振。第四步点击运行按钮。如果程序正常运行1602会显示初始重量。这里必须提醒一个Proteus的操作细节STM32F103C8默认情况下程序运行需要配置启动文件选择也就是BOOT0和BOOT1引脚电平。在仿真中BOOT0要接低电平BOOT1接低电平让芯片从主Flash启动。很多人的仿真一直卡在“芯片没有响应”的状态就是忘记了这两个引脚的电平设置。在Proteus里你可以直接不连接这两个引脚但为了标准建议显式接GND。5.2 仿真运行时的典型故障排查我在调试类似项目时整理了一份高频问题排查表这里直接分享出来现象可能原因排查方法1602无显示或只有背光对比度电位器未调好D4-D7接错初始化时序问题调节LCD V0引脚电压到1V左右对照代码核对引脚映射重量读数固定不变电位器未接入HX711输入回路程序没读取到数据用虚拟示波器看SCK和DOUT波形确认DOUT引脚上拉读数跳得很厉害供电纹波大采样次数太少未做滤波给HX711 VCC加104电容程序开启滑动滤波超重不报警阈值设置过大GPIO配置错误先把阈值调小单步调试检查weight_g与limit_weight比较结果芯片运行但外设无响应系统时钟配置与仿真晶振不一致核对代码里的时钟配置和Proteus晶振频率一致编译报错找不到头文件Keil工程缺少固件库路径检查C/C选项卡中的Include Path是否包含所有库目录排查这类问题的核心思路是“从源头往前推信号链路”。先确认HX711是否在产生数据示波器看DOUT波形再确认数据是否被正确读入用调试器在线看变量最后再看显示和报警逻辑。永远不要跳过前面几点直接去调显示。5.3 从仿真到实物移植的注意事项仿真跑通之后如果打算做成实物有几个仿真里发现不了的坑需要提前知道。第一个是基准电压和供电质量。仿真里的电源都是理想电压源实物的HX711模块对电源纹波特别敏感建议VCC和GND之间并接一个100uF电解电容和0.1uF陶瓷电容给传感器激励端也加滤波电容。第二个是传感器接线颜色。市面上常见的称重传感器有红黑绿白四根线红色接E黑色接E-绿色接S白色接S-但不同厂家颜色定义偶尔会有差异最好用万用表先判断桥臂电阻再接线。第三个是共地问题。STM32和HX711模块必须共地否则通信电平无法保持稳定这是很多实物调试中“读数随机漂移”的根本原因。还有一点值得注意Proteus仿真中HX711的通信时序是理想化的实物中信号线较长时容易引入串扰这时候SCK引脚上的信号质量可能变差。解决办法是缩短杜邦线长度或者在SCK和DOUT线上各自串联一个100欧姆左右的电阻用来抑制振铃。6. 实测体验与个人经验这套项目我完整跑过一遍从Proteus仿真到实物移植都做了。整体印象是HX711STM32这个组合对于学习“传感器信号链”非常有帮助——从微弱信号生成、放大、ADC采集到数字滤波、标定换算再到控制输出一整条链路非常完整。但有几个细节直到我实际调试时才真正体会到。零点追踪这个功能网上资料提的很多但真正把逻辑做好的不多。最简单的实现方式是在主循环里周期性检测空载状态并更新零点但要注意这个逻辑和按键去皮功能的关系如果用户手动去皮后又触发了零点追踪很可能覆盖掉用户刚刚设定的去皮零点。我的处理方式是在去皮之后的一个固定时间窗口内比如10秒暂停零点追踪让用户完成容器放置。这个窗口大小在仿真里无所谓但在实物中直接影响用户体验。另一个经验是关于标定参数保存。仿真环境里全局变量掉电就丢可以接受。但实物产品中标定好的scale和zero_value如果不保存每次上电都要重新标定非常痛苦。建议在工程中引入EEPROM模拟或者用STM32内部Flash的最后一个扇区存储这两个参数上电时直接读取并校验。这个功能在仿真中也能验证只是需要用代码模拟掉电场景。最后分享一个小技巧在Proteus仿真里调试HX711时可以把PA9USART1_TX连接到虚拟终端把每次读取的原始值和换算后的重量值直接打印出来。这样比用LCD查看快得多可以直观看到滤波前后数据的区别也能帮助你快速判断标定参数是否合理。把这套调试方法养成习惯以后做其他传感器项目也会省下大量时间。本文还有配套的精品资源点击获取