基于51单片机的智能电子秤设计与实现:从传感器到LCD显示

📅 2026/8/7 1:52:43
基于51单片机的智能电子秤设计与实现:从传感器到LCD显示
最近在做一个智能家居相关的项目需要用到称重功能于是自己动手设计了一款基于51单片机的智能电子秤。从选型、电路设计、代码编写到调试整个过程踩了不少坑也积累了一些实战经验。本文将完整分享这款智能电子秤的实现方案涵盖压力传感器原理、HX711模数转换芯片的使用、LCD1602显示驱动以及按键控制逻辑。无论你是电子爱好者、单片机初学者还是需要快速实现称重功能的开发者都能从本文中获得可直接复用的代码和电路图。1. 智能电子秤的核心组成与工作原理智能电子秤的核心目标是将物体的重量这一物理量转换为我们可以直观读取的数字。这个过程主要依赖于以下几个关键部件协同工作。1.1 系统架构框图一个典型的单片机智能电子秤系统其信号流和数据流可以概括为以下路径被测物体 - 压力传感器应变片 - 电桥 - 微弱电压信号 - HX711 ADC芯片 - 数字信号 - 51单片机 - 数据处理 - LCD1602显示/按键控制单片机作为大脑负责协调ADC采样、数据计算、人机交互等所有任务。1.2 核心元器件详解压力传感器本例采用电阻应变式原理传感器内部是一个由应变电阻组成的惠斯通电桥。当传感器受力发生形变时应变电阻的阻值会发生微小变化导致电桥失去平衡从而输出一个与压力成正比的毫伏级差分电压信号。选型关键参数量程如5kg、灵敏度如1.0mV/V、额定激励电压通常为5V或10V。本文示例使用一个常见的5kg量程传感器。HX711 24位高精度ADC芯片为什么需要它传感器输出的信号非常微弱且为模拟量51单片机无法直接处理。HX711专为电子秤设计集成了放大器、稳压器和24位模数转换器能将微弱的差分信号高精度地转换为单片机可读的数字信号。通信方式采用简单的同步串行接口SCK和DOUT极大简化了与单片机的连接和编程。STC89C52RC单片机角色系统控制器。负责通过IO口模拟时序与HX711通信获取重量数据进行数据的滤波、标定换算控制LCD1602显示结果并响应按键操作如去皮、校准。LCD1602液晶显示屏角色人机交互输出界面。用于显示当前重量、单价、总价等信息显示直观。矩阵键盘或独立按键角色人机交互输入设备。用于实现功能切换、输入单价、去皮清零、进入校准模式等。2. 硬件电路设计与连接硬件是系统稳定运行的基石正确的连接方式至关重要。2.1 元件清单元件名称型号/规格数量说明单片机STC89C52RC1也可用AT89C52等兼容型号ADC芯片HX7111电子秤专用模数转换器压力传感器电阻应变式5KG1带HX711模块通常已焊接好液晶屏LCD1602116字符x2行晶振11.0592MHz1产生单片机时钟电容22pF, 10uF2, 1晶振负载电容和复位电容电阻10kΩ1复位电路上拉电阻按键轻触开关4-6个用于去皮、校准、设置等电源5V直流电源1可为USB供电或稳压模块输出2.2 核心电路连接图引脚定义由于无法绘制图形以下用表格描述关键连接关系。请务必对照元器件数据手册核对引脚。单片机最小系统电源(VCC 40脚 GND 20脚)、晶振(18、19脚)、复位电路(9脚接10uF电容至VCC同时通过10K电阻上拉)是必须的。HX711模块与单片机连接HX711模块引脚连接至 STC89C52 引脚说明VCC5V电源正极GNDGND电源地DT (DOUT)P3^6数据输出线可自定义SCKP3^7时钟输入线可自定义E (VCC)5V传感器电源正极模块提供E- (GND)GND传感器电源地A-传感器输出负接传感器信号线-A传感器输出正接传感器信号线LCD1602与单片机连接4位数据模式LCD1602引脚连接至 STC89C52 引脚说明VSS (1)GND电源地VDD (2)5V电源正极VO (3)电位器中端对比度调节接10K电位器RS (4)P2^0寄存器选择RW (5)GND接地始终写操作E (6)P2^1使能信号D4 (11)P2^4数据位4D5 (12)P2^5数据位5D6 (13)P2^6数据位6D7 (14)P2^7数据位7A (15)5V (通过限流电阻)背光正极K (16)GND背光负极按键连接将几个独立按键一端接地另一端分别接至单片机IO口如P1^0, P1^1, P1^2, P1^3并在单片机IO口上加上拉电阻内部或外部至VCC。3. 软件程序设计驱动与逻辑软件是系统的灵魂下面分模块讲解代码实现。3.1 工程文件结构建议在IDE如Keil uVision中按以下结构组织项目Smart_Scale/ ├── main.c // 主函数程序入口 ├── hx711.c / hx711.h // HX711驱动 ├── lcd1602.c / lcd1602.h // LCD1602驱动 ├── key.c / key.h // 按键扫描驱动 ├── scale.c / scale.h // 称重核心逻辑滤波、标定 └── delay.c / delay.h // 延时函数3.2 HX711驱动程序这是读取重量原始数据的关键。HX711通信时序需要精确模拟。// hx711.h #ifndef __HX711_H__ #define __HX711_H__ #include reg52.h // 引脚定义根据实际连接修改 sbit HX711_DOUT P3^6; sbit HX711_SCK P3^7; // 通道和增益选择 #define GAIN_128 // 通道A增益128用于电子秤 // 函数声明 void HX711_Init(void); long HX711_Read(void); void HX711_Delay(unsigned int t); #endif// hx711.c #include hx711.h #include delay.h // 需要微秒级延时函数 // 初始化HX711 void HX711_Init(void) { HX711_SCK 1; // 初始置高 HX711_DOUT 1; // 数据线默认高电平 Delay_us(10); // 短暂延时 HX711_SCK 0; // 拉低开始准备读取 // 等待HX711准备好 (DOUT变低) while(HX711_DOUT); } // 读取一次AD转换结果 long HX711_Read(void) { unsigned long count 0; unsigned char i; HX711_SCK 0; // 确保时钟线为低 // 等待HX711数据就绪DOUT为低电平 while(HX711_DOUT); // 读取24位数据 for(i0; i24; i) { HX711_SCK 1; // 上升沿数据移位 Delay_us(1); // 短暂脉冲 count count 1; // 左移一位准备接收新数据 HX711_SCK 0; // 下降沿 Delay_us(1); if(HX711_DOUT) { count; } } // 附加一个时钟脉冲选择通道和增益增益128 HX711_SCK 1; Delay_us(1); HX711_SCK 0; // 对于24位有符号数据需要扩展符号位到32位long型 // 如果最高位第24位为1表示负数前面补1 if (count 0x800000) { count | 0xFF000000; } return ((long)count); }3.3 称重核心逻辑滤波与标定原始AD值波动大且需要转换为实际重量克或千克。// scale.h #ifndef __SCALE_H__ #define __SCALE_H__ extern float Weight_Current; // 当前重量g extern float Weight_Calibration; // 校准系数 extern long Offset_Zero; // 零点偏移空载时的AD值 void Scale_Init(void); float Get_Weight(void); void Set_Zero(void); // 去皮/归零 void Calibrate_Weight(float known_weight); // 校准已知重量为known_weightg #endif// scale.c #include scale.h #include hx711.h #include intrins.h // 可能需要_nop_() float Weight_Current 0; float Weight_Calibration 1.0; // 初始系数需校准后得到 long Offset_Zero 0; // 初始零点 // 初始化获取零点偏移 void Scale_Init(void) { long sum 0; unsigned char i; // 读取10次取平均值作为零点 for(i0; i10; i) { sum HX711_Read(); Delay_ms(10); } Offset_Zero sum / 10; } // 获取经过滤波和标定的重量 float Get_Weight(void) { long ad_value 0; float weight 0; unsigned char i; // 滑动平均滤波提高稳定性 for(i0; i5; i) { ad_value HX711_Read(); Delay_ms(5); } ad_value ad_value / 5; // 计算重量 (当前AD值 - 零点偏移) / 校准系数 // 注意实际AD值可能为负传感器反接或受压方向相反取绝对值处理 weight (float)(ad_value - Offset_Zero); if(weight 0) weight -weight; // 确保重量非负 weight weight / Weight_Calibration; // 软件滤波忽略微小抖动例如小于0.5g的变化忽略 if( (weight - Weight_Current 0.5) || (Weight_Current - weight 0.5) ) { Weight_Current weight; } return Weight_Current; } // 去皮/归零将当前状态设为新的零点 void Set_Zero(void) { long sum 0; unsigned char i; for(i0; i10; i) { sum HX711_Read(); Delay_ms(10); } Offset_Zero sum / 10; Weight_Current 0; // 显示清零 } // 重量校准放置已知重量的砝码计算校准系数 // 调用前请确保秤上已稳定放置 known_weight 克的砝码 void Calibrate_Weight(float known_weight) { long ad_value 0; unsigned char i; if(known_weight 0) return; // 重量必须为正 for(i0; i20; i) { // 多次采样求稳定值 ad_value HX711_Read(); Delay_ms(10); } ad_value ad_value / 20; // 校准系数 (稳定AD值 - 当前零点偏移) / 已知重量 Weight_Calibration (float)(ad_value - Offset_Zero) / known_weight; // 校准后可以更新当前重量显示 Weight_Current known_weight; }3.4 主程序逻辑框架主函数负责调度各个模块实现业务逻辑。// main.c #include reg52.h #include lcd1602.h #include key.h #include scale.h #include delay.h // 全局变量定义 bit Flag_Zero 0; // 去皮标志 bit Flag_Cal 0; // 校准模式标志 float Unit_Price 0.0; // 单价元/千克 float Total_Price 0.0; // 总价 void main(void) { float weight 0.0; unsigned char key_value 0; // 初始化各模块 LCD_Init(); Scale_Init(); // 这里会获取初始零点 Key_Init(); // LCD显示欢迎信息 LCD_Write_String(0, 0, Smart Scale V1.0); LCD_Write_String(0, 1, Initializing...); Delay_ms(1000); LCD_Clear(); // 主显示界面 LCD_Write_String(0, 0, Weight: g); LCD_Write_String(0, 1, Price:0.00 Yuan); while(1) { // 1. 按键扫描与处理 key_value Key_Scan(); switch(key_value) { case 1: // 按键1去皮/归零 Set_Zero(); Flag_Zero 1; break; case 2: // 按键2进入/退出校准模式 Flag_Cal ~Flag_Cal; if(Flag_Cal) { LCD_Write_String(0, 1, Cal Mode:Put 500g); } else { LCD_Write_String(0, 1, Price:0.00 Yuan); } break; case 3: // 按键3确认校准在校准模式下放好500g砝码后按此键 if(Flag_Cal) { Calibrate_Weight(500.0); // 假设用500g砝码校准 Flag_Cal 0; LCD_Write_String(0, 1, Cal OK! ); Delay_ms(1000); LCD_Write_String(0, 1, Price:0.00 Yuan); } break; // 可以添加按键4、5用于设置单价等 default: break; } // 2. 获取并显示重量非校准模式下 if(!Flag_Cal) { weight Get_Weight(); // 单位克 // 在LCD指定位置刷新重量显示例如第8列开始 LCD_Write_Char(7, 0, (unsigned int)(weight)/1000 0); // 千克位 LCD_Write_Char(8, 0, .); LCD_Write_Char(9, 0, (unsigned int)(weight)%1000/100 0); // 百克位 LCD_Write_Char(10, 0, (unsigned int)(weight)%100/10 0); // 十克位 LCD_Write_Char(11, 0, (unsigned int)(weight)%10 0); // 克位 // 计算并显示总价假设单价已设重量转换为千克 Total_Price (weight / 1000.0) * Unit_Price; // ... 刷新总价显示代码略 } // 3. 延时控制采样和刷新频率约0.5秒一次 Delay_ms(500); } }4. 系统校准与调试实战硬件焊接和代码烧录完成后必须进行校准读数才准确。4.1 校准步骤硬件准备确保系统空载秤盘上无任何东西稳定上电。获取零点程序启动后自动执行Scale_Init()会记录空载时的AD值作为Offset_Zero。此时LCD显示的重量应接近0克可能有微小漂移。执行去皮按下“去皮”键调用Set_Zero()将当前状态包括秤盘自重设为零点。此时显示应为0.000g。放置标准砝码将一个已知精确重量的砝码如500.0g轻轻放在秤盘中央。进入校准模式按下“校准”键LCD提示放入砝码。确认校准等待读数稳定约3-5秒按下“确认”键。程序会计算Weight_Calibration系数并保存实际项目中需存入EEPROM掉电不丢失。验证取下砝码显示应归零。重新放上砝码显示值应非常接近500.0g。可换用不同重量砝码交叉验证线性度。4.2 调试技巧与常见问题读数跳动大检查电源HX711和传感器对电源噪声非常敏感。确保使用干净的5V电源在VCC和GND之间靠近芯片引脚处并联一个100uF电解电容和一个0.1uF瓷片电容。检查机械结构传感器必须安装稳固秤盘不能晃动受力要垂直。优化软件滤波增加Get_Weight()函数中的滑动平均次数或改用更高级的滤波算法如卡尔曼滤波。显示负重量或超大数值检查传感器接线A和A-是否接反尝试交换连接。检查HX711通道确认代码中的增益设置与硬件匹配。检查零点重新执行Set_Zero()。LCD无显示或乱码检查对比度调节LCD的VO引脚所接的电位器。检查时序确认LCD1602.c中的延时函数是否足够特别是EN使能脉冲宽度。检查接线确认RS、RW、E、D4-D7数据线连接是否正确牢固。按键无反应检查上拉电阻如果单片机IO口内部无上拉需在外部接10k上拉电阻至VCC。消抖处理在Key_Scan()函数中必须包含软件延时消抖通常10-20ms。5. 功能扩展与优化建议基础功能实现后可以考虑以下扩展提升产品的实用性和可靠性。5.1 数据存储EEPROM校准系数(Weight_Calibration)、零点(Offset_Zero)、单价(Unit_Price)等关键数据应存储在EEPROM中如STC89C52内部EEPROM或外接24C02避免每次上电重新校准。// 示例将float类型校准系数存入EEPROM需根据具体EEPROM驱动编写 void Save_Calibration_To_EEPROM(void) { unsigned char *p (unsigned char *)(Weight_Calibration); for(int i0; i4; i) { EEPROM_Write(ADDR_CALIBRATION i, *(pi)); } }5.2 超量程与低电压报警超量程报警当读取的原始AD值接近HX711的满量程时如0x7FFFFF在LCD上显示“OL”或闪烁提示。低电压检测监测电源电压当电压低于一定阈值如4.5V时提示“Lo Bat”因为电压下降会直接影响传感器激励和ADC基准导致测量失准。5.3 计价功能完善实现完整的商品计价功能通过按键输入商品单价元/千克。实时计算并显示总价总价 (重量 / 1000) * 单价。可设计存储多种商品的预设单价方便切换。5.4 通信接口扩展增加串口UART通信将重量数据发送给电脑、蓝牙模块如HC-05或Wi-Fi模块如ESP8266实现数据上传、远程监控或接入智能家居系统。void UART_Send_Weight(float weight) { char buffer[20]; sprintf(buffer, Weight:%.1fg\r\n, weight); // 格式化字符串 printf(buffer); // 重定向printf到串口 }6. 项目总结与核心要点回顾通过这个完整的智能电子秤项目我们不仅实现了一个具体的产品更深入掌握了单片机系统开发的全流程。回顾几个核心要点信号链理解是关键从物理量重量到数字显示每一个环节传感器-电桥-ADC-MCU-显示的原理和特性都必须清楚这是调试的基础。精度取决于最弱一环整个系统的精度受限于传感器精度、HX711噪声、电源稳定性、机械结构乃至软件滤波算法。追求高精度需要全方位优化。校准是必要步骤任何模拟测量系统都存在误差和偏移软件校准是消除系统误差、提高实用性的唯一途径。稳定性重于一切对于测量仪器读数的稳定性往往比单点绝对精度更重要。充分的硬件滤波电容和软件滤波算法是保证稳定性的关键。模块化编程将HX711、LCD1602、按键、称重逻辑分别写成独立的.c/.h文件使得代码结构清晰易于维护和移植到其他项目。这个项目麻雀虽小五脏俱全涵盖了模拟电路、数字电路、单片机编程、传感器应用和人机交互等多个知识点。你可以在此基础上尝试更换更高精度的24位ADC、使用点阵屏或OLED显示、增加电池管理实现便携、甚至通过机器学习算法对数据进行更复杂的处理。希望这份详细的教程和代码能为你自己的电子秤项目或相关的测力应用提供一个坚实的起点。