news 2026/10/20 12:51:04

HX711 AD芯片实战指南:从零搭建高精度电子秤(含STM32源码与OLED驱动)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
HX711 AD芯片实战指南:从零搭建高精度电子秤(含STM32源码与OLED驱动)

1. 从零认识你的电子秤“大脑”:HX711 AD芯片

大家好,我是老张,一个在嵌入式圈子里摸爬滚打了十多年的老工程师。今天想和大家聊聊一个特别有意思的小东西——HX711。别看它只是个小小的24位AD芯片,价格也便宜,但在做高精度电子秤、厨房秤这些小玩意儿时,它可是绝对的核心“大脑”。很多新手朋友一听到“24位AD”、“差分放大”这些词就头大,觉得门槛太高。别怕,今天我就用最“人话”的方式,带你从零开始,把它玩转。

简单来说,HX711就是一块专门为称重传感器这类“小信号”设计的芯片。什么叫小信号?我们的称重传感器,在你放上一杯水或者一个苹果时,它输出的电压变化可能只有几十个微伏(uV),比蚊子哼哼的声音还微弱。普通的单片机,比如STM32自带的12位ADC,能分辨的最小电压变化大概在0.8毫伏(mV)左右,对于微伏级的信号,它根本“听不见”。这时候,HX711的作用就来了:它内部自带了一个可编程的放大器,能把传感器那微弱的“哼哼”信号,放大32倍、64倍甚至128倍,变成一个强壮清晰的“喊话”。然后,再用它高精度的24位ADC,把这个放大后的信号转换成数字量,送给我们的主控芯片(比如STM32)去处理。

我刚开始接触它的时候,也觉得数据手册上那些时序图、增益选择有点复杂。但实际用起来你会发现,它的设计非常贴心,把很多复杂的模拟电路都集成到了芯片内部。你只需要接很少的外围元件,甚至只用两颗电阻,就能给它和传感器提供一个稳定的工作电压。这大大降低了我们硬件设计的难度和出错的概率。对于想入门嵌入式、做个实物项目练手的朋友来说,用HX711搭配STM32做一个电子秤,绝对是性价比超高、成就感满满的选择。你不仅能学到模拟信号采集、数字滤波、传感器标定这些硬核知识,还能得到一个实实在在、能显示读数的小工具,放在家里称个咖啡豆、小零件,别提多实用了。

2. 硬件连接:手把手搭建你的电子秤“骨架”

理论说再多,不如动手接上线。这一部分,咱们就来实实在在的把硬件搭起来。你需要准备的东西不多:一块STM32最小系统板(我用的是常见的STM32F103C8T6,也就是“蓝板”)、一个HX711模块(某宝上几块钱一个,自带稳压和滤波,强烈建议新手直接买模块,省心)、一个称重传感器(常见的是5kg量程的铝合金传感器,带HX711接口)、一个0.96寸的OLED显示屏(I2C接口),再加上几根杜邦线就够了。

首先是电源,这是保证精度的关键。很多朋友在这里踩过坑。HX711模块和称重传感器最好用5V供电。为什么?因为传感器的输出信号幅度和供电电压是成正比的。5V供电能让传感器输出更大的信号范围,被HX711放大后,信噪比更好,最终读数更稳定。而我们的STM32和OLED屏,通常用3.3V。所以,如果你的开发板有独立的5V输出引脚(比如USB输入经过稳压后的5V),就用它给HX711模块供电。如果没有,用一个外部的5V电源适配器也行,但要确保和STM32共地。STM32和OLED屏则用3.3V。切记不要用STM32的3.3V去给HX711和传感器供电,否则灵敏度会大打折扣,而且可能驱动能力不足。

接着是信号线连接,非常简单:

  • HX711模块 → STM32:模块上通常有四个引脚:VCC、GND、DT(DOUT)、SCK。VCC接5V,GND接STM32的GND。DT(数据线)接STM32的任何一个GPIO口,我习惯接PB15。SCK(时钟线)接另一个GPIO口,我接PB14。这两个口在软件里配置成推挽输出和上拉输入就行。
  • 称重传感器 → HX711模块:传感器一般有4根线:红(电源+)、黑(电源-)、白(信号+)、绿(信号-)。对应接到HX711模块的E+、E-、A+、A-上。颜色可能因厂家而异,但接线逻辑不变。
  • OLED屏 → STM32:I2C接口的OLED就四根线:VCC(3.3V)、GND、SCL、SDA。SCL和SDA我分别接到STM32的PB11和PB10上,这两个引脚需要配置为开漏输出模式并启用内部上拉。

硬件连好后,先别急着写代码。用万用表量一下各电源引脚电压是否正常,尤其是HX711模块的输出给传感器的电压(通常是4.3V左右)。确保没有虚焊、短路。硬件是软件的基石,这一步稳了,后面调试会顺利很多。

3. 深入核心:搞懂HX711的数据通信协议

线接好了,下一步就是让STM32和HX711“对话”。这个过程其实就是读写一串串的脉冲信号,理解了它的时序,你就掌握了HX711的命门。我当初就是在这里卡了好久,翻来覆去看数据手册,最后才摸清门道。

HX711采用了一种叫做“同步半双工”的通信方式。听起来高级,其实很简单。它有两根线和单片机交互:DOUT(数据输出)和PD_SCK(时钟输入)。DOUT是HX711发给单片机的,PD_SCK是单片机发给HX711的。通信的主动权完全在单片机手里:单片机通过控制PD_SCK引脚产生时钟脉冲,同时在每个脉冲的上升沿去读取DOUT引脚的状态,拼凑出24位的数据。

这里有几个必须注意的细节,也是新手最容易出错的地方:

  1. 等待就绪:在开始发时钟脉冲之前,必须先检查DOUT引脚是否为低电平。只有当DOUT为低时,才表示HX711已经准备好了一次新的转换数据。如果DOUT是高,你就必须等待,并且在等待期间,PD_SCK必须保持为低电平。我见过有朋友的程序一上来就狂发时钟,结果读回来的全是乱码,问题就出在这里。
  2. 脉冲个数:读取一次数据,需要发送25到27个时钟脉冲。具体发多少个,取决于你选择的通道和增益:
    • 通道A,增益128:发25个脉冲。前24个脉冲读取24位数据,第25个脉冲用于设置下次转换的参数。
    • 通道A,增益64:发27个脉冲。
    • 通道B,增益32:发26个脉冲。 脉冲数不能多也不能少,否则通信会错乱。我们做电子秤一般用通道A增益128,所以发25个脉冲就行。
  3. 数据格式:读回来的24位数据是二进制补码形式。这意味着数据的最高位是符号位。对于称重传感器,我们通常只关心正向压力,所以实际处理时,我会用一个count = count ^ 0x800000的操作,将这个有符号的补码转换成一个0~16777215之间的无符号正数,这样后续计算重量就方便多了。

为了让你更直观地理解,我写了一个最基础的读取函数(基于HAL库),你可以看看里面的每一步:

uint32_t HX711_Read(void) { uint32_t count = 0; uint8_t i; HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET); // SCK拉低 delay_us(1); // 短暂延时 // 1. 等待DOUT变低(就绪) while (HAL_GPIO_ReadPin(DOUT_GPIO_Port, DOUT_Pin) == GPIO_PIN_SET); // 2. 发出24个时钟脉冲,并读取数据 for (i = 0; i < 24; i++) { HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET); // SCK拉高(上升沿) delay_us(1); count = count << 1; // 数据左移,为新位腾出空间 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET); // SCK拉低 delay_us(1); if (HAL_GPIO_ReadPin(DOUT_GPIO_Port, DOUT_Pin) == GPIO_PIN_SET) { count++; // 如果DOUT为高,则该位为1 } } // 3. 发出第25个脉冲,选择下次为通道A增益128模式 HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET); delay_us(1); count = count ^ 0x800000; // 补码转无符号正数(关键步骤!) HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET); delay_us(1); return count; }

这个函数里的delay_us可以用STM32的定时器精确实现,也可以简单用空循环替代(精度要求不高时)。把这段逻辑吃透,你的HX711驱动就成功了一大半。

4. 从原始数据到精准重量:标定与滤波算法实战

当你成功从HX711读出一串数字,比如856723时,你可能会懵:这离“克”这个单位还差得远呢。没错,这一步就是要把这个原始的AD值,转换成我们看得懂的重量。这个过程叫做标定,它是整个电子秤项目成败的关键,也是最能体现工程师经验的地方。

首先,我们需要理解一个概念:皮重(Tare)。即使秤盘上什么都没放,由于传感器本身的制造误差、安装应力、电路偏移等原因,HX711也会读出一个非零的AD值。这个值就是皮重。所以,在称重前,我们必须先“去皮”。方法很简单:在空秤状态下,连续读取多次HX711的值(比如100次),然后取平均值,把这个值存起来,记为Weight_Maopi。以后每次称重时,读到的原始值减去这个皮重,得到的就是物体产生的净AD值。

接下来是标定。你需要一个已知重量的标准砝码,比如100克。把砝码稳稳地放在秤盘上,读取此时的净AD值(减去皮重后的值)。假设你读到的值是41200。那么,一个简单的线性关系就建立了:41200个AD值 对应 100克。由此可以算出比例系数(我常叫它“GapValue”):GapValue = 41200 / 100 = 412。这意味着,在这个系统里,每412个AD值的变化,大约代表1克重量的变化。

于是,你的重量计算函数就可以这样写:

s32 Get_Weight(void) { uint32_t current_ad = HX711_Read(); if(current_ad > Weight_Maopi) { int32_t net_ad = current_ad - Weight_Maopi; // 净AD值 int32_t weight = (int32_t)((float)net_ad / GapValue); // 计算重量 return weight; } return 0; }

但事情还没完。你会发现,直接这样算出来的重量,数值会在真实值附近跳来跳去,很不稳定。这是因为存在各种干扰:电源纹波、空气流动、微小的震动等等。这就需要引入数字滤波。对于电子秤这种慢变信号,一个简单又有效的办法是滑动平均滤波。我常用的方法是:开辟一个数组,缓存最近10次的重量计算结果,每次显示时,都取这10个值的平均值。代码大概长这样:

#define FILTER_LEN 10 int32_t weight_buffer[FILTER_LEN] = {0}; uint8_t buffer_index = 0; int32_t Get_Filtered_Weight(void) { int32_t raw_weight = Get_Weight(); // 获取原始计算重量 weight_buffer[buffer_index] = raw_weight; // 存入缓冲区 buffer_index = (buffer_index + 1) % FILTER_LEN; // 索引循环 int64_t sum = 0; for(int i=0; i<FILTER_LEN; i++) { sum += weight_buffer[i]; } return (int32_t)(sum / FILTER_LEN); // 返回平均值 }

实测下来,经过这样的滤波处理,重量读数会变得非常稳定,几乎看不到跳动。你还可以尝试更高级的滤波算法,比如一阶低通滤波,但滑动平均对于入门项目来说,已经完全够用且效果显著。

5. 让结果一目了然:OLED屏驱动与界面设计

辛苦了半天,数据总算算准了,总不能一直靠串口打印看重量吧?是时候请出我们的“脸面”——OLED显示屏了。0.96寸的OLED屏,分辨率128x64,功耗低、显示清晰,通过I2C总线与STM32连接,只需要两根数据线,非常节省IO口。

驱动OLED屏,你不需要从零开始写底层驱动。网上有大量开源的OLED驱动库,比如SSD1306的驱动。你只需要把对应的.c和.h文件添加到你的工程里,根据你的硬件连接,修改一下I2C的读写函数或者引脚定义,就能轻松调用OLED_ShowString、OLED_ShowNum这样的函数来显示内容了。

对于电子秤的界面,我的设计原则是:简洁、清晰、信息明确。通常我会把屏幕分为三个区域:

  1. 标题区:屏幕顶部显示“电子秤”或“Weight Scale”这样的固定标题。
  2. 主显示区:屏幕中央用最大的字体显示当前重量,单位是“g”。这是视觉焦点。
  3. 状态区:屏幕底部可以显示一些状态信息,比如电池电量图标、单位切换提示(g/kg),或者一个稳定的指示标志。

这里有个实用的小技巧:为了提升用户体验,我通常会在重量显示上做一点动画效果。比如,当重量发生变化时,新数值不是“唰”一下直接跳变,而是有一个快速的数字递增或递减的滚动效果。虽然只是视觉上的小把戏,但能让你的电子秤看起来更“高级”、更“流畅”。实现起来也不难,就是在更新显示前,判断一下新旧数值的差值,然后以一定的步进,分几次显示中间值,最后到达目标值。

另外,记得在程序里合理控制屏幕刷新频率。重量数据我们可能每100ms更新一次,但屏幕不需要刷新得这么快。可以设置一个500ms的定时刷新,或者只在重量值确实发生变化时才刷新屏幕,这样可以降低系统功耗,尤其是在电池供电的场景下。

6. 工程整合与进阶优化:打造一个稳健的系统

前面我们把各个模块都逐个击破了,现在要把它们整合到一个完整的、健壮的系统里。这不仅仅是把代码堆在一起,而是要思考如何让它们协调工作,并且处理各种异常情况。

首先,我建议你使用状态机的思想来组织主程序。电子秤的工作流程可以抽象成几个状态:上电初始化->等待稳定(去皮)->稳定称重->超载报警。用一个状态变量来记录当前状态,在while(1)主循环里根据状态执行不同的操作。这样写出来的代码结构清晰,易于维护和扩展。比如,在“等待稳定”状态,你可以连续采样一段时间,判断数据波动是否小于某个阈值,从而确认空秤状态是否稳定,然后再进行去皮操作。

其次,增加按键功能。除了显示重量,一个实用的电子秤至少需要两个按键:一个“去皮/归零”键,一个“单位切换”键(克/盎司)。按键处理要加入消抖,并且最好用中断或定时扫描的方式,避免阻塞主循环。当按下“去皮”键时,就调用之前写的Get_Maopi函数,更新皮重值。

异常处理是区分业余作品和专业作品的重要一环。你的代码里应该考虑到:

  • 传感器断线检测:如果HX711的DOUT线一直为高电平(等待超时),或者读回来的AD值长时间为0或满量程,可能是传感器或HX711损坏、断线了。此时应该在OLED屏上显示“Err Sensor”之类的提示。
  • 超量程保护:当计算出的重量超过你传感器量程的110%时(比如5kg的传感器,超过5.5kg),应该停止增加显示,并闪烁显示“OVER”警告,防止传感器永久损坏。
  • 电源管理:如果你用的是电池,可以增加一个简单的电量检测电路(电阻分压接到ADC),在屏幕上显示电量图标。当电压过低时,提示“Low Bat”并进入休眠模式。

最后,是关于精度再提升的进阶思考。如果你发现线性度还不够好(比如100g很准,但500g偏差较大),可以考虑进行两点标定。即用两个不同重量的砝码(如100g和500g),建立一次线性方程(y = kx + b),而不是简单的单点比例。这能更好地补偿传感器的非线性误差。代码上就是解一个二元一次方程组,求出k和b。虽然稍微复杂点,但对于追求精度的你来说,绝对是值得的。

把这些都做好,你的电子秤就不再是一个简单的课堂实验,而是一个接近产品级的、可靠实用的小工具了。我把自己在项目中反复调试、踩坑后总结出的核心源码框架都分享了出来,你可以基于它去搭建、去修改、去创造。嵌入式开发的乐趣,就在于这种从无到有、把想法变成实物的过程。希望这篇指南能帮你少走些弯路,顺利点亮你的第一个高精度电子秤。如果在实际操作中遇到什么问题,不妨多看看数据手册,多调试一下时序和参数,那种解决问题的成就感,才是最棒的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 12:49:43

睿尔曼RM-65机械臂避坑指南:C++ SDK在VS和QT中的路径配置陷阱

睿尔曼RM-65机械臂避坑指南&#xff1a;C SDK在VS和QT中的路径配置陷阱 如果你正在为睿尔曼RM-65机械臂进行C二次开发&#xff0c;大概率已经体会过那种“配置半天&#xff0c;编译报错”的挫败感。Visual Studio和QT Creator这两个看似友好的IDE&#xff0c;在引入第三方SDK时…

作者头像 李华
网站建设 2026/10/5 19:51:33

GLM-4.7-Flash多轮对话实战:会议纪要→待办提取→邮件草稿全自动链路

GLM-4.7-Flash多轮对话实战&#xff1a;会议纪要→待办提取→邮件草稿全自动链路 创作者信息 ┌─────────────────────────────────────┐ │ 桦漫AIGC集成开发 │ │ 微信: henryhan1117 │ ├────────────────────…

作者头像 李华
网站建设 2026/10/20 12:50:50

SDXL 1.0电影级绘图工坊在计算机视觉教学中的应用

SDXL 1.0电影级绘图工坊在计算机视觉教学中的应用 1. 引言 计算机视觉课程一直面临着理论与实践脱节的挑战。学生们在课堂上学习各种算法原理&#xff0c;但往往缺乏直观的感受和实际的应用场景。传统的教学方式依赖于有限的图像数据集和预设的实验&#xff0c;难以激发学生的…

作者头像 李华
网站建设 2026/10/11 20:39:40

边沿检测的黑科技:FPGA中如何用Verilog实现精准信号捕捉

边沿检测的黑科技&#xff1a;FPGA中如何用Verilog实现精准信号捕捉 在高速数字系统的世界里&#xff0c;一个看似简单的信号跳变往往承载着关键信息。无论是传感器捕捉到物理量的突变&#xff0c;还是通信协议中标志位的起始&#xff0c;亦或是按键消抖后确认的有效动作&…

作者头像 李华
网站建设 2026/10/11 20:19:49

如何突破Unity资源处理瓶颈?UABEA跨平台资产提取工具全解析

如何突破Unity资源处理瓶颈&#xff1f;UABEA跨平台资产提取工具全解析 【免费下载链接】UABEA UABEA: 这是一个用于新版本Unity的C# Asset Bundle Extractor&#xff08;资源包提取器&#xff09;&#xff0c;用于提取游戏中的资源。 项目地址: https://gitcode.com/gh_mirr…

作者头像 李华
网站建设 2026/10/12 2:03:07

3步突破帧率枷锁,畅享原神丝滑体验

3步突破帧率枷锁&#xff0c;畅享原神丝滑体验 【免费下载链接】genshin-fps-unlock unlocks the 60 fps cap 项目地址: https://gitcode.com/gh_mirrors/ge/genshin-fps-unlock 帧率限制成"掉帧刺客"&#xff1f;这款工具让你的显卡火力全开 当你在璃月港的…

作者头像 李华