STM32F103C8T6驱动HC-SR04超声波模块,OLED显示测距结果(附完整工程代码)
STM32F103C8T6与HC-SR04超声波测距系统开发实战项目背景与硬件选型在嵌入式开发领域距离测量是一个基础但极其重要的功能。HC-SR04超声波模块因其成本低廉、使用简单而广受欢迎配合STM32F103C8T6这款经典的ARM Cortex-M3内核微控制器可以构建出稳定可靠的测距系统。这个组合特别适合智能小车避障、液位检测、智能家居感应等应用场景。核心硬件组件STM32F103C8T6最小系统板Blue Pill开发板HC-SR04超声波测距模块工作电压5V测量范围2cm-400cm0.96寸OLED显示屏SSD1306驱动I2C接口硬件连接示意图如下模块引脚STM32引脚备注HC-SR04 VCC5V电源正极HC-SR04 GNDGND电源地HC-SR04 TrigPA1触发信号输出HC-SR04 EchoPA2回波信号输入OLED VCC3.3V电源正极OLED GNDGND电源地OLED SCLPB6I2C时钟线OLED SDAPB7I2C数据线超声波测距原理深度解析HC-SR04模块通过发射和接收超声波来测量距离。其工作流程可分为三个阶段触发阶段向Trig引脚发送至少10μs的高电平脉冲发射阶段模块自动发射8个40kHz的超声波脉冲回波检测阶段Echo引脚输出高电平其持续时间与距离成正比距离计算公式为距离(cm) 高电平时间(μs) / 58这个公式的推导基于声速340m/s和往返时间的考量。在实际应用中我们需要特别注意温度补偿声速会随温度变化v331.40.6*T℃T为摄氏温度多次采样建议取5-10次测量的平均值以提高精度超时处理设置合理的超时时间如30ms避免长时间等待STM32CubeMX工程配置使用STM32CubeMX可以快速完成硬件初始化配置以下是关键步骤时钟配置设置HSE为外部晶振8MHz系统时钟配置为72MHzAPB1定时器时钟为72MHzGPIO配置PA1设置为GPIO输出Trig引脚PA2设置为GPIO输入Echo引脚定时器配置// TIM3基本配置 htim3.Instance TIM3; htim3.Init.Prescaler 71; // 72MHz/72 1MHz (1μs分辨率) htim3.Init.CounterMode TIM_COUNTERMODE_UP; htim3.Init.Period 65535; // 最大计数值 htim3.Init.ClockDivision TIM_CLOCKDIVISION_DIV1;I2C配置用于OLEDI2C1模式选择标准模式100kHzPB6SCL和PB7SDA设置为复用开漏输出核心代码实现超声波驱动模块超声波模块的驱动代码主要包括初始化、触发和距离测量三个部分// 超声波模块初始化 void HCSR04_Init(void) { GPIO_InitTypeDef GPIO_InitStruct {0}; // Trig引脚配置 GPIO_InitStruct.Pin GPIO_PIN_1; GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); // Echo引脚配置 GPIO_InitStruct.Pin GPIO_PIN_2; GPIO_InitStruct.Mode GPIO_MODE_INPUT; GPIO_InitStruct.Pull GPIO_NOPULL; HAL_GPIO_Init(GPIOA, GPIO_InitStruct); // 定时器初始化 MX_TIM3_Init(); }距离测量函数实现float Get_Distance(void) { uint32_t start_time 0, end_time 0; float distance 0; // 发送10μs触发脉冲 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); delay_us(10); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // 等待回波信号变高 while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) GPIO_PIN_RESET); // 启动定时器并记录开始时间 __HAL_TIM_SET_COUNTER(htim3, 0); HAL_TIM_Base_Start(htim3); // 等待回波信号变低 while(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2) GPIO_PIN_SET); // 停止定时器并获取时间 end_time __HAL_TIM_GET_COUNTER(htim3); HAL_TIM_Base_Stop(htim3); // 计算距离单位cm distance end_time / 58.0f; return distance; }OLED显示模块OLED显示部分采用SSD1306驱动芯片通过I2C接口通信。以下是关键显示函数// 在OLED上显示浮点数 void OLED_ShowFloat(uint8_t x, uint8_t y, float num, uint8_t width, uint8_t size) { char buffer[10]; sprintf(buffer, %.2f, num); OLED_ShowString(x, y, buffer, size); } // 主显示函数 void Update_Display(float distance) { OLED_Clear(); OLED_ShowString(0, 0, Distance:, 16); OLED_ShowFloat(0, 2, distance, 5, 16); OLED_ShowString(80, 2, cm, 16); OLED_Refresh(); }系统优化与调试技巧测量精度提升温度补偿// 带温度补偿的距离计算 float Get_Distance_With_Temp(float temperature) { float sound_speed 331.4f 0.6f * temperature; return (end_time * sound_speed) / 20000.0f; }数字滤波移动平均滤波中值滤波卡尔曼滤波常见问题解决测量值不稳定确保电源稳定建议在VCC和GND之间加100μF电容增加软件滤波算法避免测量表面过于光滑或吸音材料无回波信号检查Trig和Echo引脚连接确认模块供电电压为5V测试时保持测量距离在2cm以上OLED显示异常检查I2C地址通常0x78或0x7A确认上拉电阻4.7kΩ已正确连接验证初始化序列是否正确完整工程架构项目采用模块化设计主要文件结构如下├── Core/ │ ├── Src/ │ │ ├── main.c │ │ ├── stm32f1xx_hal_msp.c │ │ └── stm32f1xx_it.c │ └── Inc/ │ └── main.h ├── Drivers/ ├── HCSR04/ │ ├── Inc/ │ │ └── hcsr04.h │ └── Src/ │ └── hcsr04.c ├── OLED/ │ ├── Inc/ │ │ └── oled.h │ └── Src/ │ └── oled.c └── STM32F103C8T6_FLASH.ld关键函数调用关系main()初始化各外设主循环中调用Get_Distance()获取距离调用Update_Display()刷新OLED显示添加适当的延时建议100-200ms进阶应用扩展基于这个基础框架可以进一步扩展更多实用功能多传感器融合结合红外传感器提高短距离测量精度添加温度传感器实现自动补偿无线传输// 通过串口发送数据示例 printf(Distance: %.2f cm\r\n, distance);可扩展为蓝牙或Wi-Fi传输阈值报警功能if(distance 20.0f) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); // 点亮LED报警 } else { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); }低功耗优化间隔测量模式使用定时器唤醒代替延时关闭不必要的外设时钟