2.19 梁山派GD32F470驱动HX711实现高精度称重传感器模块移植指南

📅 发布时间:2026/7/7 7:28:50 👁️ 浏览次数:
2.19 梁山派GD32F470驱动HX711实现高精度称重传感器模块移植指南
梁山派GD32F470驱动HX711实现高精度称重传感器模块移植指南最近在做一个智能厨房秤的项目用到了HX711这款24位高精度ADC芯片搭配梁山派GD32F470开发板。很多朋友问我怎么把HX711模块移植到自己的项目里今天我就把整个移植过程从硬件连接到软件驱动再到校准调试手把手地分享给大家。无论你是做电子秤、力检测还是其他需要精密测量的嵌入式应用这篇教程都能帮你快速搞定。1. HX711模块是个啥先来认识一下在开始动手之前咱们先搞清楚要用的“武器”是什么。HX711可不是一个简单的模块它是专门为高精度电子秤设计的24位模数转换器ADC芯片。简单来说它的工作就是把传感器比如称重传感器本质上是一个应变片电桥输出的微弱电压信号转换成单片机MCU能看懂的数字信号。为什么非得用它呢因为普通的单片机内置ADC精度通常只有12位而HX711能达到24位分辨率高了不是一点半点非常适合要求精确测量的场合。这个模块有几个关键特点我给大家捋一捋高精度24位ADC意味着它能区分出非常微小的电压变化。内置放大器芯片内部集成了128倍的可编程增益放大器。称重传感器输出的信号往往非常微弱毫伏级别这个放大器能把它放大到适合ADC采样的范围省了咱们外接放大电路的麻烦。两路输入它有两路模拟通道A和B可以接不同类型的传感器或进行差分测量我们一般用通道A。接口简单和MCU通信只用两根线SCK和DT属于一种简单的同步串行接口比I2C、SPI还省引脚。模块的工作电压很宽2.6V到5.5V都行梁山派的3.3V供电完全没问题。功耗也很低工作时电流在100到1500微安之间。注意网上常见的HX711模块通常和压力/称重传感器成套卖。原始资料里提供了一个淘宝采购链接和一个百度网盘资料下载链接密码j2sh大家可以按需获取数据手册和更详细的资料。2. 硬件连接把模块接到梁山派上硬件连接是第一步也是最不能出错的一步。HX711模块通常有4个引脚VCC、GND、DT数据线、SCK时钟线。根据原始资料我们使用梁山派GD32F470的以下引脚进行连接HX711模块引脚梁山派对应引脚说明VCC3.3V电源正极接开发板的3.3V输出GNDGND电源地接开发板的GNDDTPB9数据线用于从HX711读取数据SCKPB8时钟线由梁山派产生用于控制HX711的转换和数据读取时序连接的时候用杜邦线对应接好就行。确保传感器比如悬臂梁称重传感器正确连接到HX711模块的“E”、“E-”、“A”、“A-”端子具体接法看传感器和模块的标识。提示接线时最好先断电。SCK和DT虽然是数字信号但线也不要拖得太长避免引入干扰影响24位ADC的稳定性。3. 软件驱动移植代码逐行解析硬件连好了接下来就是让梁山派的代码能“驱动”它。咱们需要把HX711的驱动代码移植到你的工程里。原始资料已经提供了完整的bsp_hx711.c和bsp_hx711.h文件我们不仅要会用还要看懂每一行是干嘛的。3.1 引脚与宏定义 (bsp_hx711.h)头文件里主要做了两件事引脚映射和定义一些方便操作的宏。#ifndef _BSP_HX711_H_ #define _BSP_HX711_H_ #include gd32f4xx.h // 1. 引脚端口和时钟定义 #define RCU_SCK RCU_GPIOB // SCK引脚所在的GPIO端口时钟PB8 #define PORT_SCK GPIOB #define GPIO_SCK GPIO_PIN_8 #define RCU_DT RCU_GPIOB // DT引脚所在的GPIO端口时钟PB9 #define PORT_DT GPIOB #define GPIO_DT GPIO_PIN_9 // 2. 操作宏定义让代码更简洁 // 设置DT为输出模式驱动里暂时没用到输出模式但宏保留着 #define DT_OUT() gpio_mode_set(PORT_DT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_DT) // 设置DT为输入模式读取数据时必须为输入 #define DT_IN() gpio_mode_set(PORT_DT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_DT) // 读取DT引脚的电平 #define DT_GET() gpio_input_bit_get(PORT_DT, GPIO_DT) // 控制DT和SCK引脚输出高或低电平 #define DT(x) gpio_bit_write(PORT_DT, GPIO_DT, (x ? SET : RESET)) #define SCK(x) gpio_bit_write(PORT_SCK, GPIO_SCK, (x ? SET : RESET)) // 3. 函数声明 void HX711_GPIO_Init(void); float Get_Weight(void); void Get_Maopi(void); #endif这里把PB8和PB9固定为SCK和DT如果你需要换其他引脚修改这里的GPIO_PIN_8和GPIO_PIN_9即可但要注意GPIO端口GPIOB可能也要相应改变。3.2 初始化函数 (HX711_GPIO_Init)在bsp_hx711.c中第一个关键函数是初始化GPIO。void HX711_GPIO_Init(void) { /* 使能GPIOB的时钟 */ rcu_periph_clock_enable(RCU_SCK); // 实际上RCU_SCK和RCU_DT都是RCU_GPIOB rcu_periph_clock_enable(RCU_DT); /* 配置SCK(PB8)为推挽输出速度50MHz */ gpio_mode_set(PORT_SCK, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_SCK); gpio_output_options_set(PORT_SCK, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_SCK); /* 配置DT(PB9)为上拉输入模式 */ gpio_mode_set(PORT_DT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_DT); }这个函数很简单就是配置PB8为输出用来发时钟PB9为输入用来读数据。注意DT配置了内部上拉这是因为HX711的数据线在空闲时需要保持高电平。3.3 核心数据读取函数 (HX711_Read)这是驱动最核心的部分它按照HX711的时序通过SCK和DT两根线把24位的ADC数据“读”回来。unsigned int HX711_Read(void) // 增益128 { unsigned long count 0; unsigned char i; DT(1); // 确保DT为高宏定义实际是设置PB9输出高但DT此时是输入模式此操作可能无效或多余可参考数据手册优化 delay_us(1); // 短暂延时 SCK(0); // 初始确保SCK为低电平 count 0; while(DT_GET()); // 等待DT变为低电平。HX711准备好数据后DT会变低。 for(i0; i24; i) // 循环24次读取24位数据 { SCK(1); // 产生一个时钟上升沿 delay_us(1); // 保持高电平一段时间 count count 1; // 将已读取的数据左移一位为新数据腾出位置 SCK(0); // 时钟拉低HX711会在下降沿后更新DT数据 delay_us(1); if(DT_GET()) // 读取DT引脚当前电平 count; // 如果为高电平当前位就是1 } // 第25个脉冲用于设置下一次转换的通道和增益这里选择通道A增益128 SCK(1); count count ^ 0x800000; // 对读取的24位数据进行补码转换。HX711输出的是二进制补码。 delay_us(1); SCK(0); return(count); }我一步步解释这个时序等待就绪while(DT_GET());这行在等待DT线变低。HX711完成一次AD转换后会把DT线拉低告诉MCU“数据准备好了快来读”。逐位读取接着循环24次。每次循环先把SCK拉高再拉低产生一个时钟脉冲。在SCK从高变低下降沿之后HX711会送出下一位数据到DT线上。所以我们在SCK(0);之后去读取DT_GET()的值拼接到count变量里。第25个脉冲24位数据读完后再发一个时钟脉冲第25个。这个脉冲的作用是告诉HX711本次读取结束同时选择下一次转换的通道和增益这里是通道A增益128。这个在数据手册里有明确时序图。数据转换count count ^ 0x800000;这一行是关键。HX711输出的24位数据是二进制补码形式。与0x800000二进制第24位为1进行异或操作相当于将最高位取反从而将补码转换为单片机常用的偏移二进制码或无符号数方便后续计算。注意原始代码中DT(1);这一行值得商榷。因为前面已经将DT配置为输入模式再用输出宏DT(x)去操作可能无效。更常见的做法是在初始化后直接通过SCK控制时序依靠HX711内部和上拉电阻来维持DT电平。如果你在调试时发现一直卡在while(DT_GET());可以尝试注释掉DT(1);这一行。3.4 去皮与称重函数 (Get_Maopi,Get_Weight)光读到ADC值还不够我们需要把它转换成有意义的重量。unsigned int HX711_Buffer; unsigned int Weight_Maopi; // 存储“皮重”的ADC值 int Weight_Shiwu; unsigned char Flag_Error 0; // 校准参数这是整个称重准不准的关键 // GapValue 传感器满量程输出对应的AD值 / 满量程重量 // 需要根据你的实际传感器和砝码进行校准 #define GapValue 208.05 void Get_Maopi(void) { Weight_Maopi HX711_Read(); // 在空秤不放任何东西时调用记录此时的ADC值作为零点 } float Get_Weight(void) { float Weight 0; HX711_Buffer HX711_Read(); // 读取当前ADC值 if(HX711_Buffer Weight_Maopi) { Weight_Shiwu HX711_Buffer - Weight_Maopi; // 减去皮重得到实物的净AD值 Weight (float)Weight_Shiwu / GapValue; // 除以校准系数得到实际重量单位取决于GapValue的校准 } return Weight; // 返回计算出的重量 }这里引入了两个重要概念去皮 (Get_Maopi)在电子秤上容器本身的重量叫“皮重”。我们空秤的时候调用一次Get_Maopi()就是把当前传感器可能带着托盘的读数记下来以后所有的测量值都减去这个数就得到了物品的净重。校准系数 (GapValue)这是最关键的参数GapValue (AD值 / 重量)。比如你放上一个200g的标准砝码读到的AD值减去皮重后是41610那么GapValue就大约是41610 / 200 208.05。每个传感器都不一样这个值必须实测校准4. 在工程中调用与验证驱动文件准备好后就可以在主函数里使用了。4.1 主函数示例#include gd32f4xx.h #include systick.h #include stdio.h #include bsp_usart.h #include bsp_hx711.h int main(void) { // 系统初始化 nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2); systick_config(); usart_gpio_config(9600U); // 初始化串口用于打印重量到电脑 // HX711初始化 HX711_GPIO_Init(); // 重要上电后确保秤上是空的进行去皮操作 Get_Maopi(); delay_1ms(500); // 延时稳定一下 Get_Maopi(); // 可以多取几次平均这里简单再取一次 printf(HX711 Weight Scale Start\r\n); while(1) { // 循环读取并打印重量 float current_weight Get_Weight(); printf(Weight %.2f g\r\n, current_weight); // 假设校准后单位是克(g) delay_1ms(500); // 每500ms测量一次 } }4.2 校准与调试实战烧录程序后打开串口助手你应该能看到重量输出。但这时数字很可能不准甚至跳动很大。别急按下面步骤校准确保空秤稳定什么也不放观察输出的值是否在零点附近小幅波动。调用Get_Maopi()后Get_Weight()应该输出接近0的值比如0.00~0.50g之间波动。如果漂移很大检查硬件连接是否牢固电源是否稳定传感器是否受力均匀。校准GapValue放上一个已知重量的标准砝码比如200.00g。观察此时Get_Weight()输出的值假设显示为210.50g。这说明当前GapValue偏小了导致算出的重量偏大。我们需要增大GapValue。修改bsp_hx711.c文件中的#define GapValue 208.05将其等比例增大。计算公式是新GapValue 旧GapValue * (显示重量 / 真实重量)。例如208.05 * (210.50 / 200.00) ≈ 219.0。重新编译、烧录程序再放上砝码看显示。重复这个步骤直到显示重量与砝码重量基本一致。多次测量取平均高精度测量时软件上可以做滤波。比如连续读取10次HX711_Read()去掉最大最小值后求平均再用这个平均AD值去计算重量可以有效减少跳动。处理异常值可以在Get_Weight函数里增加判断如果读到的AD值异常比如小于皮重或超过传感器量程对应的最大AD值就返回一个错误码或上一次的有效值。按照上面的步骤你应该能成功驱动HX711并得到稳定的重量读数。这个驱动框架在多个我的小项目里都跑过只要硬件没问题校准得当精度和稳定性都非常不错。遇到问题多查查时序和那个关键的GapValue祝大家移植顺利