30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度1. 先搞清楚输入捕获到底能测什么频率范围STM32C552的定时器输入捕获功能最直接的价值就是能精确测量外部信号的频率和占空比。但很多人一上来就卡在为什么测不准这个问题上其实关键不是代码写错而是没搞清楚输入捕获的测量边界。输入捕获测量频率的核心原理很简单通过捕获信号边沿上升沿/下降沿的时间戳计算两个边沿之间的时间差。但这个时间差能测多宽的范围完全取决于定时器的计数频率和计数器位数。以STM32C552的TIM15为例如果系统时钟是144MHz预分频设置为143那么定时器的实际计数频率就是1MHz每个计数代表1微秒。16位计数器的最大值是65535所以单次能测量的最大周期就是65.535毫秒对应最低频率约15.26Hz。这意味着如果你想测量10Hz以下的低频信号直接使用16位计数器就会遇到溢出问题。反过来如果要测量100kHz以上的高频信号1MHz的计数频率可能分辨率不够误差会比较大。所以第一步不是急着写代码而是先算清楚你要测的信号频率范围是多少在这个范围内定时器配置能不能覆盖如果信号频率过低是否需要处理计数器溢出如果信号频率过高是否需要提高定时器计数频率2. TIM15输入捕获的硬件连接和CubeMX配置实际接线时最容易出错的就是信号路径。很多人以为随便找个GPIO接上就能测其实输入捕获通道有固定的引脚映射。TIM15_CH1对应PA2引脚但有些封装可能映射到其他引脚。在开始之前一定要查数据手册确认具体的引脚分配。CubeMX配置时这几个参数最容易设置错误2.1 时钟树配置先确认TIM15的输入时钟频率。如果系统时钟配置为144MHz那么TIM15的时钟通常也是144MHz除非APB总线有分频。这个基础频率直接影响后续所有计算。2.2 定时器基本参数在TIM15配置界面Prescaler预分频器决定定时器的计数频率Counter Period自动重装载值设置计数器的最大值Clock Division时钟分频通常保持默认值1Auto-reload preload自动重载预装载建议使能避免更新时产生毛刺关键计算// 假设系统时钟144MHz想要1MHz计数频率 TIM15_PSC (144000000 / 1000000) - 1 143 TIM15_ARR 0xFFFF // 16位最大值2.3 输入捕获通道配置在TIM15的Channel1配置中Mode选择Input Capture direct modeIC Selection选择DirectIC Polarity这是关键如果要同时测量频率和占空比选择Rising and Falling EdgeIC Prescaler选择No division每个边沿都捕获IC Filter根据信号质量选择信号干净时选择No Filter极性选择的重要性Rising Edge Only只捕获上升沿只能测频率Falling Edge Only只捕获下降沿同样只能测频率Rising and Falling Edge同时捕获上升沿和下降沿能同时测频率和占空比2.4 NVIC中断配置必须开启TIM15全局中断否则捕获事件无法触发中断回调函数。在NVIC配置中使能TIM15 global interrupt并设置合适的优先级。3. 输入捕获的核心代码实现配置完成后代码部分需要处理几个关键环节初始化、中断回调、数据计算和溢出处理。3.1 定时器初始化和启动// 定时器参数配置函数 hal_status_t TIM15_IC_Config(uint32_t psc, uint32_t arr) { hal_tim_handle_t* htim15 mx_tim15_gethandle(); if (htim15 NULL) return HAL_ERROR; // 设置预分频器 if (HAL_TIM_SetPrescaler(htim15, psc) ! HAL_OK) return HAL_ERROR; // 设置自动重装载值 if (HAL_TIM_SetPeriod(htim15, arr) ! HAL_OK) return HAL_ERROR; // 计数器清零 if (HAL_TIM_SetCounter(htim15, 0) ! HAL_OK) return HAL_ERROR; return HAL_OK; } // 启动输入捕获 hal_status_t TIM15_IC_Start(void) { hal_tim_handle_t* htim15 mx_tim15_gethandle(); if (htim15 NULL) return HAL_ERROR; // 启动通道1的输入捕获中断 if (HAL_TIM_IC_StartChannel_IT(htim15, HAL_TIM_CHANNEL_1) ! HAL_OK) return HAL_ERROR; // 启动定时器计数器 if (HAL_TIM_Start(htim15) ! HAL_OK) return HAL_ERROR; return HAL_OK; }3.2 计数器溢出处理16位计数器最大到65535就会归零所以两次捕获值相减时必须考虑溢出情况static uint32_t TIM15_GetDiff(uint32_t start, uint32_t end) { if (end start) { return end - start; // 正常情况直接相减 } else { return (0xFFFF 1 - start) end; // 发生溢出分段计算 } }这个函数是测量准确性的关键。如果没有溢出处理当信号周期超过65.535ms时计算结果会完全错误。3.3 输入捕获中断回调函数这是最核心的逻辑部分需要区分上升沿和下降沿并计算周期和占空比// 全局变量定义 static volatile uint32_t last_rise 0; // 上一次上升沿捕获值 static volatile uint32_t current_rise 0; // 当前上升沿捕获值 static volatile uint32_t current_fall 0; // 当前下降沿捕获值 static volatile uint8_t rise_valid 0; // 上升沿有效标志 static volatile uint8_t fall_valid 0; // 下降沿有效标志 void HAL_TIM_IC_Callback(hal_tim_handle_t* htim, hal_tim_channel_t channel) { if ((htim ! mx_tim15_gethandle()) || (channel ! HAL_TIM_CHANNEL_1)) { return; // 确保是TIM15通道1的中断 } uint32_t capture_value HAL_TIM_ReadCapturedValue(htim, HAL_TIM_CHANNEL_1); uint32_t pin_level HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2); // 读取PA2当前电平 if (pin_level GPIO_PIN_SET) { // 当前为高电平说明刚发生上升沿 if (rise_valid 0) { last_rise capture_value; // 第一次上升沿只记录不计算 rise_valid 1; fall_valid 0; } else { current_rise capture_value; // 计算周期上升沿到上升沿 uint32_t period TIM15_GetDiff(last_rise, current_rise); if ((period ! 0) (fall_valid ! 0)) { // 计算高电平时间上升沿到下降沿 uint32_t high_time TIM15_GetDiff(last_rise, current_fall); if (high_time period) { // 计算频率和占空比 uint32_t freq 1000000 / period; // 1MHz计数频率单位Hz uint32_t duty (high_time * 100) / period; // 占空比百分比 // 更新测量结果需要加中断保护 __disable_irq(); measured_freq freq; measured_duty duty; measurement_ready 1; __enable_irq(); } } last_rise current_rise; fall_valid 0; } } else { // 当前为低电平说明刚发生下降沿 if (rise_valid ! 0) { current_fall capture_value; fall_valid 1; } } }3.4 主循环中的数据处理在主循环中需要安全地读取测量结果while (1) { if (measurement_ready) { uint32_t freq, duty; // 关中断读取变量避免数据不一致 __disable_irq(); measurement_ready 0; freq measured_freq; duty measured_duty; __enable_irq(); printf(频率: %lu Hz, 占空比: %lu%%\r\n, freq, duty); HAL_Delay(1000); // 每秒打印一次 } }4. 实际测量中的精度问题和优化方案即使代码完全正确实际测量时还是会有误差。这些误差主要来自几个方面4.1 时钟精度误差STM32的内部RC振荡器精度大约在1%左右如果对频率测量精度要求高建议使用外部晶振。外部晶振的精度通常可以达到10-50ppm比内部RC振荡器高两个数量级。4.2 量化误差这是数字测量的固有误差。比如1MHz的计数频率每个计数代表1微秒那么测量结果的最小分辨率就是1微秒。对于1kHz的信号周期1ms量化误差最大可达0.1%。降低量化误差的方法提高定时器计数频率减小预分频值测量多个周期求平均值使用更高位的计数器有些STM32型号有32位定时器4.3 信号边沿抖动如果被测信号有噪声边沿检测会有抖动导致测量结果不稳定。解决方法在CubeMX中配置输入滤波Input Filter软件上多次测量取平均值硬件上增加RC滤波电路4.4 中断响应延迟中断响应和处理需要时间这会影响高频率信号的测量精度。优化建议中断服务函数尽量简洁使用DMA传输捕获值如果支持对于高频信号考虑使用定时器的编码器模式或其他专用测量方式5. 不同频率范围的配置建议根据你要测量的频率范围需要调整定时器配置5.1 低频信号测量1Hz-100Hz对于低频信号最大的问题是计数器溢出。解决方案// 降低计数频率扩展测量范围 #define TIM15_PSC 1439 // 计数频率100kHz #define TIM15_ARR 0xFFFF // 此时每个计数代表10微秒 // 最大可测量周期65535 * 10us 0.65535秒 → 最低频率1.53Hz5.2 中频信号测量100Hz-10kHz这是输入捕获最擅长的范围使用1MHz计数频率#define TIM15_PSC 143 // 计数频率1MHz #define TIM15_ARR 0xFFFF // 每个计数1微秒适合测量周期100us-10ms的信号5.3 高频信号测量10kHz-100kHz高频信号需要更高的计数频率以减少量化误差#define TIM15_PSC 71 // 计数频率2MHz #define TIM15_ARR 0xFFFF // 每个计数0.5微秒提高分辨率5.4 超高频信号100kHz以上对于100kHz以上的信号输入捕获可能不是最佳选择因为中断响应时间成为瓶颈量化误差相对较大系统负担较重替代方案使用定时器的PWM输入模式专门测量高频PWM使用外部计数器和定时器配合考虑使用频率计数器芯片6. 常见问题排查指南当测量结果不正常时按这个顺序排查6.1 完全无输出检查硬件连接信号源是否正常工作接线是否正确信号→PA2地线→GND用示波器确认信号是否到达STM32引脚检查CubeMX配置TIM15时钟是否使能GPIO是否正确配置为复用功能NVIC中断是否使能输入捕获通道配置是否正确检查代码初始化定时器参数配置函数是否调用输入捕获启动函数是否调用主循环中是否处理测量结果6.2 测量值不稳定信号质量问题检查信号是否有噪声尝试增加输入滤波器确认信号幅度符合STM32要求0-3.3V代码逻辑问题检查溢出处理函数是否正确确认边沿判断逻辑检查变量是否使用volatile修饰系统负载问题确认没有其他高优先级中断影响检查是否在中断中进行了复杂操作6.3 测量值有固定偏差时钟精度问题检查系统时钟配置考虑使用外部晶振校准时钟频率计算公式问题确认计数频率计算正确检查预分频值设置验证频率计算公式6.4 只能测频率不能测占空比极性配置问题确认CubeMX中设置为Rising and Falling Edge检查代码中的边沿判断逻辑下降沿捕获问题确认下降沿也能进入中断检查下降沿处理代码是否执行7. 进阶应用多通道测量和自动量程掌握了单通道测量后可以进一步扩展功能7.1 多通道同时测量TIM15有多个输入捕获通道可以同时测量多个信号// 启动多个通道 HAL_TIM_IC_StartChannel_IT(htim15, HAL_TIM_CHANNEL_1); HAL_TIM_IC_StartChannel_IT(htim15, HAL_TIM_CHANNEL_2); // 在回调函数中区分通道 void HAL_TIM_IC_Callback(hal_tim_handle_t* htim, hal_tim_channel_t channel) { switch (channel) { case HAL_TIM_CHANNEL_1: // 处理通道1 break; case HAL_TIM_CHANNEL_2: // 处理通道2 break; } }7.2 自动量程功能对于未知频率的信号可以实现自动量程// 先快速测量大致频率 uint32_t quick_measure_freq(void) { // 使用高计数频率快速测量 TIM15_IC_Config(71, 0xFFFF); // 2MHz // 测量几个周期 // 返回大致频率 } // 根据大致频率选择最优配置 void auto_range_config(uint32_t approx_freq) { if (approx_freq 100) { TIM15_IC_Config(1439, 0xFFFF); // 100kHz适合低频 } else if (approx_freq 10000) { TIM15_IC_Config(143, 0xFFFF); // 1MHz适合中频 } else { TIM15_IC_Config(71, 0xFFFF); // 2MHz适合高频 } }7.3 使用DMA减少CPU负担对于需要连续测量的应用可以使用DMA自动传输捕获值// 启动输入捕获DMA模式 HAL_TIM_IC_Start_DMA(htim15, HAL_TIM_CHANNEL_1, buffer, buffer_size); // DMA传输完成回调函数 void HAL_TIM_IC_CaptureCallback(hal_tim_handle_t* htim) { // 处理DMA缓冲区中的数据 }输入捕获功能真正落地时最该关注的不是代码能不能编译通过而是测量结果的稳定性和准确性。建议先用信号发生器产生已知频率的信号进行验证确认测量系统工作正常后再接入实际信号。对于长期使用的应用还要考虑异常情况的处理比如信号丢失、频率突变等情况确保系统在各种条件下都能稳定工作。 30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度
STM32C552定时器输入捕获:频率与占空比精确测量实战指南
30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度1. 先搞清楚输入捕获到底能测什么频率范围STM32C552的定时器输入捕获功能最直接的价值就是能精确测量外部信号的频率和占空比。但很多人一上来就卡在为什么测不准这个问题上其实关键不是代码写错而是没搞清楚输入捕获的测量边界。输入捕获测量频率的核心原理很简单通过捕获信号边沿上升沿/下降沿的时间戳计算两个边沿之间的时间差。但这个时间差能测多宽的范围完全取决于定时器的计数频率和计数器位数。以STM32C552的TIM15为例如果系统时钟是144MHz预分频设置为143那么定时器的实际计数频率就是1MHz每个计数代表1微秒。16位计数器的最大值是65535所以单次能测量的最大周期就是65.535毫秒对应最低频率约15.26Hz。这意味着如果你想测量10Hz以下的低频信号直接使用16位计数器就会遇到溢出问题。反过来如果要测量100kHz以上的高频信号1MHz的计数频率可能分辨率不够误差会比较大。所以第一步不是急着写代码而是先算清楚你要测的信号频率范围是多少在这个范围内定时器配置能不能覆盖如果信号频率过低是否需要处理计数器溢出如果信号频率过高是否需要提高定时器计数频率2. TIM15输入捕获的硬件连接和CubeMX配置实际接线时最容易出错的就是信号路径。很多人以为随便找个GPIO接上就能测其实输入捕获通道有固定的引脚映射。TIM15_CH1对应PA2引脚但有些封装可能映射到其他引脚。在开始之前一定要查数据手册确认具体的引脚分配。CubeMX配置时这几个参数最容易设置错误2.1 时钟树配置先确认TIM15的输入时钟频率。如果系统时钟配置为144MHz那么TIM15的时钟通常也是144MHz除非APB总线有分频。这个基础频率直接影响后续所有计算。2.2 定时器基本参数在TIM15配置界面Prescaler预分频器决定定时器的计数频率Counter Period自动重装载值设置计数器的最大值Clock Division时钟分频通常保持默认值1Auto-reload preload自动重载预装载建议使能避免更新时产生毛刺关键计算// 假设系统时钟144MHz想要1MHz计数频率 TIM15_PSC (144000000 / 1000000) - 1 143 TIM15_ARR 0xFFFF // 16位最大值2.3 输入捕获通道配置在TIM15的Channel1配置中Mode选择Input Capture direct modeIC Selection选择DirectIC Polarity这是关键如果要同时测量频率和占空比选择Rising and Falling EdgeIC Prescaler选择No division每个边沿都捕获IC Filter根据信号质量选择信号干净时选择No Filter极性选择的重要性Rising Edge Only只捕获上升沿只能测频率Falling Edge Only只捕获下降沿同样只能测频率Rising and Falling Edge同时捕获上升沿和下降沿能同时测频率和占空比2.4 NVIC中断配置必须开启TIM15全局中断否则捕获事件无法触发中断回调函数。在NVIC配置中使能TIM15 global interrupt并设置合适的优先级。3. 输入捕获的核心代码实现配置完成后代码部分需要处理几个关键环节初始化、中断回调、数据计算和溢出处理。3.1 定时器初始化和启动// 定时器参数配置函数 hal_status_t TIM15_IC_Config(uint32_t psc, uint32_t arr) { hal_tim_handle_t* htim15 mx_tim15_gethandle(); if (htim15 NULL) return HAL_ERROR; // 设置预分频器 if (HAL_TIM_SetPrescaler(htim15, psc) ! HAL_OK) return HAL_ERROR; // 设置自动重装载值 if (HAL_TIM_SetPeriod(htim15, arr) ! HAL_OK) return HAL_ERROR; // 计数器清零 if (HAL_TIM_SetCounter(htim15, 0) ! HAL_OK) return HAL_ERROR; return HAL_OK; } // 启动输入捕获 hal_status_t TIM15_IC_Start(void) { hal_tim_handle_t* htim15 mx_tim15_gethandle(); if (htim15 NULL) return HAL_ERROR; // 启动通道1的输入捕获中断 if (HAL_TIM_IC_StartChannel_IT(htim15, HAL_TIM_CHANNEL_1) ! HAL_OK) return HAL_ERROR; // 启动定时器计数器 if (HAL_TIM_Start(htim15) ! HAL_OK) return HAL_ERROR; return HAL_OK; }3.2 计数器溢出处理16位计数器最大到65535就会归零所以两次捕获值相减时必须考虑溢出情况static uint32_t TIM15_GetDiff(uint32_t start, uint32_t end) { if (end start) { return end - start; // 正常情况直接相减 } else { return (0xFFFF 1 - start) end; // 发生溢出分段计算 } }这个函数是测量准确性的关键。如果没有溢出处理当信号周期超过65.535ms时计算结果会完全错误。3.3 输入捕获中断回调函数这是最核心的逻辑部分需要区分上升沿和下降沿并计算周期和占空比// 全局变量定义 static volatile uint32_t last_rise 0; // 上一次上升沿捕获值 static volatile uint32_t current_rise 0; // 当前上升沿捕获值 static volatile uint32_t current_fall 0; // 当前下降沿捕获值 static volatile uint8_t rise_valid 0; // 上升沿有效标志 static volatile uint8_t fall_valid 0; // 下降沿有效标志 void HAL_TIM_IC_Callback(hal_tim_handle_t* htim, hal_tim_channel_t channel) { if ((htim ! mx_tim15_gethandle()) || (channel ! HAL_TIM_CHANNEL_1)) { return; // 确保是TIM15通道1的中断 } uint32_t capture_value HAL_TIM_ReadCapturedValue(htim, HAL_TIM_CHANNEL_1); uint32_t pin_level HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2); // 读取PA2当前电平 if (pin_level GPIO_PIN_SET) { // 当前为高电平说明刚发生上升沿 if (rise_valid 0) { last_rise capture_value; // 第一次上升沿只记录不计算 rise_valid 1; fall_valid 0; } else { current_rise capture_value; // 计算周期上升沿到上升沿 uint32_t period TIM15_GetDiff(last_rise, current_rise); if ((period ! 0) (fall_valid ! 0)) { // 计算高电平时间上升沿到下降沿 uint32_t high_time TIM15_GetDiff(last_rise, current_fall); if (high_time period) { // 计算频率和占空比 uint32_t freq 1000000 / period; // 1MHz计数频率单位Hz uint32_t duty (high_time * 100) / period; // 占空比百分比 // 更新测量结果需要加中断保护 __disable_irq(); measured_freq freq; measured_duty duty; measurement_ready 1; __enable_irq(); } } last_rise current_rise; fall_valid 0; } } else { // 当前为低电平说明刚发生下降沿 if (rise_valid ! 0) { current_fall capture_value; fall_valid 1; } } }3.4 主循环中的数据处理在主循环中需要安全地读取测量结果while (1) { if (measurement_ready) { uint32_t freq, duty; // 关中断读取变量避免数据不一致 __disable_irq(); measurement_ready 0; freq measured_freq; duty measured_duty; __enable_irq(); printf(频率: %lu Hz, 占空比: %lu%%\r\n, freq, duty); HAL_Delay(1000); // 每秒打印一次 } }4. 实际测量中的精度问题和优化方案即使代码完全正确实际测量时还是会有误差。这些误差主要来自几个方面4.1 时钟精度误差STM32的内部RC振荡器精度大约在1%左右如果对频率测量精度要求高建议使用外部晶振。外部晶振的精度通常可以达到10-50ppm比内部RC振荡器高两个数量级。4.2 量化误差这是数字测量的固有误差。比如1MHz的计数频率每个计数代表1微秒那么测量结果的最小分辨率就是1微秒。对于1kHz的信号周期1ms量化误差最大可达0.1%。降低量化误差的方法提高定时器计数频率减小预分频值测量多个周期求平均值使用更高位的计数器有些STM32型号有32位定时器4.3 信号边沿抖动如果被测信号有噪声边沿检测会有抖动导致测量结果不稳定。解决方法在CubeMX中配置输入滤波Input Filter软件上多次测量取平均值硬件上增加RC滤波电路4.4 中断响应延迟中断响应和处理需要时间这会影响高频率信号的测量精度。优化建议中断服务函数尽量简洁使用DMA传输捕获值如果支持对于高频信号考虑使用定时器的编码器模式或其他专用测量方式5. 不同频率范围的配置建议根据你要测量的频率范围需要调整定时器配置5.1 低频信号测量1Hz-100Hz对于低频信号最大的问题是计数器溢出。解决方案// 降低计数频率扩展测量范围 #define TIM15_PSC 1439 // 计数频率100kHz #define TIM15_ARR 0xFFFF // 此时每个计数代表10微秒 // 最大可测量周期65535 * 10us 0.65535秒 → 最低频率1.53Hz5.2 中频信号测量100Hz-10kHz这是输入捕获最擅长的范围使用1MHz计数频率#define TIM15_PSC 143 // 计数频率1MHz #define TIM15_ARR 0xFFFF // 每个计数1微秒适合测量周期100us-10ms的信号5.3 高频信号测量10kHz-100kHz高频信号需要更高的计数频率以减少量化误差#define TIM15_PSC 71 // 计数频率2MHz #define TIM15_ARR 0xFFFF // 每个计数0.5微秒提高分辨率5.4 超高频信号100kHz以上对于100kHz以上的信号输入捕获可能不是最佳选择因为中断响应时间成为瓶颈量化误差相对较大系统负担较重替代方案使用定时器的PWM输入模式专门测量高频PWM使用外部计数器和定时器配合考虑使用频率计数器芯片6. 常见问题排查指南当测量结果不正常时按这个顺序排查6.1 完全无输出检查硬件连接信号源是否正常工作接线是否正确信号→PA2地线→GND用示波器确认信号是否到达STM32引脚检查CubeMX配置TIM15时钟是否使能GPIO是否正确配置为复用功能NVIC中断是否使能输入捕获通道配置是否正确检查代码初始化定时器参数配置函数是否调用输入捕获启动函数是否调用主循环中是否处理测量结果6.2 测量值不稳定信号质量问题检查信号是否有噪声尝试增加输入滤波器确认信号幅度符合STM32要求0-3.3V代码逻辑问题检查溢出处理函数是否正确确认边沿判断逻辑检查变量是否使用volatile修饰系统负载问题确认没有其他高优先级中断影响检查是否在中断中进行了复杂操作6.3 测量值有固定偏差时钟精度问题检查系统时钟配置考虑使用外部晶振校准时钟频率计算公式问题确认计数频率计算正确检查预分频值设置验证频率计算公式6.4 只能测频率不能测占空比极性配置问题确认CubeMX中设置为Rising and Falling Edge检查代码中的边沿判断逻辑下降沿捕获问题确认下降沿也能进入中断检查下降沿处理代码是否执行7. 进阶应用多通道测量和自动量程掌握了单通道测量后可以进一步扩展功能7.1 多通道同时测量TIM15有多个输入捕获通道可以同时测量多个信号// 启动多个通道 HAL_TIM_IC_StartChannel_IT(htim15, HAL_TIM_CHANNEL_1); HAL_TIM_IC_StartChannel_IT(htim15, HAL_TIM_CHANNEL_2); // 在回调函数中区分通道 void HAL_TIM_IC_Callback(hal_tim_handle_t* htim, hal_tim_channel_t channel) { switch (channel) { case HAL_TIM_CHANNEL_1: // 处理通道1 break; case HAL_TIM_CHANNEL_2: // 处理通道2 break; } }7.2 自动量程功能对于未知频率的信号可以实现自动量程// 先快速测量大致频率 uint32_t quick_measure_freq(void) { // 使用高计数频率快速测量 TIM15_IC_Config(71, 0xFFFF); // 2MHz // 测量几个周期 // 返回大致频率 } // 根据大致频率选择最优配置 void auto_range_config(uint32_t approx_freq) { if (approx_freq 100) { TIM15_IC_Config(1439, 0xFFFF); // 100kHz适合低频 } else if (approx_freq 10000) { TIM15_IC_Config(143, 0xFFFF); // 1MHz适合中频 } else { TIM15_IC_Config(71, 0xFFFF); // 2MHz适合高频 } }7.3 使用DMA减少CPU负担对于需要连续测量的应用可以使用DMA自动传输捕获值// 启动输入捕获DMA模式 HAL_TIM_IC_Start_DMA(htim15, HAL_TIM_CHANNEL_1, buffer, buffer_size); // DMA传输完成回调函数 void HAL_TIM_IC_CaptureCallback(hal_tim_handle_t* htim) { // 处理DMA缓冲区中的数据 }输入捕获功能真正落地时最该关注的不是代码能不能编译通过而是测量结果的稳定性和准确性。建议先用信号发生器产生已知频率的信号进行验证确认测量系统工作正常后再接入实际信号。对于长期使用的应用还要考虑异常情况的处理比如信号丢失、频率突变等情况确保系统在各种条件下都能稳定工作。 30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度