STM32F103C8T6 + HX711 + 压力传感器:从CubeMX配置到串口打印重量值的保姆级教程
STM32F103C8T6与HX711压力传感器全流程实战指南
1. 项目概述与硬件准备
在嵌入式开发领域,重量测量是一个常见但技术要求较高的应用场景。STM32F103C8T6作为一款性价比极高的ARM Cortex-M3内核微控制器,配合HX711这款专为电子秤设计的24位ADC芯片,能够构建稳定可靠的压力测量系统。这套组合特别适合需要精确测量小范围重量变化的场景,比如智能厨房秤、实验室测量设备或工业自动化中的重量检测环节。
硬件准备清单 :
- STM32F103C8T6最小系统板(蓝色药丸开发板)
- HX711模块(带焊接排针)
- 压力传感器(常见规格:5kg/10kg量程)
- 杜邦线若干(建议使用优质线材减少干扰)
- USB转TTL串口模块(用于调试输出)
- 稳压电源或手机充电器(为系统供电)
硬件连接时需特别注意:
- HX711的VCC引脚可接3.3V或5V,但必须与STM32逻辑电平匹配
- DOUT(数据线)连接STM32的GPIO输入引脚
- SCK(时钟线)连接STM32的GPIO输出引脚
- 压力传感器的四个应变片引线需正确接入HX711的A+、A-、B+、B-端子
2. CubeMX工程配置详解
2.1 时钟系统配置
启动CubeMX后,选择STM32F103C8T6型号并进入时钟配置界面。对于HX711应用,我们推荐如下配置:
- 在RCC配置中选择高速外部晶振(HSE)
-
系统时钟树设置:
- PLL源选择HSE
- 设置PLL倍频因子为9(8MHz晶振×9=72MHz系统时钟)
- 配置AHB预分频器为1(72MHz)
- APB1预分频器设为2(36MHz)
- APB2预分频器保持1(72MHz)
提示:精确的时钟配置对HX711的时序控制至关重要,建议使用外部晶振而非内部RC振荡器。
2.2 GPIO引脚配置
根据硬件连接方案,在CubeMX中配置对应引脚:
| 引脚功能 | 引脚编号 | 模式配置 | 备注 |
|---|---|---|---|
| SCK | PA0 | GPIO_Output | 推挽输出,无上下拉 |
| DOUT | PA1 | GPIO_Input | 上拉输入 |
| USART1_TX | PA9 | USART1_TX | 异步模式 |
| USART1_RX | PA10 | USART1_RX | 异步模式 |
配置完成后生成代码前,务必检查:
- 每个GPIO的初始状态设置是否正确
- 是否启用了需要的时钟(如USART1)
- 中断优先级配置(本项目暂不需要)
3. HX711驱动开发与移植
3.1 基本读写时序实现
HX711的通信协议相对简单但时序要求严格。创建hx711.c文件并实现以下核心函数:
// 读取HX711数据(增益128)
uint32_t HX711_Read(void) {
uint32_t count = 0;
uint8_t i;
HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);
// 等待数据就绪
while(HAL_GPIO_ReadPin(DOUT_GPIO_Port, DOUT_Pin) == GPIO_PIN_SET);
// 读取24位数据
for(i=0; i<24; i++) {
HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);
delay_us(1);
count = count << 1;
HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);
delay_us(1);
if(HAL_GPIO_ReadPin(DOUT_GPIO_Port, DOUT_Pin) == GPIO_PIN_SET) {
count++;
}
}
// 设置增益为128(发送第25个脉冲)
HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET);
delay_us(1);
HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET);
delay_us(1);
return count ^ 0x800000; // 补码转换
}
3.2 去皮与重量计算
实际应用中需要考虑去皮(Tare)功能,即扣除容器重量:
// 全局变量定义
uint32_t tare_value = 0;
float calibration_factor = 106.5f; // 需根据传感器特性调整
void Get_Tare(void) {
uint32_t sum = 0;
for(uint8_t i=0; i<10; i++) {
sum += HX711_Read();
HAL_Delay(10);
}
tare_value = sum / 10;
}
float Get_Weight(void) {
uint32_t raw_data = HX711_Read();
if(raw_data > tare_value) {
return (float)(raw_data - tare_value) / calibration_factor;
}
return 0.0f;
}
4. 数据处理与优化技巧
4.1 数字滤波实现
压力传感器读数常伴有噪声,采用合适的滤波算法可显著提升稳定性:
移动平均滤波实现 :
#define FILTER_WINDOW_SIZE 5
float moving_average_filter(float new_sample) {
static float buffer[FILTER_WINDOW_SIZE] = {0};
static uint8_t index = 0;
static float sum = 0;
sum -= buffer[index];
buffer[index] = new_sample;
sum += buffer[index];
index = (index + 1) % FILTER_WINDOW_SIZE;
return sum / FILTER_WINDOW_SIZE;
}
卡尔曼滤波简化版 :
float simple_kalman_filter(float new_value) {
static float last_value = 0;
static float p = 1.0f;
const float q = 0.01f; // 过程噪声
const float r = 0.1f; // 观测噪声
// 预测
p = p + q;
// 更新
float kg = p / (p + r);
float current_value = last_value + kg * (new_value - last_value);
p = (1 - kg) * p;
last_value = current_value;
return current_value;
}
4.2 校准与误差补偿
精确测量需要进行系统校准:
-
零点校准 :
- 空载状态下执行Get_Tare()函数
- 确保传感器不受外力作用
-
满量程校准 :
- 放置已知重量的标准砝码
- 调整calibration_factor直到显示重量与实际一致
-
计算公式:
新校准系数 = (当前系数 × 显示重量) / 实际重量
常见问题排查:
- 读数不稳定:检查电源质量,确保传感器供电充足
- 数值漂移:检查机械结构是否稳固,避免温度剧烈变化
- 线性度差:考虑分段校准或非线性补偿算法
5. 系统集成与调试
5.1 主程序逻辑实现
在main.c中构建完整应用流程:
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
// 初始化延时函数
delay_init(72);
printf("系统启动...\r\n");
printf("执行去皮操作,请确保空载...\r\n");
Get_Tare();
printf("去皮完成,当前零点值:%lu\r\n", tare_value);
while(1) {
float weight = Get_Weight();
weight = moving_average_filter(weight); // 应用滤波
printf("当前重量: %.2f g\r\n", weight);
HAL_Delay(200); // 控制输出频率
}
}
5.2 串口调试技巧
利用串口输出调试信息时,推荐以下实践:
-
格式化输出 :
printf("重量: %.1fg 原始值: %lu 校准系数: %.2f\r\n", weight, raw_data, calibration_factor); -
调试命令接口 :
if(serial_data_available()) { char cmd = getchar(); switch(cmd) { case 't': Get_Tare(); break; case '+': calibration_factor *= 1.01f; break; case '-': calibration_factor *= 0.99f; break; } } -
数据可视化 :
- 使用串口绘图工具(如SerialPlot)实时显示重量曲线
- 通过Excel分析采集的历史数据
6. 进阶优化方向
6.1 低功耗设计
对于电池供电的应用,可实施以下优化:
- 配置STM32进入睡眠模式,定时唤醒采样
- 动态调整HX711的采样速率
- 关闭不必要的外设时钟
void enter_low_power_mode(void) {
// 配置唤醒源(如外部中断)
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
}
6.2 多传感器融合
结合其他传感器提升系统可靠性:
- 温度传感器补偿热漂移
- 加速度计检测机械振动干扰
- 湿度传感器监测环境变化
6.3 用户界面增强
提升终端用户体验:
- 添加按键控制去皮/校准功能
- 设计OLED显示界面
- 实现蓝牙/Wi-Fi无线数据传输
- 开发手机APP可视化数据
void update_display(float weight) {
char buf[16];
sprintf(buf, "%.1f g", weight);
OLED_ShowString(0, 0, (uint8_t *)buf, 16);
}
在实际项目中,我发现机械结构的稳定性往往比电路设计更能影响测量精度。一个常见的错误是过度关注软件滤波而忽视了传感器的物理安装。使用3D打印的传感器支架配合适当的预紧力调节,能让系统性能提升显著。
更多推荐
所有评论(0)