
STM32F103驱动HX711称重模块从电路设计到代码调试的完整避坑指南在嵌入式系统开发中精确的重量测量是一个常见但颇具挑战性的需求。无论是工业自动化中的配料系统还是医疗设备中的剂量控制甚至是智能家居中的厨房秤都需要稳定可靠的称重解决方案。而HX711作为一款专为称重传感器设计的24位模数转换器(ADC)以其高精度和低成本特性成为了众多开发者的首选。本文将带领你从零开始基于STM32F103系列MCU特别是资源受限的C6T6等小容量型号构建一个完整的称重系统。不同于简单的代码示例我们将深入探讨硬件设计中的关键细节、时序控制的精确实现以及实际项目中可能遇到的各种坑及其解决方案。无论你是正在开发商业产品的工程师还是完成毕业设计的学生这篇指南都能帮助你少走弯路快速实现稳定可靠的称重功能。1. 硬件设计从原理图到PCB布局的关键考量1.1 HX711模块选型与基本特性市面上的HX711模块主要分为两种类型普通版和带金属屏蔽罩的版本。对于精度要求较高的应用建议选择带屏蔽罩的模块它能有效减少电磁干扰(EMI)对微弱称重信号的影响。HX711的核心特性包括24位无失码分辨率理论最小可检测电压约0.3μV5V参考电压时可编程增益支持128倍通道A、64倍通道A和32倍通道B放大双差分输入内置低噪声可编程放大器直接连接称重传感器转换速率10Hz或80Hz可选通过RATE引脚配置提示购买模块时注意检查模块上的滤波电容是否足够。有些廉价模块可能省略了关键的电源滤波电容会导致读数不稳定。1.2 STM32与HX711的接口设计HX711与STM32的通信采用简单的两线制时钟和数据但有几个硬件设计细节直接影响系统稳定性GPIO选择必须使用具有FT5V耐压标志的GPIO引脚。对于STM32F103C6T6可用的FT引脚包括引脚功能备注PB0CLK必须配置为开漏输出PB1DATA配置为浮空输入上拉电阻设计CLK引脚1KΩ上拉到HX711的VCC非STM32的3.3VDATA引脚HX711内部已有上拉外部可不加电源隔离当HX711采用5V供电时必须确保数字信号的电压转换// 正确配置开漏输出CubeMX设置 GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_OD; // 开漏输出 GPIO_InitStruct.Pull GPIO_NOPULL; // 无内部上拉1.3 称重传感器连接与校准称重传感器通常采用惠斯通电桥结构连接时需注意激励电压(EXC/-)连接HX711的AVDD和AGND信号输出(SIG/-)连接HX711的A和A-通道校准电阻在EXC-和AGND之间并联一个0.1μF电容可减少噪声典型连接电路参数计算V_{diff} (V_{exc} \times R_{var}) / (2R R_{var})其中R为电桥固定臂电阻通常350Ω或1KΩRvar为应变电阻变化量。2. 软件架构精确时序与数据处理2.1 微秒级延时实现HX711对时序要求严格必须实现精确的微秒级延时。基于HAL库的优化实现如下// 微秒延时校准 void DelayCalibrate(void) { uint32_t ticks_per_us SystemCoreClock / 1000000; DWT-LOAD 0xFFFFFFFF; DWT-CTRL | DWT_CTRL_CYCCNTENA_Msk; } // 精确微秒延时 void DelayUs(uint32_t us) { uint32_t start DWT-CYCCNT; uint32_t ticks us * (SystemCoreClock / 1000000); while((DWT-CYCCNT - start) ticks); }注意使用DWT(Debug Watchpoint and Trace)单元前需先使能它CoreDebug-DEMCR | CoreDebug_DEMCR_TRCENA_Msk;2.2 HX711通信协议实现HX711的数据读取分为三个阶段等待就绪检测DATA线变低时钟脉冲发送25~27个时钟脉冲读取数据通道选择通过额外时钟设置下次转换的通道和增益完整读取函数示例uint32_t HX711_Read(ChannelGain cg) { while(GPIO_Read(DATA_PIN) 1); // 等待就绪 uint32_t data 0; for(uint8_t i0; i24; i) { // 读取24位数据 GPIO_Set(CLK_PIN); DelayUs(1); GPIO_Reset(CLK_PIN); data | GPIO_Read(DATA_PIN) (23 - i); DelayUs(1); } // 设置下次转换的通道和增益 for(uint8_t i0; icg; i) { GPIO_Set(CLK_PIN); DelayUs(1); GPIO_Reset(CLK_PIN); DelayUs(1); } return data ^ 0x800000; // 转换补码到原码 }2.3 数字滤波与噪声抑制原始ADC数据通常包含高频噪声需进行数字滤波移动平均滤波#define FILTER_SIZE 8 int32_t moving_avg_filter(int32_t new_val) { static int32_t buffer[FILTER_SIZE] {0}; static uint8_t index 0; static int64_t sum 0; sum - buffer[index]; buffer[index] new_val; sum new_val; index (index 1) % FILTER_SIZE; return sum / FILTER_SIZE; }中值滤波int32_t median_filter(int32_t new_val) { static int32_t buffer[5] {0}; static uint8_t index 0; buffer[index] new_val; index (index 1) % 5; int32_t temp[5]; memcpy(temp, buffer, sizeof(temp)); bubble_sort(temp, 5); // 实现简单的冒泡排序 return temp[2]; // 返回中值 }3. 系统校准与温度补偿3.1 两点校准法称重系统需要两个标准重量进行校准零点校准空载offset HX711_Read(GAIN_128);满量程校准已知重量Wscale (HX711_Read(GAIN_128) - offset) / W;实际重量计算weight (raw_value - offset) / scale;3.2 温度漂移补偿应变式称重传感器对温度敏感可采用多项式补偿float temp_compensated raw_value * (1.0 a*(T - T0) b*(T - T0)*(T - T0));其中a、b为温度系数通过实验测定。4. 低功耗设计与优化4.1 HX711电源管理HX711的AVDD在转换间隙会自动关闭但可通过硬件设计进一步降低功耗降低采样率将RATE引脚拉低选择10Hz模式间歇工作完成测量后拉低PD_SCK引脚超过60μs使芯片进入休眠动态增益调节根据重量自动切换增益轻载用高增益重载用低增益4.2 STM32低功耗策略配合HX711的工作周期STM32可进入低功耗模式void EnterLowPowerMode(void) { HAL_SuspendTick(); // 暂停SysTick HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); SystemClock_Config(); // 唤醒后重新配置时钟 }唤醒可通过外部中断连接HX711的DATA引脚实现。5. 常见问题排查与解决方案5.1 读数不稳定可能原因及解决方法电源噪声增加10μF钽电容和0.1μF陶瓷电容并联到AVDD机械振动增加软件滤波或硬件减震接地环路确保传感器与HX711单点接地5.2 线性度差校准步骤空载时读取10次取平均值作为零点施加最大量程50%的标准重量记录读数施加最大量程100%的标准重量记录读数使用两点校准法计算scale值5.3 响应速度慢优化策略将RATE引脚拉高选择80Hz模式减少滤波窗口大小权衡噪声和响应速度使用预测算法提前估计重量变化趋势6. 进阶技巧多传感器与自动量程切换6.1 多HX711并行读取通过片选信号控制多个HX711void SelectSensor(uint8_t id) { for(uint8_t i0; iMAX_SENSORS; i) { HAL_GPIO_WritePin(CS_GPIO, CS_PINS[i], (i id) ? GPIO_PIN_RESET : GPIO_PIN_SET); } DelayUs(100); // 稳定时间 }6.2 自动量程切换算法根据当前重量自动切换增益GainSetting AutoRange(int32_t raw) { static GainSetting current_gain GAIN_128; if(current_gain GAIN_128 abs(raw) 0x600000) { current_gain GAIN_64; HX711_SetGain(current_gain); } else if(current_gain GAIN_64 abs(raw) 0x300000) { current_gain GAIN_128; HX711_SetGain(current_gain); } return current_gain; }在实际项目中我发现最容易被忽视的是电源质量对测量精度的影响。曾有一个项目读数总是随机跳动最后发现是开关电源的纹波太大更换为线性稳压器后立即稳定。另一个常见误区是过度依赖软件滤波其实硬件设计合理的话简单的移动平均就能获得很好的效果。