☰
51单片机电子秤系列weight
2026/10/15 3:58:42 网站建设 项目流程

1. 引言

这是一套基于STC89C52(REGX52.H)的智能称重分拣系统,核心硬件包括:

  • HX711:24 位高精度 A/D 转换芯片,负责读取称重传感器(电阻应变式)的原始数据;
  • DS1302:实时时钟芯片,用于记录每次称重的日期与时间;
  • AT24C02:I²C 接口的 EEPROM,用于断电保存累计合格数、次品数、标准重量、误差阈值等关键参数;
  • LCD1602:两行 16 字符液晶屏,用于人机交互显示;
  • 蜂鸣器 + LED:超重/异常报警输出。

本文从代码实现角度,逐段讲解这段代码的工作原理、数据流向与各模块的协作方式,帮助你彻底读懂这套称重分拣系统的每一行代码。文末附有函数职责总览表与状态机流程图,方便你快速把握全局。

2. 系统整体架构与模块划分

2.1 硬件连接概览

外设模块接口类型与单片机连接作用
HX711自定义 GPIO 时序P 口(SCK/DOUT)读取称重传感器原始值
DS1302三线串行RST/SCLK/IO提供实时时钟
AT24C02I²CSCL/SDA掉电保存统计数据
LCD1602并行 8 位P0/P2 等显示模式、重量、时间
蜂鸣器GPIO 输出任意 I/O超重报警
LEDGPIO 输出P2.4超重指示

2.2 软件模块划分

MODE 1

MODE 2

MODE 3

MODE 4

是

否

main() 主循环

mode 判断

Display_M1 时间显示

Display_M2 称重+超重报警

Display_M3 误差检测/批量测量

Display_M4 数据统计/串口发送

Get_Weight() 读取重量

超重?

Buzzer_Time(100) 报警

LED=1 正常


3. 代码逐段精讲

3.1 全局变量与宏定义

sbit LED=P2^4;unsignedintWeight_Maopi=0,Range=1000,qupi,num;longWeight_Shiwu=0;unsignedcharnum_Store,Weight_Store_Num=0,mode,m4;unsignedcharERROR1,Bad_Num1,Keynum,TimeSetSelect=7,TimeSetFlashFlag;unsignedcharWeight_Shiwu_Flag1,num_Flag,Weight_Shiwu_Flag2;unsignedintWeight_Standard1,FanWei_Max,FanWei_Min;intWeight_Standard=200;chartemp,m3,ERROR,Bad_Num,sum,Month,Day,Hour,Minute,m3_Flag;unsignedchari,Weight_Flag,KeynumFlag1,k8,m3_qingling;floatT;#defineGapValue426.04

讲解要点:

  • Weight_Maopi(毛皮重量)与qupi(去皮值)是两个容易混淆的变量:前者是 HX711 原始读数,后者是去皮后的偏移量,二者在Get_Weight()中分别承担「零点偏移」与「去皮」两个不同阶段的补偿。
  • Weight_Shiwu用long是因为 HX711 原始值可达 24 位有符号数,unsigned int(16 位)会溢出。
  • GapValue是标定系数,注释已说明不同传感器需单独校准——它决定了原始 A/D 值到克数的换算比例,是称重系统能否准确的关键参数。### 3.2 去皮函数Get_Maopi()
voidGet_Maopi(){qupi=Weight_Shiwu;}

逻辑分析:该函数把当前净重存入qupi作为去皮基准。它依赖Weight_Shiwu已被Get_Weight()更新过,因此调用顺序很关键——必须先执行Get_Weight()得到当前重量,再调用Get_Maopi()记录去皮值,后续称重时Get_Weight()会减去该值得到净重。

3.3 重量读取与超重判断Get_Weight()

voidGet_Weight(){Weight_Shiwu=HX711_Read();Weight_Shiwu=Weight_Shiwu-Weight_Maopi;Weight_Shiwu=(unsignedint)((float)(Weight_Shiwu)/GapValue)-qupi;Weight_Shiwu-=18600;if(Weight_Shiwu<=0||Weight_Shiwu>5000){Weight_Shiwu=0;}if(Weight_Shiwu>0&&Weight_Shiwu<=5000){if(Weight_Shiwu>Range&&mode==2){Buzzer_Time(100);LED=0;}elseif(mode==2&&Weight_Shiwu<=Range){LED=1;}}}

逐行讲解:

代码行作用潜在问题
HX711_Read()读取 24 位原始 A/D 值需确认返回类型是有符号还是无符号
- Weight_Maopi减去毛重(零点偏移)Weight_Maopi初始为 0,首次需先标定
(float)/GapValue原始值 → 克数换算GapValue需按传感器实测标定
- qupi去皮偏移与Weight_Maopi功能重叠,易混淆
-= 18600经验补偿值硬编码魔法数,建议改为宏定义并注释来源
>5000归零超量程保护量程上限写死,建议用宏MAX_WEIGHT

关键点说明:

  1. 18600是经验补偿值,用于修正传感器零点漂移,属于硬编码常量,理解时需结合具体传感器特性;
  2. 量程上限5000是超量程保护阈值,超过该值重量被强制归零,避免异常读数;
  3. 超重判断仅在mode==2(称重模式)下生效,其他模式不触发报警。### 3.4 时间设置与显示TimeSet()/Timeshow()

TimeSet()是状态机式的按键处理:

  • Keynum==1:切换当前编辑的时间字段(年→月→日→时→分→秒循环);
  • Keynum==5:当前字段加 1,并做边界回绕(如月份 1–12、日期按大小月/闰年判断);
  • Keynum==6:当前字段减 1,同样做边界回绕。

亮点:闰年判断(DS1302_Time[0]%4==0)已实现,逻辑完整。

实现细节:

  • 大小月判断通过查表或分支实现,日期边界按月份天数回绕;
  • 按键处理为单次触发,未做消抖与长按加速。### 3.5 数据存储AT24C02_*系列
voidAT24C02_Writebyte_Data(){AT24C02_Writebyte(0,sum);Delay(5);AT24C02_Writebyte(1,Bad_Num);Delay(5);// ... 共 10 个字节}

存储布局表:

EEPROM 地址存储内容数据类型说明
0x00sumunsigned char累计合格数
0x01Bad_Numunsigned char累计次品数
0x02–0x03Weight_Standardint(低/高字节)标准重量
0x04ERRORunsigned char误差阈值
0x05–0x08月/日/时/分unsigned char最后称重时间
0x09m3_Flagunsigned char模式 3 标志

写入机制说明:

  • 每次写 10 个字节都带Delay(5),可改为「先写后校验读回」;
  • 建议增加**校验和(checksum)**字节,防止掉电写入不完整导致数据损坏;
  • AT24C02_Writebyte_qingling_data()与AT24C02_Writebyte_qingling()功能几乎重复,可合并为一个函数并加参数。

3.6 显示函数族Display_*

函数名显示内容适用模式
Display_M1()MODE 1 + 时间占位模式 1
Display_M2()MODE 2 MAX + 当前重量模式 2
Display_M3()MODE 3 ERROR + 标准重量模式 3 设置
Display_M3_Measure()MODE 3 NUM + 当前重量模式 3 测量
Display_M3_Store()“save data …”模式 3 保存
Display_M4_Standard()Weight + ERROR模式 4 查看标准
Display_M4_Num()SUM + BadNum模式 4 统计
Display_M4_Time()最后称重时间模式 4 时间
Display_M4_Send()“SEND DATA ?”模式 4 确认发送
Display_M4_successful()“send successfully”模式 4 发送成功

设计评价:每个显示函数职责单一、命名清晰,是这段代码中结构最规范的部分,值得保持。


6. 案例补充:一个完整的称重分拣场景

场景:某小型电子厂需要对电阻进行重量分拣,标准重量 200g,误差 ±5g。

操作流程:

  1. 上电→ 系统自动读取 AT24C02 中保存的标准重量 200g、误差 5g;
  2. 模式 2 称重→ 放上电阻,LCD 显示实时重量;
  3. 超重判断→ 若 >205g,蜂鸣器报警、LED 亮,判定为次品;
  4. 模式 3 批量测量→ 连续测量 10 个,自动统计合格/次品数;
  5. 模式 4 查看统计→ 显示 SUM=8、BadNum=2,并通过串口发送到上位机;
  6. 掉电保护→ 数据自动存入 AT24C02,下次上电可恢复。

串口输出示例:

last time: 10-11 20:27 last standard: error: 5 weight: 0200 last data: sum: 008 bad: 002

7. 函数职责总览表

函数名所属模块职责依赖
Get_Maopi()称重记录去皮值Weight_Shiwu
Get_Weight()称重读取并换算重量、超重报警HX711、蜂鸣器、LED
Timeshow()时间读取 DS1302 并刷新 LCDDS1302、LCD
TimeSet()时间按键设置时间(含闰年判断)按键、DS1302
AT24C02_Readbyte_Data()存储从 EEPROM 读回全部参数AT24C02
AT24C02_Writebyte_Data()存储保存全部参数到 EEPROMAT24C02
Display_M1~M4_*()显示各模式界面刷新LCD1602
UART_Send_num()通信串口发送统计结果UART

8. 总结

这段代码功能完整、模块划分清晰,尤其是显示函数族和 AT24C02 存储设计值得肯定。主要改进空间集中在:

  1. 消除魔法数,用宏定义替代硬编码;
  2. 收敛全局变量,用结构体或状态机封装;
  3. 补齐边界处理(按键消抖、变量类型、初始化);
  4. 增加数据校验,提升掉电可靠性。

如果你需要,我可以进一步:把TimeSet()重构为查表法、为Get_Weight()增加数字滤波(滑动平均)、或补充完整的main()主循环框架。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询