STM32超声波测距实战从硬件连接到OLED显示附完整代码超声波测距技术因其成本低、精度适中、实现简单等优势在智能小车避障、工业测距、智能家居等领域广泛应用。本文将手把手带你完成基于STM32的超声波测距系统开发涵盖硬件连接、代码实现到OLED显示的全流程。不同于简单的代码搬运我们会深入探讨温度补偿、误差处理等实际开发中必须面对的细节问题。1. 硬件设计与连接1.1 超声波模块选型与原理市面上常见的HC-SR04超声波模块工作电压为5V测距范围2cm-400cm满足大多数场景需求。其核心工作原理如下触发阶段给Trig引脚至少10μs的高电平脉冲发射阶段模块自动发送8个40kHz的超声波脉冲回波检测模块通过Echo引脚输出高电平持续时间与距离成正比距离计算公式为距离(cm) 高电平时间(μs) / 58注意声速受温度影响显著15℃时为340m/s温度每变化1℃声速变化约0.6m/s。高精度应用需增加温度传感器进行补偿。1.2 硬件连接示意图STM32引脚超声波模块OLED显示屏PB11Trig-PB10Echo-PB6-SCLPB7-SDA3.3VVCCVCCGNDGNDGND关键细节超声波模块最好单独供电避免电机等大电流设备干扰Echo引脚建议串联200Ω电阻保护IO口OLED显示模块选择I2C接口版本节省IO资源2. 软件架构设计2.1 核心代码结构/* 文件结构 */ ├── Drivers │ ├── STM32F1xx_HAL_Driver │ └── CMSIS ├── Inc │ ├── hcsr04.h │ ├── oled.h │ └── main.h └── Src ├── hcsr04.c // 超声波驱动 ├── oled.c // 显示驱动 └── main.c // 主逻辑2.2 定时器配置关键代码使用TIM2进行高精度时间测量void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig {0}; TIM_MasterConfigTypeDef sMasterConfig {0}; htim2.Instance TIM2; htim2.Init.Prescaler 72-1; // 1MHz计数频率 htim2.Init.CounterMode TIM_COUNTERMODE_UP; htim2.Init.Period 0xFFFFFFFF; // 最大计数值 htim2.Init.ClockDivision TIM_CLOCKDIVISION_DIV1; HAL_TIM_Base_Init(htim2); sClockSourceConfig.ClockSource TIM_CLOCKSOURCE_INTERNAL; HAL_TIM_ConfigClockSource(htim2, sClockSourceConfig); sMasterConfig.MasterOutputTrigger TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(htim2, sMasterConfig); }3. 核心算法实现3.1 带温度补偿的距离计算float Get_Distance(float temperature) { uint32_t pulse_width 0; float sound_speed 331.4 0.6 * temperature; // m/s float distance_cm 0; // 触发测量 HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET); delay_us(15); HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET); // 等待回波 while(!HAL_GPIO_ReadPin(ECHO_GPIO_Port, ECHO_Pin)); HAL_TIM_Base_Start(htim2); while(HAL_GPIO_ReadPin(ECHO_GPIO_Port, ECHO_Pin)); HAL_TIM_Base_Stop(htim2); pulse_width __HAL_TIM_GET_COUNTER(htim2); // 获取计数值 distance_cm (pulse_width * sound_speed) / 20000.0; // 往返距离 return distance_cm; }3.2 数字滤波处理针对超声波测距常见的随机误差采用移动平均滤波#define FILTER_SIZE 5 float Moving_Average_Filter(float new_data) { static float buffer[FILTER_SIZE] {0}; static uint8_t index 0; float sum 0; buffer[index] new_data; index (index 1) % FILTER_SIZE; for(int i0; iFILTER_SIZE; i){ sum buffer[i]; } return sum / FILTER_SIZE; }4. OLED显示优化4.1 多级菜单实现通过按键切换显示模式typedef enum { DISPLAY_MODE_NORMAL, DISPLAY_MODE_HISTORY, DISPLAY_MODE_SETTING } DisplayMode_t; void Update_Display(DisplayMode_t mode) { switch(mode){ case DISPLAY_MODE_NORMAL: OLED_ShowString(0, 0, Distance:); OLED_ShowFloat(2, 0, current_distance, 1, 1); OLED_ShowString(4, 0, cm); break; case DISPLAY_MODE_HISTORY: // 显示历史数据统计 break; case DISPLAY_MODE_SETTING: // 显示参数设置界面 break; } }4.2 可视化效果增强添加距离柱状图显示void Draw_Distance_Bar(float distance) { uint8_t bar_length (uint8_t)(distance / 400.0 * 128); // 满量程400cm对应128像素 OLED_DrawRectangle(0, 6, bar_length, 8, 1); OLED_Refresh(); }5. 常见问题排查5.1 典型故障现象及解决方法故障现象可能原因解决方案测量值固定为0Echo引脚未连接检查硬件连接测量值波动大电源干扰增加滤波电容测量值偏大温度补偿未启用启用温度补偿算法OLED显示乱码I2C地址不匹配确认OLED模块的I2C地址5.2 性能优化技巧降低功耗间隔测量替代连续测量提高响应速度使用DMA传输OLED数据增强鲁棒性添加超时判断防止死等回波// 带超时的回波检测 uint32_t timeout 100000; // 100ms超时 while(!HAL_GPIO_ReadPin(ECHO_GPIO_Port, ECHO_Pin) timeout--); if(timeout 0) return -1; // 超时错误6. 项目扩展方向6.1 多传感器融合结合红外传感器提升测距可靠性#define ULTRASONIC_WEIGHT 0.7 #define IR_WEIGHT 0.3 float Fused_Distance(float ultrasonic_dist, float ir_dist) { return ULTRASONIC_WEIGHT * ultrasonic_dist IR_WEIGHT * ir_dist; }6.2 无线数据传输通过蓝牙模块将数据发送到手机APPvoid Bluetooth_Send(float distance) { char buffer[20]; sprintf(buffer, DIST:%.1fcm\n, distance); HAL_UART_Transmit(huart1, (uint8_t*)buffer, strlen(buffer), 100); }在完成基础功能后尝试添加以下高级功能自动校准功能测量数据SD卡存储通过PWM控制蜂鸣器报警