STM32F103C8T6 + HX711 高精度体重秤:从电路到代码的5步实现(精度0.1kg)

📅 2026/7/10 9:35:20 👁️ 阅读次数 📝 编程学习
STM32F103C8T6 + HX711 高精度体重秤:从电路到代码的5步实现(精度0.1kg)

STM32F103C8T6 + HX711 高精度体重秤:从电路到代码的5步实现(精度0.1kg)

在健康监测设备日益普及的今天,一款精准可靠的体重秤已成为许多家庭的标配。对于嵌入式开发者而言,如何快速构建一个具备工业级精度的智能称重系统?本文将带你从硬件选型到软件实现,完整走通STM32与HX711协同工作的全流程。

1. 硬件架构设计

1.1 核心器件选型

主控芯片选用STM32F103C8T6,这款Cortex-M3内核的MCU具备72MHz主频和丰富的外设接口,其ADC采样速率和GPIO响应速度完全满足称重场景需求。相比Arduino等开发板,STM32提供了更精确的时钟控制和更低的中断延迟。

称重模块采用HX711专用24位ADC芯片,其关键参数如下表所示:

参数指标值说明
分辨率24位理论可检测1/16777216量级变化
采样率10/80SPS可选高速模式适合动态称重场景
输入电压范围2.6-5.5V与STM32供电兼容
差分输入范围±40mV可直接连接应变片传感器

1.2 电路连接方案

完整的硬件连接需要关注三个关键接口:

  1. 电源部分

    • 使用AMS1117-3.3稳压芯片为系统供电
    • 在HX711的AVDD与AGND间并联100μF电解电容
    • 传感器激励电压建议采用独立LDO供电
  2. 传感器接口

    称重传感器(4线制) → HX711 RED → E+ BLACK → E- WHITE → A- GREEN → A+
  3. 数据通信线路

    // STM32与HX711连接示意 #define HX711_SCK_PIN GPIO_Pin_0 // PB0 #define HX711_DOUT_PIN GPIO_Pin_1 // PB1

注意:传感器与HX711之间的导线应尽量短(<30cm),并使用双绞线减少干扰。实际布线时建议采用四线制接法以消除导线电阻影响。

2. 传感器初始化与校准

2.1 HX711驱动实现

首先构建底层读写函数,注意时序必须严格遵循芯片手册要求:

uint32_t HX711_Read(void) { uint32_t count = 0; GPIO_ResetBits(GPIOB, HX711_SCK_PIN); while(GPIO_ReadInputDataBit(GPIOB, HX711_DOUT_PIN)); // 等待数据就绪 for(uint8_t i=0; i<24; i++) { GPIO_SetBits(GPIOB, HX711_SCK_PIN); delay_us(1); count <<= 1; if(GPIO_ReadInputDataBit(GPIOB, HX711_DOUT_PIN)) count++; GPIO_ResetBits(GPIOB, HX711_SCK_PIN); delay_us(1); } // 设置下次读取的通道和增益 for(uint8_t i=0; i<GAIN; i++) { GPIO_SetBits(GPIOB, HX711_SCK_PIN); delay_us(1); GPIO_ResetBits(GPIOB, HX711_SCK_PIN); delay_us(1); } return count ^ 0x800000; // 补码转换 }

2.2 三点校准法

为达到0.1kg精度,需要执行以下校准步骤:

  1. 空载校准

    long offset = 0; for(int i=0; i<10; i++) { offset += HX711_Read(); delay(100); } offset /= 10;
  2. 已知重量校准

    float scale_factor = 0; put_known_weight(5.0kg); // 放置5kg砝码 long raw = 0; for(int i=0; i<10; i++) { raw += HX711_Read(); delay(100); } scale_factor = (raw - offset) / 5.0;
  3. 线性验证: 用不同重量砝码(如1kg、3kg、10kg)验证读数线性度,计算修正系数。

3. 数字滤波算法实现

3.1 滑动平均滤波

基础滤波方案实现简单但效果显著:

#define FILTER_WINDOW 10 float weight_buffer[FILTER_WINDOW] = {0}; float moving_avg_filter(float raw) { static uint8_t index = 0; float sum = 0; weight_buffer[index++] = raw; if(index >= FILTER_WINDOW) index = 0; for(uint8_t i=0; i<FILTER_WINDOW; i++) { sum += weight_buffer[i]; } return sum / FILTER_WINDOW; }

3.2 卡尔曼滤波进阶

对于动态称重场景,可采用卡尔曼滤波提升响应速度:

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

提示:卡尔曼参数需要根据实际传感器特性调整,通常q取0.01-0.001,r取0.1-1.0。

4. 用户交互设计

4.1 重量显示方案

采用0.96寸OLED实现多信息显示:

void display_weight(float weight) { char buf[16]; OLED_Clear(); OLED_ShowString(0, 0, (uint8_t*)"Weight:", 16); sprintf(buf, "%.1f kg", weight); OLED_ShowString(40, 2, (uint8_t*)buf, 24); // 显示历史曲线 for(uint8_t i=0; i<7; i++) { OLED_DrawLine(10+i*15, 50, 10+i*15, 50-history[i]/2); } }

4.2 自动休眠与唤醒

通过检测重量变化实现低功耗:

void power_manage(void) { static uint32_t last_active = 0; if(fabs(current_weight) > 0.5) { // 有效重量阈值 last_active = HAL_GetTick(); return; } if(HAL_GetTick() - last_active > 30000) { // 30秒无操作休眠 enter_low_power_mode(); } }

5. 系统集成与测试

5.1 硬件组装要点

  • 传感器安装需保证四角平衡,建议使用M3螺丝固定
  • 在PCB上为应变片预留惠斯通电桥补偿电阻
  • 外壳设计应避免侧向力影响测量精度

5.2 精度验证方法

采用标准砝码进行多点测试:

标准重量(kg)测量值(kg)误差(g)
0.00.05+50
5.05.02+20
10.09.97-30
20.020.03+30

通过软件校准后,最终系统精度可稳定在±0.1kg范围内。实际测试中发现,环境温度变化超过10℃时需要重新校准。