HX711压力传感器实战:基于STM32 HAL库的精准称重系统设计与校准
2026/7/15 1:57:50 网站建设 项目流程

1. HX711压力传感器与STM32开发基础

第一次接触HX711压力传感器时,我被它的小巧体积和强大功能惊艳到了。这个只有指甲盖大小的芯片,居然能实现24位精度的模数转换,完全能满足厨房秤、工业称重等场景的需求。HX711本质上是一个带放大功能的ADC芯片,专门为应变片式称重传感器设计。

硬件连接其实非常简单,你只需要准备:

  • 一块STM32开发板(推荐STM32F103C8T6,便宜又好用)
  • HX711模块(淘宝10块钱左右)
  • 压力传感器(通常随HX711一起购买)

接线时要注意:HX711的VCC接3.3V或5V,GND接地,DOUT接STM32的GPIO输入引脚,SCK接GPIO输出引脚。我用的是PB0和PB1,你完全可以根据自己开发板的空闲引脚调整。

2. HAL库环境搭建与GPIO配置

使用STM32CubeMX可以快速生成HAL库工程。新建工程选择你的芯片型号后,在Pinout界面配置两个GPIO:

  • 将PB0设置为GPIO_Output(推挽输出,高速模式)
  • 将PB1设置为GPIO_Input(上拉输入)

生成代码后,在main.c中添加HX711的初始化函数:

void Init_HX711pin(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOB_CLK_ENABLE(); // SCK引脚配置 GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); // DOUT引脚配置 GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); }

实测发现,HAL库的GPIO操作比标准库稍慢,所以在时序要求严格的场合,可以直接操作寄存器:

#define HX711_SCK_SET() (GPIOB->BSRR = GPIO_PIN_0) #define HX711_SCK_RESET() (GPIOB->BRR = GPIO_PIN_0) #define HX711_DOUT_READ() (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1))

3. HX711数据读取与增益设置

HX711的数据读取需要严格遵循时序。芯片支持三种增益设置(128/64/32),对应不同的应用场景。我以最常用的128倍增益为例:

uint32_t HX711_Read(void) { uint32_t count = 0; uint8_t i; HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); while(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_SET); for(i=0; i<24; i++) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); count <<= 1; HAL_Delay(1); // 实际使用中应该用更精确的延时 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1) == GPIO_PIN_SET) count++; HAL_Delay(1); } // 第25个脉冲选择增益 HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); count ^= 0x800000; // 转换补码 HAL_Delay(1); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); return count; }

几个关键点需要注意

  1. 必须先等待DOUT变低才开始读取
  2. 每个时钟脉冲后需要至少1us的延时
  3. 第25个脉冲决定下次转换的增益
  4. 返回的数据是补码形式,需要异或0x800000转换

4. 称重算法实现与去皮功能

实际称重时需要先获取空载时的基准值(去皮),然后计算实际重量:

uint32_t tare_weight = 0; // 去皮重量 float calibration_factor = 106.5f; // 校准系数 float Get_Weight(void) { uint32_t raw_data = HX711_Read(); if(raw_data > tare_weight) { float weight = (raw_data - tare_weight) / calibration_factor; return weight > 0 ? weight : 0; } return 0; } void Tare(void) { tare_weight = HX711_Read(); }

校准系数需要根据实际传感器调整。我的经验是先用标准砝码测试:

  1. 空载时调用Tare()去皮
  2. 放上已知重量的砝码(如500g)
  3. 记录此时的raw_data值
  4. 计算:calibration_factor = (raw_data - tare_weight) / 砝码重量

5. 卡尔曼滤波实现数据平滑

原始数据会有波动,加入卡尔曼滤波后效果明显改善。我在项目中使用的简化版卡尔曼滤波器:

typedef struct { float q; // 过程噪声协方差 float r; // 测量噪声协方差 float x; // 估计值 float p; // 估计误差协方差 float k; // 卡尔曼增益 } KalmanFilter; void Kalman_Init(KalmanFilter* kf, float q, float r) { kf->q = q; kf->r = r; kf->p = 1; kf->x = 0; } float Kalman_Update(KalmanFilter* kf, float measurement) { // 预测 kf->p += kf->q; // 更新 kf->k = kf->p / (kf->p + kf->r); kf->x += kf->k * (measurement - kf->x); kf->p *= (1 - kf->k); return kf->x; }

使用时先初始化:

KalmanFilter kf; Kalman_Init(&kf, 0.01, 0.5); // 参数需要根据实际情况调整

然后在获取重量后滤波:

float raw_weight = Get_Weight(); float filtered_weight = Kalman_Update(&kf, raw_weight);

6. 线性回归校准提升精度

为了进一步提高精度,我采用了线性回归校准。具体步骤:

  1. 准备多个标准砝码(如100g、200g、500g、1000g)
  2. 记录每个砝码对应的AD值
  3. 使用Excel或数学工具计算斜率和截距
  4. 应用校准公式:
typedef struct { float slope; float intercept; } LinearCalibration; LinearCalibration calib = {0.0023, -12.4}; // 示例值 float Calibrated_Weight(uint32_t raw) { return calib.slope * (raw - tare_weight) + calib.intercept; }

实测发现,经过线性校准后,误差可以控制在0.5%以内,完全满足商业电子秤的要求。

7. 完整工程实现与优化建议

将上述模块整合后,主程序逻辑如下:

int main(void) { HAL_Init(); SystemClock_Config(); Init_HX711pin(); KalmanFilter kf; Kalman_Init(&kf, 0.01, 0.5); Tare(); // 去皮 while(1) { float weight = Kalman_Update(&kf, Get_Weight()); printf("Weight: %.1fg\r\n", weight); HAL_Delay(100); } }

几个优化建议

  1. 使用定时器中断定期采样,避免主循环阻塞
  2. 添加温度补偿,环境温度变化会影响传感器精度
  3. 实现自动休眠功能,降低功耗
  4. 对于快速变化的重量(如流水线称重),可以适当降低滤波强度

8. 常见问题排查与解决

在实际开发中遇到过几个典型问题:

问题1:读数不稳定

  • 检查电源是否稳定,HX711对电源噪声敏感
  • 确保传感器安装牢固,没有机械振动
  • 适当增加卡尔曼滤波的Q值

问题2:重量显示为负数

  • 确认去皮操作正确
  • 检查传感器接线是否正确,A+和A-不要接反
  • 可能是线性校准的截距设置过大

问题3:响应速度慢

  • 降低滤波强度(减小R值)
  • 检查延时函数是否过长
  • 尝试使用DMA或中断方式读取数据

问题4:不同重量段误差不一致

  • 分段线性校准,对不同重量范围使用不同参数
  • 检查传感器量程是否合适,超量程使用会降低精度

记得每次硬件改动后都要重新校准。我用3D打印了一个传感器支架,发现支架本身的重量也会影响测量,所以必须在安装好所有机械结构后再进行校准。

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

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

立即咨询