STM32F103C8T6最小系统板驱动HC-SR04超声波模块,从接线到串口打印距离的保姆级教程
STM32F103C8T6最小系统板驱动HC-SR04超声波模块实战指南在电子设计竞赛和嵌入式开发学习中STM32F103C8T6最小系统板因其高性价比和丰富资源成为学生群体的首选。本文将完整展示如何用这块蓝色小药丸驱动HC-SR04超声波模块从硬件连接到软件实现最终通过串口实时显示距离数据。与动辄上百元的开发板不同这套方案总成本不足50元却能实现相同的测距功能。1. 硬件准备与电路连接1.1 器件选型要点核心控制器STM32F103C8T6最小系统板20-25元Cortex-M3内核72MHz主频64KB Flash 20KB SRAM37个GPIO实际可用约34个传感器模块HC-SR04超声波模块8-12元工作电压5V DC测量范围2cm-400cm精度3mm理论值注意虽然STM32F103C8T6工作电压为3.3V但HC-SR04的Echo信号经过电平转换可直接接入实测稳定可靠。1.2 接线方案对比下表展示三种常用连接方式连接方式Trig引脚Echo引脚VCCGND特点标准接法PA1PA05VGND需外部上拉中断优化PA8PB125VGND支持外部中断串口复用PA9PA105VGND与串口1共用推荐采用中断优化方案具体接线如下HC-SR04 STM32F103C8T6 VCC → 5V引脚 Trig → PA8 (推挽输出) Echo → PB12 (浮空输入) GND → GND2. 开发环境搭建2.1 工具链配置IDE选择Keil MDK-ARM需注册STM32CubeIDE免费PlatformIO VSCode推荐跨平台库支持# PlatformIO环境依赖 [env:bluepill_f103c8] platform ststm32 board bluepill_f103c8 framework stm32cube lib_deps stm32duino/STM32duino FreeRTOS10.4.42.2 工程创建步骤以STM32CubeMX为例选择MCU型号STM32F103C8Tx配置时钟树72MHz HCLK开启外设GPIO: PA8(OUT), PB12(IN)USART1(115200 baud)TIM2(基本定时器)生成代码前勾选Generate peripheral initialization as a pair of .c/.h files3. 核心代码实现3.1 定时器配置定时器用于精确测量Echo高电平持续时间// tim.c void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig {0}; TIM_MasterConfigTypeDef sMasterConfig {0}; htim2.Instance TIM2; htim2.Init.Prescaler 71; // 1MHz计数频率 htim2.Init.CounterMode TIM_COUNTERMODE_UP; htim2.Init.Period 0xFFFF; 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.2 外部中断处理PB12配置为上升沿触发中断// gpio.c void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin GPIO_PIN_12){ if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_12)){ HAL_TIM_Base_Start(htim2); __HAL_TIM_SET_COUNTER(htim2, 0); } else { uint32_t pulse __HAL_TIM_GET_COUNTER(htim2); HAL_TIM_Base_Stop(htim2); float distance pulse * 0.034 / 2; // 单位cm printf(Distance: %.2fcm\r\n, distance); } } }3.3 主循环逻辑触发信号生成与测量控制// main.c while (1) { // 产生10us触发脉冲 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); delay_us(15); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); // 间隔60ms以上防止回波干扰 HAL_Delay(100); }4. 调试技巧与性能优化4.1 常见问题排查无回波信号检查Trig脉冲宽度是否≥10us确认VCC供电≥4.5V测量模块电流正常约15mA距离数据跳变# 简易滤波算法示例 def median_filter(values): sorted_values sorted(values) length len(sorted_values) return sorted_values[length//2] distances [get_distance() for _ in range(5)] stable_distance median_filter(distances)4.2 精度提升方案温度补偿公式声速 331.4 0.6 × 温度(℃) 0.0124 × 湿度(%)使用TIM输入捕获模式替代外部中断定时器组合将GPIO配置为50MHz高速模式4.3 功耗优化当需要电池供电时void enter_low_power_mode() { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); HAL_SuspendTick(); HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); SystemClock_Config(); // 唤醒后重新配置时钟 }5. 扩展应用实例5.1 多模块级联方案通过74HC138译码器控制多个HC-SR04void select_sensor(uint8_t num) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, (num0)1); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, (num1)1); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, (num2)1); }5.2 与OLED显示集成使用I2C接口的SSD1306显示实时距离void show_distance(float dist) { char buf[16]; sprintf(buf, %.1fcm, dist); SSD1306_GotoXY(0, 0); SSD1306_Puts(buf, Font_11x18, 1); SSD1306_UpdateScreen(); }5.3 阈值报警功能当距离小于设定值时触发蜂鸣器if(distance SAFE_DISTANCE){ HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET); printf(!WARNING! Too close: %.1fcm\r\n, distance); } else { HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET); }