news 2026/4/14 7:15:45

从零开始:STM32定时器输入捕获与超声波测距的实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零开始:STM32定时器输入捕获与超声波测距的实战指南

STM32定时器输入捕获与超声波测距实战指南

超声波测距技术因其成本低廉、实现简单且精度适中,在智能小车避障、机器人定位、液位检测等领域广泛应用。本文将深入讲解如何利用STM32的定时器输入捕获功能驱动HC-SR04超声波模块实现高精度距离测量。

1. 超声波测距原理与硬件连接

HC-SR04超声波模块通过发射超声波并接收其反射信号来测量距离。模块包含四个引脚:

  • VCC:5V电源输入
  • GND:接地
  • Trig:触发信号输入
  • Echo:回波信号输出

测距原理如下:

  1. STM32向Trig引脚发送至少10μs的高电平脉冲
  2. 模块自动发射8个40kHz的超声波脉冲
  3. 超声波遇到障碍物反射后被模块接收
  4. 模块通过Echo引脚输出高电平,持续时间与距离成正比

距离计算公式:

距离(cm) = (高电平时间(μs) × 0.0343) / 2

硬件连接示例:

Trig引脚 --- PA0 (通用输出) Echo引脚 --- PA1 (定时器输入捕获通道) VCC --- 5V GND --- GND

2. STM32定时器输入捕获配置

输入捕获是测量脉冲宽度的关键技术。我们以TIM2为例,配置输入捕获功能:

void TIM2_Cap_Init(u16 arr, u16 psc) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_ICInitTypeDef TIM2_ICInitStructure; NVIC_InitTypeDef NVIC_InitStructure; // 使能时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 配置GPIO GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 输入下拉 GPIO_Init(GPIOA, &GPIO_InitStructure); // 定时器基础配置 TIM_TimeBaseStructure.TIM_Period = arr; TIM_TimeBaseStructure.TIM_Prescaler = psc; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // 输入捕获配置 TIM2_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM2_ICInitStructure.TIM_ICFilter = 0x00; TIM_ICInit(TIM2, &TIM2_ICInitStructure); // 中断配置 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); TIM_ITConfig(TIM2, TIM_IT_Update|TIM_IT_CC2, ENABLE); TIM_Cmd(TIM2, ENABLE); }

关键参数说明:

参数说明典型值
arr自动重装载值65535
psc预分频系数71 (1MHz计数频率)
TIM_ICPolarity捕获极性初始设为上升沿
TIM_ICFilter输入滤波器0表示不滤波

3. 中断服务函数实现

中断服务函数需要处理定时器溢出和捕获事件,准确计算高电平持续时间:

volatile u8 TIM2CH1_CAPTURE_STA = 0; // 状态标志 volatile u16 TIM2CH1_CAPTURE_VAL; // 捕获值 void TIM2_IRQHandler(void) { if((TIM2CH1_CAPTURE_STA & 0X80) == 0) { // 未完成捕获 if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { // 溢出中断 if(TIM2CH1_CAPTURE_STA & 0X40) { // 已捕获到高电平 if((TIM2CH1_CAPTURE_STA & 0X3F) == 0X3F) { // 高电平过长 TIM2CH1_CAPTURE_STA |= 0X80; // 标记完成 TIM2CH1_CAPTURE_VAL = 0XFFFF; } else { TIM2CH1_CAPTURE_STA++; } } } if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET) { // 捕获中断 if(TIM2CH1_CAPTURE_STA & 0X40) { // 下降沿 TIM2CH1_CAPTURE_STA |= 0X80; // 标记完成 TIM2CH1_CAPTURE_VAL = TIM_GetCapture2(TIM2); TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Rising); // 重置为上升沿 } else { // 上升沿 TIM2CH1_CAPTURE_STA = 0; TIM2CH1_CAPTURE_VAL = 0; TIM_SetCounter(TIM2, 0); TIM2CH1_CAPTURE_STA |= 0X40; // 标记捕获到上升沿 TIM_OC2PolarityConfig(TIM2, TIM_ICPolarity_Falling); // 设为下降沿 } } } TIM_ClearITPendingBit(TIM2, TIM_IT_CC2|TIM_IT_Update); }

状态标志TIM2CH1_CAPTURE_STA的位定义:

  • 位7:捕获完成标志
  • 位6:已捕获到上升沿标志
  • 位0-5:溢出计数器

4. 距离计算与温度补偿

完成高电平时间测量后,可计算实际距离并考虑温度补偿:

float Get_Distance(void) { float distance = 0; u32 time = 0; // 发送触发信号 GPIO_SetBits(GPIOA, GPIO_Pin_0); delay_us(20); GPIO_ResetBits(GPIOA, GPIO_Pin_0); // 等待捕获完成 while((TIM2CH1_CAPTURE_STA & 0X80) == 0); // 计算总时间 time = TIM2CH1_CAPTURE_STA & 0X3F; time *= 65536; // 溢出时间总和 time += TIM2CH1_CAPTURE_VAL; // 计算距离(25℃标准声速) distance = time * 0.0343 / 2; // 温度补偿(可选) // float temperature = Get_Temperature(); // 从温度传感器读取 // float sound_speed = 331.5 + 0.6 * temperature; // distance = (time * sound_speed / 10000) / 2; TIM2CH1_CAPTURE_STA = 0; // 准备下一次测量 return distance; }

温度对声速的影响:

温度(℃)声速(m/s)误差(100cm时)
0331.5+3.5cm
25343.0基准
50361.5-5.4cm

5. 实战优化与常见问题

5.1 测量稳定性优化

  1. 多次测量取平均:连续测量5次,去掉最大最小值后取平均
  2. 软件滤波:采用滑动窗口滤波或卡尔曼滤波算法
  3. 盲区处理:忽略2-4cm内的测量结果(超声波模块固有盲区)
#define SAMPLE_TIMES 5 float Get_Stable_Distance(void) { float distances[SAMPLE_TIMES]; float sum = 0; for(int i=0; i<SAMPLE_TIMES; i++) { distances[i] = Get_Distance(); delay_ms(100); // 两次测量间隔至少60ms } // 排序并去掉最大最小值 Bubble_Sort(distances, SAMPLE_TIMES); for(int i=1; i<SAMPLE_TIMES-1; i++) { sum += distances[i]; } return sum / (SAMPLE_TIMES-2); }

5.2 常见问题排查

问题现象可能原因解决方案
测量值恒为0Echo引脚未连接正确检查硬件连接
测量值波动大环境干扰或电源不稳添加软件滤波,检查电源
测量距离偏小温度补偿未启用添加温度传感器补偿
无法触发测量Trig脉冲宽度不足确保Trig脉冲≥10μs

5.3 扩展应用

结合STM32其他外设可实现更丰富的功能:

  1. LCD显示:实时显示测量距离
  2. 无线传输:通过蓝牙/WiFi上传数据
  3. 电机控制:根据距离自动调整电机速度
  4. 多传感器融合:结合红外、激光等传感器提高可靠性
// LCD显示示例 void Display_Distance(float distance) { char buf[20]; sprintf(buf, "Dist: %.1fcm", distance); LCD_DisplayString(0, 0, (u8*)buf); }

通过本指南的系统学习,开发者可以掌握STM32定时器输入捕获的核心技术,并灵活应用于各种超声波测距场景。实际项目中,建议结合具体需求优化测量算法和硬件设计,以获得最佳性能。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/9 18:06:57

Nunchaku FLUX.1 CustomV3实战:手把手教你生成惊艳插画

Nunchaku FLUX.1 CustomV3实战&#xff1a;手把手教你生成惊艳插画 你有没有试过输入一句话&#xff0c;几秒钟后就得到一张堪比专业插画师手绘的高清作品&#xff1f;不是概念图&#xff0c;不是草稿&#xff0c;而是细节饱满、光影自然、风格统一的完整插画——人物发丝根根…

作者头像 李华
网站建设 2026/4/10 6:10:47

3个超实用技巧!用ncmdump实现格式转换自由

3个超实用技巧&#xff01;用ncmdump实现格式转换自由 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 你是否曾因下载的音乐文件格式受限而无法跨设备播放&#xff1f;ncmdump格式转换工具正是解决这一痛点的理想选择&#xff0c;它…

作者头像 李华
网站建设 2026/4/10 14:32:07

校园竞赛管理系统设计计算机毕设(源码+lw+部署文档+讲解等)

博主介绍&#xff1a;✌ 专注于VUE,小程序&#xff0c;安卓&#xff0c;Java,python,物联网专业&#xff0c;有18年开发经验&#xff0c;长年从事毕业指导&#xff0c;项目实战✌选取一个适合的毕业设计题目很重要。✌关注✌私信我✌具体的问题&#xff0c;我会尽力帮助你。一、…

作者头像 李华
网站建设 2026/4/8 22:41:31

Nano-Banana拆解引擎:轻松搞定产品部件展示与标注

Nano-Banana拆解引擎&#xff1a;轻松搞定产品部件展示与标注 Datawhale干货 教程作者&#xff1a;林工&#xff0c;某消费电子品牌结构设计组 你有没有遇到过这些场景&#xff1f; 新品发布会前一周&#xff0c;市场部催着要10套不同角度的产品爆炸图&#xff0c;而结构工…

作者头像 李华
网站建设 2026/4/13 23:52:03

规避EMI:Altium Designer布局布线的抗干扰思路

以下是对您提供的博文《规避EMI:Altium Designer布局布线的抗干扰思路——面向高可靠性功率电子系统的工程实践分析》所进行的 深度润色与专业重构 。本次优化严格遵循您的全部要求: ✅ 彻底去除AI痕迹,语言自然、老练、有工程师现场感; ✅ 摒弃“引言/核心知识点/应用…

作者头像 李华
网站建设 2026/4/11 11:33:33

零样本语音克隆真能行?GLM-TTS真实体验分享

零样本语音克隆真能行&#xff1f;GLM-TTS真实体验分享 你有没有试过——只用一段3秒的录音&#xff0c;就让AI开口说出你完全没听过的话&#xff1f;不是调音效、不是拼接剪辑&#xff0c;而是从零开始“学”出一个人的声音&#xff0c;再用这个声音念任意文字&#xff1f;听…

作者头像 李华