STM32F103C8T6最小系统板驱动HC-SR04超声波模块,从接线到串口打印距离的保姆级教程
STM32F103C8T6最小系统板驱动HC-SR04超声波模块实战指南
在电子设计竞赛和嵌入式开发学习中,STM32F103C8T6最小系统板因其高性价比和丰富资源成为学生群体的首选。本文将完整展示如何用这块"蓝色小药丸"驱动HC-SR04超声波模块,从硬件连接到软件实现,最终通过串口实时显示距离数据。与动辄上百元的开发板不同,这套方案总成本不足50元,却能实现相同的测距功能。
1. 硬件准备与电路连接
1.1 器件选型要点
- 核心控制器:STM32F103C8T6最小系统板(20-25元)
- Cortex-M3内核,72MHz主频
- 64KB Flash + 20KB SRAM
- 37个GPIO(实际可用约34个)
- 传感器模块:HC-SR04超声波模块(8-12元)
- 工作电压:5V DC
- 测量范围:2cm-400cm
- 精度:3mm(理论值)
注意:虽然STM32F103C8T6工作电压为3.3V,但HC-SR04的Echo信号经过电平转换可直接接入,实测稳定可靠。
1.2 接线方案对比
下表展示三种常用连接方式:
| 连接方式 | Trig引脚 | Echo引脚 | VCC | GND | 特点 |
|---|---|---|---|---|---|
| 标准接法 | PA1 | PA0 | 5V | GND | 需外部上拉 |
| 中断优化 | PA8 | PB12 | 5V | GND | 支持外部中断 |
| 串口复用 | PA9 | PA10 | 5V | GND | 与串口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 FreeRTOS@10.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 files"
3. 核心代码实现
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-SR04:
void select_sensor(uint8_t num) { HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, (num>>0)&1); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, (num>>1)&1); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, (num>>2)&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); }