GD32F3x实战:用定时器输入捕获精准测量PWM频率与占空比(附完整代码)

发布时间:2026/5/22 13:38:37

GD32F3x实战:用定时器输入捕获精准测量PWM频率与占空比(附完整代码) GD32F3x实战高精度PWM频率与占空比测量全解析在嵌入式系统开发中PWM信号的精确测量是许多项目的基础需求。无论是电机控制、传感器数据采集还是电源管理准确获取PWM的频率和占空比信息都至关重要。本文将深入探讨如何利用GD32F3x系列微控制器的定时器输入捕获功能实现高精度的PWM参数测量。1. 输入捕获原理与硬件配置1.1 定时器输入捕获工作机制GD32F3x的定时器输入捕获功能通过检测外部信号的边沿变化来实现时间测量。其核心原理可以概括为边沿检测定时器通道可配置为上升沿、下降沿或双边沿触发时间戳记录当检测到指定边沿时当前定时器计数值被锁存到捕获寄存器中断触发捕获事件可触发中断便于及时处理测量数据关键寄存器TIMERx_CCRx捕获/比较寄存器存储边沿触发时的计数值TIMERx_CCER捕获/比较使能寄存器控制捕获极性TIMERx_SMCR从模式控制寄存器可用于复位计数器1.2 GD32F3x硬件连接指南对于PWM测量推荐使用以下硬件配置硬件要素推荐配置注意事项输入引脚具有定时器输入功能的GPIO需查阅芯片数据手册确认引脚复用功能信号电平3.3V兼容若信号源电压不同需添加电平转换电路滤波电路根据信号质量决定高频噪声较大时可添加RC低通滤波典型初始化代码示例void timer_input_capture_init(void) { rcu_periph_clock_enable(RCU_GPIOA); rcu_periph_clock_enable(RCU_TIMER2); /* 配置GPIO为浮空输入模式 */ gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_6); /* 定时器基础配置 */ timer_parameter_struct timer_initpara { .prescaler 120-1, // 1MHz时钟 .alignedmode TIMER_COUNTER_EDGE, .counterdirection TIMER_COUNTER_UP, .period 65535, // 16位计数器 .clockdivision TIMER_CKDIV_DIV1, .repetitioncounter 0 }; timer_init(TIMER2, timer_initpara); /* 输入捕获通道配置 */ timer_ic_parameter_struct timer_icpara { .icpolarity TIMER_IC_POLARITY_RISING, .icselection TIMER_IC_SELECTION_DIRECTTI, .icprescaler TIMER_IC_PSC_DIV1, .icfilter 0 }; timer_input_capture_config(TIMER2, TIMER_CH_0, timer_icpara); /* 使能中断 */ timer_interrupt_enable(TIMER2, TIMER_INT_UP | TIMER_INT_CH0); nvic_irq_enable(TIMER2_IRQn, 13, 0); timer_enable(TIMER2); }2. 测量算法与状态机设计2.1 频率与占空比计算原理PWM信号的关键参数测量基于时间间隔计算频率(F) 1 / 周期(T)占空比(D) 高电平时间(Th) / 周期(T) × 100%测量过程需要捕获三个关键时间点第一个上升沿T1随后的下降沿T2下一个上升沿T3计算关系Th T2 - T1 T T3 - T1 F 1 / (T × 定时器时钟周期) D (Th / T) × 100%2.2 四状态机实现方案为确保测量准确性我们采用四状态状态机stateDiagram [*] -- IDLE IDLE -- RISING_EDGE_1: 上升沿触发 RISING_EDGE_1 -- FALLING_EDGE: 下降沿触发 FALLING_EDGE -- RISING_EDGE_2: 上升沿触发 RISING_EDGE_2 -- DATA_READY: 数据就绪 DATA_READY -- IDLE: 数据处理完成对应代码实现enum capture_state { STATE_IDLE, // 初始状态 STATE_RISING_EDGE_1, // 捕获到第一个上升沿 STATE_FALLING_EDGE, // 捕获到下降沿 STATE_RISING_EDGE_2, // 捕获到第二个上升沿 STATE_DATA_READY // 数据就绪可计算 }; volatile struct { uint32_t rise1_count; uint32_t fall_count; uint32_t rise2_count; uint16_t overflow_count; enum capture_state state; } pwm_capture;3. 中断服务程序优化3.1 定时器溢出处理定时器溢出是精度测量的关键因素需在中断中准确记录void TIMER2_IRQHandler(void) { if(timer_interrupt_flag_get(TIMER2, TIMER_INT_FLAG_UP)) { pwm_capture.overflow_count; timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP); } if(timer_interrupt_flag_get(TIMER2, TIMER_INT_CH0)) { switch(pwm_capture.state) { case STATE_IDLE: // 初始化测量参数 pwm_capture.rise1_count 0; pwm_capture.fall_count 0; pwm_capture.rise2_count 0; pwm_capture.overflow_count 0; // 重置计数器并改变捕获极性 timer_disable(TIMER2); timer_counter_value_config(TIMER2, 0); timer_channel_input_capture_polarity_config(TIMER2, TIMER_CH_0, TIMER_IC_POLARITY_FALLING); timer_enable(TIMER2); pwm_capture.state STATE_RISING_EDGE_1; break; case STATE_RISING_EDGE_1: pwm_capture.rise1_count timer_channel_capture_value_register_read(TIMER2, TIMER_CH_0); timer_channel_input_capture_polarity_config(TIMER2, TIMER_CH_0, TIMER_IC_POLARITY_RISING); pwm_capture.state STATE_FALLING_EDGE; break; case STATE_FALLING_EDGE: pwm_capture.fall_count timer_channel_capture_value_register_read(TIMER2, TIMER_CH_0); pwm_capture.state STATE_RISING_EDGE_2; break; case STATE_RISING_EDGE_2: pwm_capture.rise2_count timer_channel_capture_value_register_read(TIMER2, TIMER_CH_0); pwm_capture.state STATE_DATA_READY; break; } timer_interrupt_flag_clear(TIMER2, TIMER_INT_CH0); } }3.2 测量精度提升技巧时钟源选择使用外部晶振可获得更高精度避免使用HSI内部时钟源预分频器优化// 计算最优预分频值 uint32_t timer_clock rcu_clock_freq_get(CK_TIMER); uint32_t desired_freq 1000000; // 1MHz uint16_t prescaler (timer_clock / desired_freq) - 1;数字滤波配置timer_ic_parameter_struct.icfilter 0x6; // 8个时钟周期的滤波4. 实际应用与性能优化4.1 动态范围扩展技术为适应不同频率范围的PWM信号可采用动态调整策略自动预分频调节算法void adjust_timer_prescaler(uint32_t measured_freq) { uint32_t new_prescaler; if(measured_freq 50000) { new_prescaler (system_clock / 10000000) - 1; // 10MHz } else if(measured_freq 5000) { new_prescaler (system_clock / 1000000) - 1; // 1MHz } else { new_prescaler (system_clock / 100000) - 1; // 100kHz } timer_disable(TIMER2); timer_prescaler_config(TIMER2, new_prescaler, TIMER_PSC_RELOAD_NOW); timer_enable(TIMER2); }多定时器协作方案使用TIMER2测量高频率信号使用TIMER5测量低频率信号通过软件自动切换信号路由4.2 抗干扰处理策略工业环境中PWM信号常伴有噪声可采取以下措施硬件层面添加RC低通滤波典型值R1kΩ, C100nF使用施密特触发器整形信号软件层面#define SAMPLE_COUNT 5 uint32_t filter_measurements(uint32_t raw_values[], uint8_t count) { uint32_t sum 0; // 去掉最高和最低值 bubble_sort(raw_values, count); for(uint8_t i 1; i count - 1; i) { sum raw_values[i]; } return sum / (count - 2); }4.3 实时性能优化对于需要快速响应的应用可采取以下优化DMA传输捕获数据void setup_capture_dma(void) { dma_parameter_struct dma_init_struct; dma_deinit(DMA0, DMA_CH0); dma_init_struct.direction DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.memory_addr (uint32_t)capture_buffer; dma_init_struct.memory_inc DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.memory_width DMA_MEMORY_WIDTH_16BIT; dma_init_struct.number BUFFER_SIZE; dma_init_struct.periph_addr (uint32_t)TIMER2_CH0CV; dma_init_struct.periph_inc DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.periph_width DMA_PERIPHERAL_WIDTH_16BIT; dma_init_struct.priority DMA_PRIORITY_HIGH; dma_init(DMA0, DMA_CH0, dma_init_struct); dma_circulation_enable(DMA0, DMA_CH0); timer_dma_enable(TIMER2, TIMER_DMA_CH0D); dma_channel_enable(DMA0, DMA_CH0); }双缓冲技术volatile uint32_t capture_buffer[2][BUFFER_SIZE]; volatile uint8_t active_buffer 0; void TIMER2_IRQHandler(void) { if(/* 缓冲区满中断 */) { active_buffer ^ 1; // 切换缓冲区 // 处理非活动缓冲区数据 } }5. 调试技巧与常见问题5.1 典型问题排查指南问题现象可能原因解决方案测量值不稳定信号噪声大增加硬件滤波或软件滤波频率测量值翻倍捕获状态机错误检查边沿触发极性设置占空比始终为0或100%只捕获到一种边沿验证GPIO引脚配置和信号连接测量值偏差大定时器时钟配置错误检查RCU时钟树配置5.2 调试工具推荐逻辑分析仪使用同时捕获PWM输入和MCU调试输出验证边沿触发时刻与计数器值的关系GD32虚拟串口调试void debug_printf(const char *fmt, ...) { va_list args; va_start(args, fmt); char buffer[128]; vsnprintf(buffer, sizeof(buffer), fmt, args); usart_data_transmit(USART0, (uint8_t *)buffer, strlen(buffer)); va_end(args); }实时变量监控// 在调试器中监控这些关键变量 volatile uint32_t debug_rise1 pwm_capture.rise1_count; volatile uint32_t debug_fall pwm_capture.fall_count; volatile uint32_t debug_rise2 pwm_capture.rise2_count;5.3 性能基准测试在不同时钟配置下的测量精度对比输入频率理论值实测值误差率1kHz1.000kHz1.002kHz0.2%10kHz10.00kHz9.98kHz-0.2%50kHz50.00kHz49.95kHz-0.1%100kHz100.0kHz99.8kHz-0.2%测试条件GD32F303 120MHz1MHz定时器时钟室温25℃

相关新闻