news 2026/6/11 9:22:23

别再只会用内部时钟了!STM32F103C8T6定时器外部时钟ETR实战:用红外对射传感器做个简易计数器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再只会用内部时钟了!STM32F103C8T6定时器外部时钟ETR实战:用红外对射传感器做个简易计数器

STM32F103C8T6定时器外部时钟ETR实战:红外对射传感器构建高精度计数器

红外对射传感器在工业自动化、智能家居等领域有着广泛应用,而如何准确统计其触发次数往往是开发者面临的挑战。本文将带你深入探索STM32F103C8T6定时器的外部时钟模式(ETR),通过实战项目演示如何利用红外对射传感器构建一个高精度计数器。不同于传统的中断计数方式,ETR模式直接在硬件层面完成脉冲计数,不仅响应速度更快,还能有效减轻CPU负担。

1. 项目概述与硬件准备

红外对射传感器由发射器和接收器组成,当有物体通过时会遮挡红外线,导致接收器输出电平变化。这种特性使其成为理想的非接触式计数传感器。我们选择STM32F103C8T6的TIM2定时器,因其ETR引脚(PA0)与红外传感器输出可直接连接。

所需硬件组件:

  • STM32F103C8T6最小系统板
  • 红外对射传感器模块(如E18-D80NK)
  • 杜邦线若干
  • USB-TTL串口模块(用于调试输出)

接线示意图:

红外传感器OUT —— PA0 (TIM2_ETR) 红外传感器VCC —— 3.3V 红外传感器GND —— GND

传感器输出特性分析:

  • 常态输出高电平(无遮挡)
  • 遮挡时输出低电平
  • 每次遮挡/解除形成完整脉冲边沿

2. 定时器ETR模式核心原理

2.1 外部时钟模式2工作机制

ETR模式2允许外部信号直接驱动定时器计数器,完全绕过预分频器。其信号路径为:

ETR引脚 → 边沿检测 → 分频器(可选) → 计数器

关键配置参数:

  • TIM_ExtTRGPolarity:选择上升沿或下降沿触发
  • TIM_ExtTRGPrescaler:外部时钟预分频(1/2/4/8)
  • ExtTRGFilter:数字滤波器长度(0-15)

2.2 时基单元参数设计

在红外计数应用中,Period和Prescaler的组合决定了计数逻辑:

TIM_TimeBaseInitStruct.TIM_Period = 10-1; // 计数到9后溢出 TIM_TimeBaseInitStruct.TIM_Prescaler = 1-1; // 每个脉冲计数1次

这种配置表示:

  • 每1次传感器触发 → 计数器+1
  • 计数器达到9后 → 触发更新事件(中断)
  • 计数器自动归零

若设置Prescaler为N-1,则需N次触发才能使计数器+1,实现"每N次计数1"的效果。

3. 完整代码实现与解析

3.1 GPIO与定时器初始化

首先配置PA0为浮空输入模式,确保能准确捕获传感器信号:

void GPIO_Config(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); }

定时器ETR模式配置关键代码:

void TIM2_ETR_Config(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // ETR时钟模式2配置 TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F); // 时基单元设置 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_TimeBaseInitStruct.TIM_Period = 100-1; // 计数100次触发中断 TIM_TimeBaseInitStruct.TIM_Prescaler = 1-1; // 每个脉冲计数1次 TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct); // 中断配置 TIM_ClearFlag(TIM2, TIM_FLAG_Update); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); NVIC_EnableIRQ(TIM2_IRQn); TIM_Cmd(TIM2, ENABLE); }

3.2 中断服务程序实现

在中断中实现计数逻辑和串口输出:

volatile uint32_t totalCount = 0; // 全局累计计数 void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { totalCount += 100; // 每次中断代表100次触发 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 通过串口输出当前计数(需自行实现USART_Send函数) USART_Send(USART1, "Current count: "); USART_SendNum(USART1, totalCount); USART_Send(USART1, "\r\n"); } }

3.3 实时计数器读取函数

为方便调试,提供实时读取计数器的函数:

uint32_t Get_CurrentCount(void) { return totalCount + TIM_GetCounter(TIM2); }

4. 高级应用与性能优化

4.1 抗干扰设计策略

工业环境中存在各种干扰,可通过以下方式增强稳定性:

  1. 硬件滤波

    // 设置15个时钟周期的滤波 TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);
  2. 软件去抖

    • 在中断服务程序中添加时间戳检查
    • 设置最小触发间隔(如10ms)
  3. 信号调理电路

    • 在传感器输出端添加RC滤波
    • 使用施密特触发器整形信号

4.2 多传感器协同计数

通过级联多个定时器实现多通道计数:

定时器传感器引脚最大频率
TIM2传感器1PA036MHz
TIM3传感器2PA636MHz
TIM4传感器3PB636MHz

配置代码示例:

// 初始化TIM3和TIM4的ETR模式 TIM_ETRClockMode2Config(TIM3, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F); TIM_ETRClockMode2Config(TIM4, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);

4.3 超高频计数处理

当需要统计高频信号时(>1MHz),可采用以下优化:

  1. DMA直接内存访问

    // 配置DMA将计数器值定期传输到内存 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM2->CNT; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)countBuffer; DMA_InitStructure.DMA_BufferSize = 1024; DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  2. 输入捕获模式比较

    • ETR模式适合规则脉冲计数
    • 非规则脉冲建议使用输入捕获模式

性能对比表:

计数方式最高频率CPU占用适用场景
ETR模式36MHz规则脉冲
输入捕获1MHz非规则脉冲
外部中断100kHz低频非规则信号

5. 实际项目经验分享

在工业传送带项目中,我们使用ETR模式实现了以下优化:

  1. 参数动态调整技术

    // 根据传送带速度自动调整Prescaler void Adjust_Prescaler(uint16_t speed) { TIM_PrescalerConfig(TIM2, speed/100, TIM_PSCReloadMode_Immediate); }
  2. 零丢失计数方案

    • 在中断服务开始时立即读取计数器
    • 使用32位变量扩展计数范围
    • 添加看门狗定时器检测异常
  3. 功耗优化技巧

    • 在空闲时段关闭定时器时钟
    • 使用STOP模式+外部唤醒
    • 动态调整滤波器参数

常见问题解决:

若发现计数不准确,首先检查:

  1. 传感器输出波形是否干净
  2. GPIO模式是否正确设置为浮空输入
  3. 滤波器参数是否适合当前环境
  4. 电源稳定性是否达标

通过本项目的实践,我们成功将计数误差控制在0.001%以内,同时CPU占用率低于5%,显著提升了系统整体性能。这种方案特别适合需要长时间稳定运行的工业计数应用。

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

亚马逊员工现身西雅图市议会听证会,力挺暂停令政策

亚马逊员工力挺暂停令现身听证会在西雅图市议会的多场听证会上,出现了亚马逊员工的身影,他们和其他人一同为支持暂停令政策作证,是暂停令最坚定的支持者之一。编辑观点:亚马逊员工的支持或对暂停令政策推进有积极影响,…

作者头像 李华
网站建设 2026/6/11 9:22:18

边缘间隙异常引发量产故障汇总,教你看懂设计隐患

板材边缘间隙不足、间隙设计不合理,是 PCB 量产阶段排名靠前的工艺故障诱因。这类问题不会在实验室样机测试中集中爆发,却会在批量 SMT 生产、分板、整机装配、长期使用过程中陆续显现,故障现象多样、排查周期长,很多团队反复整改…

作者头像 李华
网站建设 2026/6/11 9:22:07

ArcGIS Pro二次开发小技巧:一键搞定Polyline闭合,告别手动描点

ArcGIS Pro二次开发实战:一键闭合Polyline的工程化解决方案在GIS数据处理流程中,线要素转面是高频操作,但往往被一个看似简单的条件卡住——Polyline必须闭合。许多从CAD导入或手动绘制的线要素,由于首尾点未闭合,导致…

作者头像 李华
网站建设 2026/6/11 9:21:59

别再被*U818骗了!C# CAD二次开发中,动态块的真实块名到底怎么拿?

破解C# CAD二次开发中的动态块命名迷局:从*U818到真实块名的终极指南在AutoCAD二次开发领域,动态块的处理一直是让开发者又爱又恨的话题。特别是当你在代码中满怀期待地调用BlockName属性,却得到一个莫名其妙的"*U818"时&#xff0…

作者头像 李华