简介基于51单片机的电子秤设计方案是面向单片机开发初学者的课程设计/毕业设计项目核心使用C/C语言编写。项目以51单片机为主控结合HX711称重传感器完成重量采集、滤波处理与LCD1602显示涵盖硬件接口、ADC转换、数据显示和故障保护等完整开发环节适合电子、计算机类学生实战练手。压缩包共29个文件约3.89MB不仅包含C源程序与Keil工程还提供Proteus仿真工程、原理图PDF、HX711官方资料、参考论文和仿真效果图便于对照学习与离线调试验证。目前已有267人下载学习。通过这个项目读者能掌握51单片机I/O控制、中断、定时器及HX711驱动方法并了解电子秤的电源管理、超载保护与滤波算法设计。5kg传感器接法、开发必读教程和安装截图也收录在内可帮助快速复现整套系统并延伸二次开发。1. 51单片机电子秤真正的难点不在单片机在称重传感器和那颗 HX711一台能稳定显示到 0.1g 的电子秤主控用一片 8 位 51 单片机就够了多数人做样品之前都不太信。真正决定精度的不是 MCU而是称重传感器以及一颗型号为 HX711 的专用称重 ADC。整个 51 单片机电子秤的链路很短悬臂梁式传感器把重量变成毫伏级差分电压HX711 用 24 位精度把它数字化单片机负责读取、换算并送到液晶屏。相比直接用片内 ADC这套方案成本低、抗干扰好也是课程设计里最常见的参考架构。下面按硬件接线、C51 驱动、标定滤波、参数保存的顺序展开。新手能照步骤搭起来老工程师也能在标定细节和存储设计上找到可改的点。2. 硬件选型与接线称重传感器、HX711 和 51 单片机怎么连2.1 悬臂梁式称重传感器量程、灵敏度与四线制端子电子秤的核心传感元件一般是电阻应变式悬臂梁传感器。它把重量转成弹性体上的微小形变再由贴在梁上的应变片组成惠斯通电桥输出一对差分电压。常见量程有 1kg、5kg、10kg、20kg。课程设计做人体秤选 5kg 或 1kg 的居多1kg 量程满量程输出小但同档位分辨率更好要兼顾“能称大件”就选 10kg 以上代价是 1g 以下的分辨率会被噪声吃掉。灵敏度一般标为 1.0mV/V 或 2.0mV/V意思是每 1V 激励电压、满量程时输出 1~2mV。常见 HX711 模块给电桥的激励由片内 LDO 提供约 4.3V于是满量程差分信号在 4~9mV 量级正好落在片内 128 倍增益的合理输入范围里。便宜的模块型传感器只引出四根线激励正、激励负、信号正、信号负对应电桥两个激励端和两个差分端。常见颜色对应关系如下表但不同厂家对白绿的定义并不统一。导线颜色常见定义接 HX711 模块红激励正 EE黑激励负 E-E-白信号正 SA绿信号负 S-A-如果白绿定义反了上电后空载读数会是一个很大的负值或者读数一直往下掉。此时不用重新焊接把 A 和 A- 两根线在端子上对调即可对调不影响标定结果只改变读数符号。2.2 HX711 为什么是 51 单片机最顺手的称重 ADC51 单片机没有带可编程增益放大的高精度 ADC片内 10 位 ADC 对称重来说分辨率差了两个数量级。HX711 是专为电子秤设计的 Σ-Δ 型 ADC外部接口只有两根 IOPD_SCK 和 DOUT。它把电桥激励、增益放大和 AD 转换全包了51 单片机只需要按位把结果读出来。HX711 有两个模拟通道A 通道可选 128 倍或 64 倍增益B 通道固定 32 倍增益。悬臂梁传感器输出很小默认用 A 通道 128 倍即可。数据输出速率由 RATE 引脚决定常用模块默认接地对应 10SPS也就是每秒完成 10 次转换。这个速率对稳定称量够用后面滤波章节会再讨论响应速度的取舍。输出数据是 24 位二进制补码高位在前。上电后第一次读到的数据不建议直接用传感器和模块需要几百毫秒稳定常见做法是连续读三五次后丢弃再把之后的读数用于平均值计算。2.3 模块引脚对接、共地与 Proteus 仿真的边界HX711 模块通常已经做好电桥激励传感器四根线直接拧到模块端子模块再通过四根线连 51 单片机。下面是一组常见接线以及对应的引脚定义代码HX711 模块引脚51 单片机引脚说明VCC5V模块与单片机同源供电GNDGND必须共地DOUTP1.1数据输出低电平表示转换就绪SCKP1.0时钟输入由单片机拉高拉低sbit HX711_SCK P1^0; // 时钟单片机输出模块输入 sbit HX711_DOUT P1^1; // 数据低电平表示转换完成引脚定义要放在所有函数之前端口可以换但换过之后读取函数里的 sbit 也要同步修改。接好后先不写驱动用万用表量模块 VCC-GND 是否为 5V再量传感器红黑两脚之间是否有约 4.3V 的激励电压。这两个电压对了电路基本就通了。提示如果给模块单独供电两个电源的 GND 必须连在一起否则 DOUT 电平在单片机看来是悬浮的读数会出现偶发的 0 和满量程跳变。供电顺序上传感器和单片机最好从同一路 5V 取电但不要让继电器、电机这类大电流负载和电桥共用供电回路。常见现象是 USB 供电时读数每隔几十毫秒跳一下多数不是代码问题而是电源纹波叠加进了模拟段。如果要在 Proteus 里仿真 51 单片机电子秤注意元件库不一定自带 HX711 模型。常见做法是用电位器或可调电源模拟电桥的差分输出先把主程序的读取、换算、显示逻辑跑通硬件标定仍以实物为准。3. 用 Keil C51 写 HX711 驱动24 位读数、重量换算与 LCD1602 显示3.1 HX711 读取时序与补码符号处理HX711 的时序是典型的同步串行DOUT 为高表示转换还没完成DOUT 拉低后数据就绪此后 PD_SCK 的每个上升沿把一位数据从 DOUT 移出先输出最高位。读完 24 位后第 25 个脉冲用于选择下一次转换的通道和增益25 个脉冲对应 A 通道 128 倍增益26 个对应 B 通道 32 倍27 个对应 A 通道 64 倍。只做悬臂梁称重时固定用 25 个脉冲。sbit HX711_SCK P1^0; sbit HX711_DOUT P1^1; long HX711_Read(void) { unsigned char i; long val 0; HX711_SCK 0; while (HX711_DOUT); // 等待 DOUT 变低表示数据就绪 for (i 0; i 24; i) { HX711_SCK 1; // 上升沿移出一位 val 1; HX711_SCK 0; if (HX711_DOUT) { val; } } if (val 0x800000) { // 24 位补码最高位为 1 表示负数 val | 0xFF000000; // 符号扩展到 32 位 } HX711_SCK 1; // 第 25 个脉冲下次仍用 A 通道 128 倍 HX711_SCK 0; return val; }逻辑说明while (HX711_DOUT)会阻塞到转换完成因此即使主循环里连续调用实际采样频率也会被 HX711 的 10SPS 输出速率限制住不需要额外做节流。移位循环里先左移再判断 DOUT正好把高位先装入结果。符号扩展这步不能省否则空载时零漂造成的负读数会被当成几百万的正数后面的减法直接算出一个离谱的重量。如果程序卡在这个函数的 while 循环里出不来优先检查 DOUT 是否确实接到了单片机引脚以及模块是否上电DOUT 悬空时电平不确定最容易造成死等。这个函数就是整套驱动的地基后面的平均值、标定、去皮都建立在它之上返回值是 ADC 原始码不是重量。3.2 重量换算公式零点偏移与比例系数如何标定原始码和重量之间不是绝对零点关系。标准做法是先记录空载读数再记录一个已知重量对应的读数两者相减得到“每克对应多少码”的比例系数weight_g (raw - zero_offset) / scalezero_offset 是空载时的原始码均值scale 是单位重量对应的码数。为了让这两个参数可靠读数不能只采一次课程设计里最常见的实现是多次采样求平均#define SAMPLE_CNT 16 long HX711_Read_Average(void) { long sum 0; unsigned char i; for (i 0; i SAMPLE_CNT; i) { sum HX711_Read(); } return sum / SAMPLE_CNT; }标定分两步。第一步秤盘空载调用HX711_Read_Average()得到zero_offset。第二步放一个标准砝码比如 500g再调用一次得到raw_500于是scale (float)(raw_500 - zero_offset) / 500.0f。之后每次显示重量就用上面的公式换回来。参数建议取值说明SAMPLE_CNT8~32越大读数越稳但响应变慢标定砝码重量量程的 50%~80%尽量覆盖日常使用区间scale 类型float通常不是整数比如 289.5 码/克具体取决于传感器灵敏度和激励电压两点标定隐含“输出完全线性”的假设。悬臂梁传感器本身线性误差在万分之几大多数课程设计场景两点够用如果标定砝码不准或者安装时有预紧力会表现为称重值随负载变大越来越偏这时才需要做多点拟合下一章展开。3.3 按键去皮与 LCD1602 显示流程去皮的本质是修改当前零点把秤盘上已有的容器重量当作新的零点。实现上不需要改动 scale只需要记录一个新的tare_raw显示时用(raw - tare_raw) / scale计算long tare_raw 0; if (KEY_TARE 0) { // 独立按键按下为低 delay_ms(20); // 消抖 if (KEY_TARE 0) { while (KEY_TARE 0); // 等待松手避免长按连触发 tare_raw HX711_Read_Average(); // 把当前负载当零点 } }按键处理两个细节消抖用 20ms 的延时或定时器扫描都行去皮采集同样要多次平均只采一次会把瞬时噪声写进零点造成显示值带一个固定偏移。按键数量多时把独立按键换成矩阵键盘即可去皮逻辑不变。显示用 LCD1602 时有个常见坑Keil C51 的 printf/sprintf 对 %f 的支持在不同库版本下并不一致很多板子上直接输出空白。稳妥做法是先把浮点重量转成整数再拼字符串char buf[17]; long wg; if (weight 0) weight 0; // 微小负漂移直接归零 wg (long)(weight * 10); // 乘 10保留一位小数 sprintf(buf, W:%5ld.%1ld g, wg / 10, wg % 10); LCD_WriteCmd(0x80); // DDRAM 第一行首地址 for (i 0; i 16; i) { LCD_WriteData(buf[i] ? buf[i] : ); // 不足 16 位补空格 }LCD1602 的 8 位模式初始化只需要四条命令0x388 位两行、0x0C开显示关光标、0x06写后光标右移、0x01清屏。刷新频率控制在 10Hz 以内因为 HX711 默认就是 10SPS刷新比采样快只是把同一个值刷多遍还白占 CPU。4. 标定与滤波电子秤从“能读数”到“称得准”的三个关键调整4.1 两点标定够不够线性度与多点最小二乘拟合两点标定的前提是“零点到满量程成直线”。悬臂梁传感器本身线性度很好但在小量程段机械安装的预紧力、秤盘自重、加载时的轻微偏心都会让实际曲线略微弯曲。在 5kg 以下量程这个弯曲通常小于满量程的 0.5%所以两点标定能满足绝大多数课程设计和家用场景。当要求误差在 0.5% 以内或者日常称重范围跨过传感器量程的大部分区间时建议做多点标定取量程的 25%、50%、75%、100% 四个点记录砝码重量和对应原始码用最小二乘拟合出一条直线#define N 4 float px[N] {100, 300, 500, 800}; // 四个标准砝码单位 g float py[N] {29411, 86453, 143990, 229150}; // 实测原始码示例值 float sx 0, sy 0, sxy 0, sxx 0; float k, b; unsigned char i; for (i 0; i N; i) { sx px[i]; sy py[i]; sxy px[i] * py[i]; sxx px[i] * px[i]; } k (N * sxy - sx * sy) / (N * sxx - sx * sx); // 斜率码/克 b (sy - k * sx) / N; // 截距等效零点拟合之后重量用(raw - b) / k计算。这里的 b 由多个点共同决定比单独采一次空载零点受单次噪声影响小如果 b 和之前手动测的 zero_offset 差很多说明传感器安装有预紧力或砝码放偏了这是机械问题不是数学题能补的。4.2 数字滤波的选择中值去毛刺滑动平均压噪声HX711 内部有 Σ-Δ 调制器的数字滤波但机械振动、电源纹波和人体触碰都会在读数上叠加额外噪声。只靠算术平均不够因为偶发的极端毛刺一次平均就能把结果拉偏好几克。常见做法分两级先做中值滤波剔除异常值再做滑动平均压低随机噪声。long HX711_Median_5(void) // 采集 5 次冒泡排序后取中值 { unsigned char i, j; long a[5], tmp; for (i 0; i 5; i) { a[i] HX711_Read(); } for (i 0; i 4; i) { for (j i 1; j 5; j) { if (a[j] a[i]) { tmp a[i]; a[i] a[j]; a[j] tmp; } } } return a[2]; }中值窗口选 3~5 个即可窗口太大对阶跃响应的延迟会很明显。中值之后再做 8~16 点平均作为最终读数整体延迟大约等于采样周期乘以总次数10SPS 下“5 点中值 16 点平均”约 2 秒才能稳定到最终值。称量大宗物料时可以把平均点数减到 8用一点稳定性换响应速度。提示滤波参数要在“读数稳定”和“称重响应”之间取舍。做计价秤可以保守一点做配料或检重场景要缩短窗口否则滞后比噪声更让人头疼。4.3 温漂、零点漂移与供电噪声的三类排查电子秤上电后最常见的问题是空载读数自己慢慢变。这不是程序 bug而是应变片电桥的温漂和弹性体蠕变。处理办法是上电后等秤面稳定 3~5 秒再采样零点并在运行时对零点做缓慢跟踪只在空载且读数变化幅度很小的情况下微调 zero_offset带负载时绝不能触发跟踪否则会越称越偏。现象常见原因处理方式空载读数缓慢变大温漂、弹性体蠕变上电预热后再采零点运行时缓慢跟踪零点读数持续跳变 ±2g 以上供电纹波、信号线过长模块 VCC 并 100μF 和 104 电容信号线双绞放砝码瞬间冲高后回落冲击载荷、机械共振加大中值窗口检查安装刚性称重值随负载变大越来越偏标定点太少或砝码不准做多点最小二乘拟合换标准砝码放置重物后读数回不到原零点超量程损伤、弹性体屈服只能换传感器重新标定最后一条值得单独说超量程是压坏传感器的常见方式20kg 的传感器压到 30kg 不会立即坏但零点回不来这是结构损伤代码治不了。5. 把标定参数写进 STC 内部 EEPROM掉电不用再标定5.1 为什么必须掉电保存以及寄存器怎么用课程设计验收时最尴尬的是断电后参数清零每次上电都要重新找砝码。标定结果本质是两个数一个零点偏移一个比例系数几十个字节就能保存。STC89C52RC 自带 EEPROM不需要外挂芯片用 ISP/IAP 寄存器组直接读写是 51 电子秤掉电保存的标准做法。STC89 系列的寄存器地址在不同型号上有差异编写前先确认手头芯片手册。以下按 STC89C52RC 的常用定义给出字节写函数sfr ISP_DATA 0xE2; sfr ISP_ADDRH 0xE3; sfr ISP_ADDRL 0xE4; sfr ISP_CMD 0xE5; sfr ISP_TRIG 0xE6; sfr ISP_CONTR 0xE7; void IAP_WriteByte(unsigned int addr, unsigned char dat) { ISP_CONTR 0x80; // 使能 IAP低三位等待时间按主频查手册 ISP_CMD 0x02; // 字节编程命令 ISP_ADDRH addr 8; ISP_ADDRL addr 0xFF; ISP_DATA dat; EA 0; // 操作期间关中断 ISP_TRIG 0x46; // 触发序列两次写入顺序不能反 ISP_TRIG 0xB9; EA 1; ISP_CONTR 0x00; // 关闭 IAP }读操作把ISP_CMD改成 0x01写之前用命令 0x03 按扇区擦除。EEPROM 写入地址从 0 开始示例中参数放在 0x0000 附近不同型号容量不同别把参数地址写超出范围。5.2 上电恢复与验证流程写 float 参数时用联合体拆成四个字节再逐字节写入读取时按同样顺序拼回来union { float f; unsigned char b[4]; } u; u.f scale; for (i 0; i 4; i) { IAP_WriteByte(0x0000 i, u.b[i]); }EEPROM 擦写寿命约十万次所以只在标定完成时写一次绝不能在称重循环里写。上电恢复逻辑用第一个字节做有效性标志新芯片 EEPROM 全为 0xFF标定完成后写 0x5A上电读到 0x5A 就恢复 zero_offset 和 scale否则进入标定引导。验证方法很直接首次烧录后手动标定一次把标定值写进 EEPROM断电重启放 500g 标准砝码显示值应与标定时一致偏差不应超过滤波后读数的波动范围。配合 3~5 秒的开机稳定等待这套电子秤就可以脱离电脑独立使用了。本文还有配套的精品资源点击获取