STM32F103C8T6实战用ETR外部时钟打造高精度红外计数器在工业自动化、智能仓储和流水线管理中物体计数是一个基础但关键的功能。传统方案往往依赖软件中断计数但在高速或高精度场景下容易丢失脉冲。STM32的ETRExternal Trigger外部时钟模式为解决这一问题提供了硬件级方案——本文将带你从电路设计到代码实现完成一个基于红外对射传感器的计数器系统。1. 为什么ETR模式更适合计数场景1.1 内部时钟的局限性当使用STM32内部时钟进行计数时通常需要这样处理红外信号// 传统中断计数方式示例 void EXTI0_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line0) ! RESET) { counter; EXTI_ClearITPendingBit(EXTI_Line0); } }这种方式存在三个明显缺陷CPU依赖性强每个脉冲都需要触发中断高频响应差超过1kHz的信号可能丢失功耗高持续唤醒内核影响低功耗设计1.2 ETR的硬件优势ETR模式通过定时器硬件直接处理外部信号零CPU干预计数由定时器硬件自动完成超高响应支持最高72MHz的输入信号经分频后灵活配置支持上升沿/下降沿触发、数字滤波实测对比在1MHz方波输入时中断方式丢失率90%而ETR模式可100%准确计数2. 硬件设计关键要点2.1 传感器选型与电路推荐使用槽型光电传感器如EE-SX670VCC(3.3V) | [R1] 10K | ----- PA0(ETR输入) | [传感器] | GND参数选择工作电压3.3V兼容输出类型数字输出OC门响应时间10μs2.2 ETR引脚配置原则STM32F103C8T6的ETR引脚对应关系定时器ETR引脚复用功能TIM1PA12TIM1_ETRTIM2PA0TIM2_ETRTIM3PD2TIM3_ETR(仅大容量)TIM4PE0TIM4_ETR(仅大容量)注意C8T6属于中等容量型号实际可用ETR引脚为PA0和PA123. 软件配置全流程3.1 初始化代码分解void TIM_ETR_Init(void) { // 1. 时钟使能 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 2. GPIO配置浮空输入模式 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); // 3. ETR模式配置 TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F); // 4. 时基单元配置 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; TIM_TimeBaseInitStruct.TIM_Period 0xFFFF; // 最大计数值 TIM_TimeBaseInitStruct.TIM_Prescaler 0; // 无分频 TIM_TimeBaseInitStruct.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseInitStruct.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_TimeBaseInitStruct); // 5. 使能计数器 TIM_Cmd(TIM2, ENABLE); }3.2 关键参数解析TIM_ExtTRGPolarityTIM_ExtTRGPolarity_NonInverted表示上升沿计数TIM_ExtTRGPolarity_Inverted表示下降沿计数ExtTRGFilter值0x0F表示最大滤波时间约240ns 72MHzPeriod设置技巧当需要统计超过65535的计数时可结合溢出中断void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_Update) ! RESET) { overflow_count; TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } }4. 高级应用技巧4.1 脉冲频率测量通过ETR模式可轻松实现频率计float Measure_Frequency(void) { uint32_t cnt1 TIM_GetCounter(TIM2); Delay_ms(1000); // 精确延时1秒 uint32_t cnt2 TIM_GetCounter(TIM2); return (cnt2 - cnt1) / 1.0; // 单位Hz }4.2 抗干扰设计工业环境中的噪声可能引发误计数推荐以下防护措施硬件滤波在ETR引脚添加100nF电容到地使用施密特触发器整形信号软件滤波TIM_ETRConfig(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);4.3 低功耗优化ETR模式配合STM32的睡眠模式可实现超低功耗计数void Enter_LowPowerMode(void) { // 配置唤醒事件 TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_External1); TIM_SelectInputTrigger(TIM2, TIM_TS_ETRF); // 进入停止模式 PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); }5. 实战包装流水线计数器某食品包装线需要统计每分钟的包装数量系统要求计数范围0-9999显示更新频率1Hz工作环境强电磁干扰实现方案typedef struct { uint16_t current_count; uint16_t last_minute_count; uint8_t update_flag; } Counter_TypeDef; Counter_TypeDef counter; void TIM2_IRQHandler(void) { if(TIM_GetITStatus(TIM2, TIM_IT_Update) ! RESET) { counter.current_count 65536; TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } } void SysTick_Handler(void) { static uint32_t ticks 0; if(ticks 1000) { ticks 0; counter.last_minute_count counter.current_count; counter.current_count 0; counter.update_flag 1; } }硬件连接注意事项传感器电源与MCU共地信号线使用双绞线传输在PA0与GND之间并联TVS二极管调试中发现当传送带空转时红外传感器可能产生抖动信号。最终通过以下配置解决TIM_ETRConfig(TIM2, TIM_ExtTRGPSC_DIV8, // 8分频 TIM_ExtTRGPolarity_NonInverted, 0x0F);