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 电路连接方案
完整的硬件连接需要关注三个关键接口:
电源部分:
- 使用AMS1117-3.3稳压芯片为系统供电
- 在HX711的AVDD与AGND间并联100μF电解电容
- 传感器激励电压建议采用独立LDO供电
传感器接口:
称重传感器(4线制) → HX711 RED → E+ BLACK → E- WHITE → A- GREEN → A+数据通信线路:
// 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精度,需要执行以下校准步骤:
空载校准:
long offset = 0; for(int i=0; i<10; i++) { offset += HX711_Read(); delay(100); } offset /= 10;已知重量校准:
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;线性验证: 用不同重量砝码(如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.0 | 0.05 | +50 |
| 5.0 | 5.02 | +20 |
| 10.0 | 9.97 | -30 |
| 20.0 | 20.03 | +30 |
通过软件校准后,最终系统精度可稳定在±0.1kg范围内。实际测试中发现,环境温度变化超过10℃时需要重新校准。