
简介基于51单片机的电子秤设计开发资料包面向单片机初学者、嵌入式爱好者以及需要完成课程设计或毕业设计的学生重点解决电子称重系统中传感器数据采集、模数转换、液晶显示与按键交互等环节的程序实现问题。内含完整Keil工程.uvproj及启动代码STARTUP.A51围绕HX711传感器驱动、LCD显示、键盘处理等模块提供C语言源文件与对应头文件并附编译生成的列表文件、目标文件可对照工程快速理解电子秤从称重到显示的全流程。压缩包共27个文件以c/h源文件、a51启动代码、uvproj工程配置、lst/obj编译中间文件为主整体仅64KB便于下载和对照学习。目前已有529人浏览学习。借助工程中main.c主程序结构、lcd.c显示模块、keyboard.c按键逻辑以及hx711.c采集驱动可以快速搭建实验环境或移植到自己的电路板中同时代码模块划分清晰适合在现有框架上扩展单位切换、去皮清零等常用功能是入门51单片机称重系统的实用参考资料。1. 51 单片机做电子秤难点不在称重而在信号链做电子秤课程设计的人很多但能把读数稳住、标定不出错的很少。51 电子秤看起来是“传感器 单片机 数码管”三板斧实际上真正决定成败的是从应变片桥路到 AD 转换这一整条信号链传感器输出只有毫伏级偏置、温漂、电源纹波都会直接变成重量误差。很多人程序写得没问题却卡在原理图上或者卡在“为什么换一个传感器就要重新标定”。这篇文章顺着 51 电子秤的完整落地路径走一遍先把原理图的关键节点讲清楚再给出可直接抄的电子称程序框架最后把标定、滤波和排错的手法补齐。适合正在做 51 单片机课程设计、或者想把 Proteus 仿真换成实物焊接的读者有一定 C 语言基础就能跟下来。2. 电子秤原理图怎么画从传感器桥路到 HX711 再到 STC89C522.1 电阻应变式传感器半桥还是全桥激励电压怎么选常见的 51 电子秤称重传感器是电阻应变式内部是惠斯通电桥。原理上应变片贴在弹性体上受力后电阻变化电桥失去平衡在信号输出端产生一个差分电压。这个电压非常小满量程时通常只有 2mV/V 左右。也就是说如果给传感器供 5V 激励满量程输出也只有 10mV这个信号直接进单片机 ADC 是完全不可用的必须经过仪表放大器放大。选型时注意传感器是半桥还是全桥。半桥传感器内部只有两个应变片需要外部再搭两个精密电阻补全电桥常见于体重秤条状传感器全桥传感器内部四个应变片都齐了直接接激励和信号就行。对于 51 电子秤全桥传感器接线更省事一般输出四根线E激励正、E-激励负、S信号正、S-信号负。激励电压的选择直接影响精度。传感器灵敏度是相对值激励越高输出差分电压越大但自热也越严重。5V 激励下传感器自身功耗一般只有几十毫瓦短时间工作没问题如果要长时间连续称重建议降到 3.3V 并用稳压芯片单独供电避免和数字电路共用电源导致纹波耦合进信号。2.1.1 传感器信号为什么要差分采集应变式传感器的输出是差分信号S 和 S- 对地的共模电压在毫伏到十几毫伏之间波动。如果采用单端采集把 S- 直接接地那么地线上的任何压降、电源纹波都会叠加到信号里而且无法区分是重量变化还是干扰变化。所以原理图上必须把 S、S- 接入差分输入的 AD 芯片或仪表放大器这也是为什么直接用 STC89C52 内部 ADC 做电子秤非常困难的原因——51 内置 ADC 通常是单端输入分辨率也远不够。2.2 HX711 是信号链的中枢为什么不用 24 位 AD 芯片自己搭很多初学者会问能不能用 ADC0832 或者 STC 内置 ADC 来做电子秤答案是能出数但精度和稳定性很差。称重传感器满量程输出 10mV如果用 5V 参考电压的普通 ADC10mV 只占满量程的 0.2%一个 8 位 ADC 的有效分辨率根本不够分。你需要的是一个带可编程增益放大器的差分 ADC。HX711 是专为电子秤设计的 24 位 ADC 芯片内部集成了低噪声仪表放大器增益可选 32、64 和 128。对于常见的 1kg、5kg 量程传感器用增益 128 档位满量程输入只需 ±20mV这恰好覆盖传感器输出范围。HX711 的数据输出是串行的只需要两根线DOUT 和 PD_SCK就能和单片机通信非常适合引脚资源紧张的 51 单片机。原理图设计时把 HX711 放在传感器和单片机之间模拟部分和数字部分尽量分开布线。2.3 最小原理图一份可直接抄的接线表下面这份接线表是针对 STC89C52RC 的最小系统方案传感器、HX711、单片机的连接方式如下HX711 引脚连接目标说明E传感器红线E激励正经 LC 滤波后接 5VE-传感器黑线E-激励负接模拟地S传感器白线S信号正差分输入S-传感器绿线S-信号负差分输入VSUP数字 5V芯片电源AVDD模拟 5V经 10Ω 电阻和 10uF 电容滤波DOUTP1.0串行数据输出PD_SCKP1.1串行时钟输入VFB、BASE悬空不使用RATE悬空或接 GND默认 10Hz 输出速率原理图里有几个关键细节。第一AVDD 和 VSUP 不要直接连在一起中间串一个小电阻再加去耦电容把数字噪声和模拟供电隔离开。第二传感器激励线 E、E- 与 HX711 之间加一个 10uF 电解电容和 0.1uF 瓷片电容并联抑制电源高频噪声。第三PD_SCK 和 DOUT 线尽量短不要和数码管段选线平行走线太长。// HX711 接线示例Keil C51 定义 sbit HX711_DOUT P1^0; sbit HX711_SCK P1^1;注意STC89C52RC 的 P1 口是准双向口读引脚前要先写 1HX711 的 DOUT 线接 P1.0 时需要把 P1.0 置 1 才能正确读取外部电平程序中需要在初始化时加上HX711_DOUT 1;。3. 电子称程序怎么写HX711 时序、称重公式与按键标定流程3.1 HX711 的时序到底怎么读DOUT 和 SCK 的配合HX711 的数据输出时序是典型的同步串行协议。DOUT 为高电平时表示 AD 转换未完成数据不可读。主控需要持续等待 DOUT 变低DOUT 变低后主控发送 25 个 SCK 脉冲前 24 个脉冲依次移出 24 位数据最高位在前第 25 个脉冲用于让芯片进入下一次转换。输出格式是二进制补码符号位扩展。初始上电时HX711 需要大约 400ms 的稳定时间程序里要延时后再读取。另外芯片有 A 通道和 B 通道A 通道增益可选 128 或 64B 通道固定增益 32。发送第 25 个脉冲之前如果 SCK 持续保持高电平超过 60us芯片会进入掉电模式使用时要注意脉冲宽度别拖太长。读取一次 AD 值的核心代码如下unsigned long HX711_Read(void) { unsigned long value 0; unsigned char i; HX711_SCK 0; // 时钟线拉低准备读取 HX711_DOUT 1; // P1.0 置 1确保能读到外部电平 while(HX711_DOUT); // 等待 DOUT 变低表示数据就绪 for(i 0; i 24; i) { HX711_SCK 1; // 上升沿移出一位数据 value value 1; // 先移位再读位 HX711_SCK 0; if(HX711_DOUT) value; } HX711_SCK 1; // 第 25 个脉冲启动下次转换 value value ^ 0x800000; // 补码转原码 HX711_SCK 0; return value; }这段代码有几个容易写错的地方。value value 1;必须在读 DOUT 之前执行否则会把当前位挤掉。补码转原码采用异或0x800000的方式把符号位取反这样空载时读到的值会从 0xFFFFFF 附近回落到 0x000000 附近的区间方便后续做去皮和标定。如果不需要支持负重量比如吊秤的拉力方向固定可以直接把返回值当作无符号数处理但电子秤一般都要支持“秤盘上放东西之后重量增加”的正向变化异或处理是更稳妥的做法。3.2 从 AD 值到克数线性标定公式HX711 读出来的原始值不是克数需要通过标定建立线性映射关系。称重传感器的输出在弹性变形范围内是线性的因此标定公式是重量 (当前读数 - 零点读数) * 标定系数。零点读数是空秤时多次读数的平均值标定系数表示“每个 AD 计数对应多少克”。标定系数的单位是克/计数计算方法是放一个已知重量的砝码读取稳定后的 AD 值用砝码重量除以砝码读数 - 零点读数。例如空秤读数为 3000放 1000g 砝码后读数为 21000那么标定系数就是1000 / (21000 - 3000) 0.05556克/计数。称重时用(当前值 - 零点) * 0.05556就能得到克数。程序里建议把所有运算放在长整型和浮点之间做好取舍long zero_offset 0; // 零点读数 float scale_factor 1.0; // 标定系数单位克/计数 float Get_Weight(void) { long ad_value; float weight; ad_value (long)HX711_Read(); // 读取原始 AD 值 weight (ad_value - zero_offset) * scale_factor; if(weight 0) weight 0; // 负值截断避免显示负数 return weight; }提示标定系数应该按“先测零点、再测满量程、最后计算”的顺序来做。不要在空载时直接修改标定系数也不要在放砝码后再清零否则会污染零点偏移量。3.3 按键标定流程先清零再放砝码实际使用时电子秤不能每次都重新写程序来标定所以要在程序里实现按键标定状态机。常见方案是三个按键去皮键Tare、标定键Cal、加减键用于微调。标定流程是按住标定键进入标定模式此时先记录空秤零点然后提示放上标准砝码程序读取稳定读数后自动计算标定系数。下面是一个简化但完整的标定逻辑框架void Key_Calibrate_Machine(void) { unsigned char step 0; unsigned long empty_val, load_val; float known_weight 1000.0; // 标准砝码重量单位克 if(cal_key_pressed 1) // 检测到标定按键 { step 1; Display_Prompt(EMPTY); // 提示清空秤盘 } while(step 1) { if(confirm_key_pressed) // 按确认键采集零点 { empty_val HX711_Read_Average(10); zero_offset (long)empty_val; step 2; Display_Prompt(LOAD); // 提示放砝码 } } while(step 2) { if(confirm_key_pressed) // 按确认键采集砝码读数 { load_val HX711_Read_Average(10); scale_factor known_weight / (float)(load_val - empty_val); Save_To_EEPROM(zero_offset, scale_factor); // 保存参数 step 0; } } }HX711_Read_Average(10)是连续读取 10 次取平均目的是滤除振动和短时噪声。保存到 EEPROM 是为了断电后不需要重新标定STC89C52 内部有 EEPROM 区可以用 STC 的 ISP 下载工具定义在程序空间之外。直接把标定系数和零点保存在单片机内部 EEPROM比每次上电重新标定要人性化得多。4. 称重不稳、跳数、零点漂移三个高频坑的排查顺序4.1 跳数先查电源和地别急着加滤波51 电子秤最常见的故障是数码管重量值末位不停跳动甚至每秒变化好几克。很多人的第一反应是加长滤波但实际上跳数的根源往往是硬件。供电是一个重灾区如果传感器激励和单片机共用同一个 5V 电源数码管的段选电流会在几十毫安级别波动这个波动直接耦合进传感器桥路AD 值就会跟着抖。建议的排查顺序是先用万用表测 HX711 的 AVDD 和 VSUP看是否在 4.8V 以上再用示波器看 DOUT 信号的上升沿是否干净最后才考虑程序滤波。AVDD 纹波超过 50mV 时读数会表现出周期性跳变跳变频率和数码管刷新频率一致这种情况加滤波只能延缓显示不能根治。从原理图上解决跳数问题常见做法是在 HX711 的 AVDD 引脚前端加10Ω 10uF的低通滤波传感器激励线 E 和 E- 之间并联 100uF 电解电容。模拟地和数字地在单片机处单点汇合不要形成地环路。4.2 滤波算法滑动平均和去极值怎么选如果电源检查后读数仍然有轻微波动那就需要软件滤波。称重场景里最常见的干扰是低频机械振动人走路、桌面抖动和高频电气噪声混合。针对不同噪声特征滤波策略完全不同。滑动平均适合平滑随机噪声但对脉冲干扰敏感中位值平均滤波先排序再去掉最大值和最小值后求平均适合既有随机噪声又有偶尔脉冲的情况。电子秤上我一般用后者采样次数取 5 到 10 次太少了滤不干净太多了响应变慢放上砝码之后要等几秒才稳定用户体验很差。unsigned long HX711_Read_Filtered(unsigned char times) { unsigned long buf[10]; unsigned char i, j; unsigned long sum 0; for(i 0; i times; i) { buf[i] HX711_Read(); delay_ms(10); // 相邻采样间隔 10ms } // 冒泡排序去掉最大值和最小值 for(i 0; i times - 1; i) { for(j 0; j times - 1 - i; j) { if(buf[j] buf[j1]) { buf[10] buf[j]; buf[j] buf[j1]; buf[j1] buf[10]; } } } for(i 1; i times - 1; i) sum buf[i]; return sum / (times - 2); }注意这个函数的采样间隔问题HX711 的默认输出速率是 10Hz每次读数的间隔约 100ms。如果程序里连续调用HX711_Read()而不加延时实际上读到的都是上一次转换的结果数据没有新鲜度滤波效果也会打折扣。所以循环里delay_ms(10)只是保证时序稳定真正的采样节拍还应当由主循环的调度周期控制。4.3 标定后不准检查量程、放大倍数和机械形变标定完成后读数仍然不准常见原因集中在三个地方。第一量程匹配错误。HX711 增益选 128 时差分管脚输入范围是 ±20mV。如果传感器满量程输出超过这个范围正半周会削顶称重到一半读数就不变了。处理办法是换增益 64或者降低传感器激励电压。第二传感器量程过大。用 5kg 的传感器称 50g 的东西输出信号只有几百微伏分辨率天然受限。第三机械结构问题。传感器必须固定在稳定的底座上如果秤盘直接压在传感器上但没有固定砝码摆放位置不同会导致受力点偏移同一个重物显示不同重量。5. 把电子秤做准的一个验证技巧三点标定与线性度回测前面做的是两点标定适合课程设计快速出数。但如果想让电子秤更接近真实商品秤的水平建议做三点标定并回测线性度。三点标定的做法是在空载、半量程、满量程三个点分别记录读数得到一个两段线性折线模型。第一段用零点到半量程计算标定系数第二段用半量程到满量程重新计算标定系数。称重时先判断当前读数落在哪个区间再使用对应的系数。这样可以抵消传感器在接近满量程时轻微的非线性偏差。值得注意的细节是两点标定只保证了零点和满量程两个点准确中间可能偏差 2 到 3 克而三点标定可以让中间段误差明显下降。对于 5kg 量程、精度 1g 的电子秤三点标定几乎是不二之选。回测线性度的操作方法是准备 100g、200g、500g、1000g、2000g 五个砝码依次放上秤盘记录每个点的显示值和实际值的差值并用表格记录。例如标准重量(g)显示重量(g)误差(g)1001011200199-15005011100010000200020011回测结果中如果误差呈现中间正、两端负的规律说明折线模型的分段点选得不够好如果误差无规律则需要回头检查采样滤波和机械固定。建议把回测结果和三个标定点的读数一起记录在最后调整系数时对比旧系数和新系数的误差分布优先保证常用量程段的精度。最后一步是验证去皮功能是否正确放上容器按去皮显示归零后再加砝码称重结果应等于砝码重量如果偏差超过一个砝码精度需要重新检查零点偏移量是否在去皮时被覆盖。本文还有配套的精品资源点击获取