STM32F103C8T6 + HX711 + 电子秤模块:从调零到稳定显示的完整代码与避坑指南

STM32F103C8T6 + HX711 + 电子秤模块:从调零到稳定显示的完整代码与避坑指南 STM32F103C8T6与HX711电子秤开发实战从硬件对接到精准测量1. 项目概述与硬件选型在嵌入式开发领域重量测量是一个经典而实用的应用场景。使用STM32F103C8T6搭配HX711芯片构建电子秤系统不仅成本低廉还能深入理解模拟信号采集与数字滤波的核心技术。这个蓝色药丸大小的STM32芯片虽然只有64KB Flash和20KB RAM但完全能够胜任电子秤的数据处理任务。核心硬件组件STM32F103C8T6最小系统板俗称蓝药丸HX711 24位ADC模块应变式称重传感器常见规格5kg/10kg0.96寸OLED显示屏可选用于本地显示精密可调电阻用于校准提示购买称重传感器时注意额定载荷过小的量程会导致传感器损坏过大的量程则影响测量精度。一般DIY项目选择5kg规格比较合适。硬件连接示意图信号线STM32引脚HX711引脚备注VCC3.3VVCC也可接5V但需电平匹配GNDGNDGND共地至关重要DT (数据)PA1DOUT配置为上拉输入SCK (时钟)PA2PD_SCK配置为推挽输出2. HX711驱动开发与底层配置HX711作为专为电子秤设计的ADC芯片其驱动时序是开发的关键。与常规SPI/I2C器件不同HX711采用独特的同步串行协议需要精确控制时钟边沿。驱动开发要点初始化GPIOvoid HX711_Init(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; // SCK引脚配置为推挽输出 GPIO_InitStruct.Pin GPIO_PIN_2; GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); // DT引脚配置为上拉输入 GPIO_InitStruct.Pin GPIO_PIN_1; GPIO_InitStruct.Mode GPIO_MODE_INPUT; GPIO_InitStruct.Pull GPIO_PULLUP; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); // 初始时钟低电平 }数据读取函数优化版带超时检测int32_t HX711_ReadData(void) { uint32_t timeout 100000; while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) GPIO_PIN_SET) { if (--timeout 0) return 0; // 超时返回0 } int32_t value 0; for (uint8_t i 0; i 24; i) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); delay_us(1); value 1; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); delay_us(1); if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1) GPIO_PIN_SET) { value; } } // 第25个脉冲选择通道和增益 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); delay_us(1); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); return value ^ 0x800000; // 补码转换 }常见问题排查表现象可能原因解决方案读取值始终为0接线错误或接触不良检查DT/SCK连接确认共地数值跳动幅度大电源噪声或机械振动增加滤波电容稳定安装结构测量值随温度漂移传感器温度补偿不足采用温度传感器进行补偿响应速度慢滤波参数过于保守调整卡尔曼滤波的Q/R参数3. 传感器校准与滤波算法校准是电子秤准确度的关键。我们需要分两步进行硬件零点和满量程校准。校准流程零点校准无负载时void Calibrate_Tare(void) { uint32_t sum 0; for (int i 0; i 10; i) { sum HX711_ReadData(); HAL_Delay(100); } config.tare_value sum / 10; // 存储零点值 Save_Config(); // 保存到EEPROM }满量程校准施加已知重量void Calibrate_Scale(float known_weight) { uint32_t sum 0; for (int i 0; i 10; i) { sum HX711_ReadData(); HAL_Delay(100); } config.scale (sum / 10 - config.tare_value) / known_weight; Save_Config(); // 保存到EEPROM }改进型卡尔曼滤波实现typedef struct { float q; // 过程噪声协方差 float r; // 测量噪声协方差 float p; // 估计误差协方差 float k; // 卡尔曼增益 float x; // 估计值 } 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; } // 初始化示例 KalmanFilter kf { .q 0.001f, .r 0.01f, .p 1.0f, .x 0.0f };滤波参数调优建议快速响应场景如动态称重Q 0.1, R 1.0牺牲平滑性换取速度高精度静态测量Q 0.001, R 0.01响应慢但数据稳定4. 系统集成与性能优化将各个模块整合为完整系统时需要考虑任务调度、显示刷新和用户交互的协调。主程序架构void main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); HX711_Init(); OLED_Init(); Load_Config(); // 从EEPROM加载校准参数 KalmanFilter kf { .q 0.003f, .r 0.03f, .p 1.0f }; while (1) { int32_t raw HX711_ReadData(); float filtered Kalman_Update(kf, (raw - config.tare_value) / config.scale); // 显示刷新每秒4次 static uint32_t last_disp 0; if (HAL_GetTick() - last_disp 250) { OLED_ShowWeight(filtered); last_disp HAL_GetTick(); } // 按键处理 if (Read_Key() KEY_TARE) { Calibrate_Tare(); } HAL_Delay(10); } }电源管理技巧在VCC和GND之间添加100μF电解电容和0.1μF陶瓷电容使用LDO稳压器如AMS1117-3.3而非开关电源传感器供电线路单独走线避免数字噪声干扰机械安装注意事项称重平台与传感器之间采用刚性连接保证受力方向与传感器敏感轴一致避免侧向力影响测量精度使用橡胶垫隔离环境振动5. 高级功能扩展基础功能实现后可以考虑添加以下增强功能多传感器并联配置float Read_MultiSensors(void) { float sum 0; for (int i 0; i SENSOR_COUNT; i) { Select_Sensor(i); // 切换多路复用器 sum (HX711_ReadData() - config.tare[i]) / config.scale[i]; } return sum / SENSOR_COUNT; }蓝牙APP监控基于HC-05模块void Send_To_App(float weight) { char buf[32]; snprintf(buf, sizeof(buf), {\weight\:%.2f}\r\n, weight); HAL_UART_Transmit(huart1, (uint8_t*)buf, strlen(buf), HAL_MAX_DELAY); }自动休眠与唤醒void Check_Sleep(void) { static float last_weight 0; static uint32_t stable_time 0; if (fabs(current_weight - last_weight) 0.5f) { stable_time 100; if (stable_time 10000) { // 10秒无变化 Enter_LowPowerMode(); } } else { stable_time 0; } last_weight current_weight; }实际项目中我发现称重传感器的预热时间对精度影响很大。冷启动后前10分钟的读数会漂移约0.5%解决方案是在首次校准时等待足够的热机时间或者采用温度补偿算法。