ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

STM32C5A3R定时器输入捕获测频率:从原理到HAL库实现

STM32C5A3R定时器输入捕获测频率:从原理到HAL库实现 STM32C5A3R 是 STM32C5 系列中的一款 MCU基于 Arm Cortex-M33 内核面向新一轮的通用工业控制、电机控制和电力电子应用。在实际项目中测量外部脉冲信号的频率是很常见的需求电机测速、流量计脉冲采集、PWM 输入解析、传感器频率输出处理都会用到。实现频率测量有多种方案最稳定、最工程化的方式是使用定时器的输入捕获功能硬件在信号边沿到达时自动记录计数值软件在中断中读取并计算周期最终换算成频率。这篇文章围绕 STM32C5A3R 的定时器输入捕获从捕获原理、CubeMX 配置、HAL 库代码、频率计算、闭环验证到常见排错路径完整梳理一套可以复用的开发流程。无论你是在做电机转速采集还是在解析外部传感器脉冲都可以把这里的思路移植到自己的工程里。1. 先理解输入捕获测频率的核心原理1.1 什么是输入捕获它和外部中断有什么不同输入捕获Input Capture是指定时器在输入引脚检测到指定边沿跳变时自动把当前计数器的计数值保存到捕获寄存器中。这个动作由硬件完成不需要 CPU 介入也不需要软件在中断里读计数器。换句话说输入捕获的核心价值是“记录事件发生的精确时刻”。外部中断也可以感知信号跳变但两者解决的问题不同。外部中断只告诉你“这里有一个上升沿或者下降沿来了”它无法精确告诉你这个边沿发生在哪个计数时刻。如果你在中断里调用HAL_GetTick()或者去读定时器计数值中间已经有若干条指令的延迟测得的时间点就不准确。输入捕获把“检测边沿”和“记录时刻”合并成一个硬件动作边沿到达的同一个时钟周期内计数值就被锁存下来精度可以做到单个定时器时钟周期。这点在多路信号同步测量、高频 PWM 解析、电机转速计算这些场景中尤其重要。1.2 频率测量的数学基础两段上升沿之间有多少个计数单位测量频率最直接的方法不是直接数脉冲而是测量一个完整周期的时长第一次上升沿到来时硬件记录计数器值capture1。第二次上升沿到来时硬件记录计数器值capture2。如果计数器在这两个边沿之间没有溢出那么一个信号周期的时长为period_ticks capture2 - capture1如果定时器时钟频率是f_timer那么信号频率是f_signal f_timer / period_ticks举个例子。定时器时钟为 1 MHz输入信号是两个上升沿之间相差 1000 个计数单位那么信号频率就是 1 MHz / 1000 1 kHz。如果相差 500 个计数单位信号频率就是 1 MHz / 500 2 kHz。这里要特别注意计数器可能溢出。如果计数器从 0 计数到自动重装值 ARR再回到 0那么在两次捕获之间可能经历了若干次溢出。此时周期计算公式要变成period_ticks (capture2 - capture1) overflow_count * (ARR 1)这个overflow_count需要在溢出中断里累加。后面写代码时会重点处理。1.3 为什么不用轮询或 GPIO 翻转计数入门学习者最容易想到的方案有三种轮询 GPIO、外部中断计数、定时器输入捕获。它们的区别非常明显方案原理精度CPU 开销适用场景GPIO 轮询主循环反复读引脚电平检测跳变低受主循环周期影响高低频、低要求演示外部中断计数每次边沿进入中断用计数器变量累加中中断响应有延迟中只需计数、不关心精确相位定时器输入捕获硬件在边沿时刻锁存计数值高精确到定时器时钟周期低精确测量频率、周期、脉宽对测量频率来说输入捕获最大的优势是“边沿时刻由硬件固化”不依赖中断响应速度。只要你把定时器预分频和自动重装值配置合理频率测量的上限基本由定时器时钟决定软件只负责读取计算结果。2. 先确认芯片型号和工具链避免在错误环境里浪费调试时间2.1 STM32C5A3R 的型号含义和定位STM32C5A3R 属于 STM32C5 系列。从命名习惯上看“C5”是产品系列代号“A3”通常关联 Flash 容量和封装规格“R”通常代表引脚数量等级。不过具体含义在不同系列之间并不完全一致建议大家以 ST 官方数据手册中的 “Device ordering information” 表格为准。在动手配置定时器之前至少需要确认这几件事该型号是否包含你需要的定时器实例例如 TIM1、TIM2、TIM3、TIM4目标定时器的输入捕获通道映射到哪些 GPIO 引脚定时器内核时钟来自哪个时钟源APB1 还是 APB2最终频率是多少。这些信息在 STM32C5 系列参考手册Reference Manual和数据手册Datasheet中都能找到。不要凭 STM32F1 或 STM32F4 的经验直接套用引脚不同系列的引脚复用表差异很大。2.2 软件工具链和芯片支持包推荐使用 ST 官方工具链整体兼容性最好STM32CubeMX用于生成初始化代码和时钟树配置STM32CubeIDE用于编译、下载和调试也可以直接打开 CubeMX 生成的工程STM32CubeC5 固件包提供 STM32C5 系列的 HAL 驱动和例程串口终端工具用来观察频率打印结果例如 PuTTY、MobaXterm、SSCOM 等。注意如果你的 STM32CubeMX 里搜索不到 STM32C5A3R大概率是没有安装对应的芯片支持包。在 CubeMX 的 Help 菜单中选择 Manage embedded software packages安装 STM32CubeC5 支持包即可。不要用旧版本固件包强行套用否则代码生成可能不完整。2.3 硬件准备做输入捕获实验硬件上需要准备一块 STM32C5A3R 核心板或最小系统板ST-Link 或其它支持 STM32C5 的调试下载器USB 转串口模块用于查看打印信息信号源验证阶段可以直接用开发板另一个定时器输出 PWM杜邦线若干。有条件的话准备一台示波器。示波器不是必须的但它在排查“引脚没有波形”和“信号质量差”这两类问题时非常高效。2.4 学习环境与生产环境的差异学习阶段用内部 PWM 输出接一根杜邦线到捕获引脚就能完成闭环验证不需要外部信号发生器。生产环境要求则不同输入信号需要经过电阻分压、光耦隔离或电平转换确保不超出 GPIO 电压范围引脚附近需要加 RC 滤波或使用定时器的输入滤波功能避免毛刺误触发代码中要对捕获值做有效性判断不能盲目打印低频测量要考虑测量窗口时间高频测量要关注定时器溢出计数是否漏记。下面配置环节先按学习环境去做生产环境的强化措施放在最佳实践部分展开。3. 用 STM32CubeMX 完成定时器输入捕获配置3.1 新建工程并确认芯片打开 STM32CubeMX新建工程选择 MCU 型号搜索 STM32C5A3R。如果列表里能搜索到直接选中进入主界面如果搜索不到先安装芯片支持包再重新打开。进入主界面后第一件事不是配置定时器而是确认两个信息在 Pinout 视图左侧的 Categories 中找到并展开 TIM 相关外设确认当前芯片有哪些定时器实例打开 System Core - RCC配置 HSE 和 LSE。如果开发板没有外部晶振HSE 可以设置为 Crystal/Ceramic Resonator 或 bypass根据开发板原理图决定没有外部晶振时也可以直接用内部时钟。3.2 配置时钟树定时器时钟是后续计算的地基输入捕获测量的精度直接依赖定时器时钟频率。点击 Clock Configuration 标签页参考开发板实际晶振频率配置 PLL使 SYSCLK、APB1、APB2 处于合理工作状态。例如如果 APB1 定时器时钟经过倍频后为 80 MHz则定时器内核时钟为 80 MHz这意味着输入捕获的最小时间分辨率为 12.5 ns。如果你的板子实际频率不同后面代码里的换算系数需要对应调整。建议把时钟树截图保存下来因为后面写代码算频率时你需要知道 TIM2 的Kernel Clock到底是多大。CubeMX 里点击对应的定时器时钟域可以看到数值。3.3 配置定时器参数直接决定测量范围和精度选择 TIM2 作为输入捕获定时器。在 Pinout 视图点击 TIM2将其 Channel1 配置为 Input Capture direct mode。然后打开 Timers - TIM2 - Parameter Settings逐项确认参数配置示例说明Prescaler79定时器时钟分频80 MHz 分频 80 倍后计数时钟为 1 MHzCounter ModeUp向上计数模式Counter Period65535自动重装值决定溢出周期Internal Clock DivisionNo Division定时器内部时钟不分频auto-reload preloadEnable自动重装影子寄存器使能避免更新瞬间出错Trigger Slave ModeDisable不使用外部触发从模式Input Capture Filter00 表示不滤波实际项目按信号噪声设置这里解释一个关键设计Prescaler 79配合 80 MHz 定时器时钟得到 1 MHz 计数频率也就是每个计数单位等于 1 微秒。这样做的好处是频率和周期数字换算非常直观。如果你要测量的信号频率很高比如 10 MHz那么预分频必须降低否则计数器分辨率不足如果你要测很低频的信号比如 0.1 Hz那么预分频要增大或者利用溢出计数扩展测量范围。测量范围大致可以这样估算可测最高频率 ≈ 定时器时钟 / (PSC 1) / 2因为一个周期至少需要两个计数单位。实际还要扣除中断处理和代码开销通常保留 20% 以上裕量。3.4 配置中断优先级捕获中断和溢出中断都要开启在 NVIC Settings 页面中将 TIM2 global interrupt 设置为 Enable并按需调整优先级。输入捕获中断用于在边沿到达时读取捕获值溢出中断用于记录计数器翻转次数。两个中断共用一个 IRQ Handler分别由 HAL 库回调分发。中断优先级建议比主循环中的普通任务高但不要高于 SysTick 时基中断否则HAL_Delay()可能受干扰。如果系统里有更加严格的实时任务需要根据实际响应需求重新排优先级。3.5 生成工程并编译确认在 Project Manager 中设置工程名称、路径、IDE 为 STM32CubeIDE代码生成器选项建议选中 “Generate peripheral initialization as a pair of .c/.h files per peripheral”这样每个外设都有独立文件阅读和维护更清晰。生成代码后先编译一次确认没有编译错误再开始写应用代码。此时不要急着改硬件先把“裸工程能编译”作为第一个检查点。4. 编写 HAL 库输入捕获代码4.1 先理清两个中断回调别把逻辑写在错误位置HAL 库在stm32c5xx_it.c中把 TIM2 的 IRQHandler 做了一层分发。你不需要修改 IRQHandler只需要重写两个弱回调函数void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim); void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);前者在捕获事件发生时被调用后者在计数器溢出时被调用。两者的触发条件是独立的。4.2 全局变量结构记录边沿和溢出状态在main.c顶部或单独的用户代码区定义以下变量#define TIM2_IC_CLOCK_HZ 1000000UL /* 定时器计数时钟1 MHz */ volatile uint32_t g_capture_buf[2] {0, 0}; volatile uint8_t g_capture_index 0; volatile uint32_t g_overflow_cnt 0; volatile uint8_t g_measure_done 0; uint32_t g_period_ticks 0; double g_freq_hz 0.0;关键设计点g_capture_buf[2]保存相邻两次上升沿的捕获值g_capture_index指示当前保存第几次捕获g_overflow_cnt记录两次捕获之间发生的计数器溢出次数g_measure_done表示一次完整周期测量结束主循环可以进行计算。4.3 启动定时器捕获通道必须显式启动在main()函数的用户代码区加入HAL_TIM_IC_Start_IT(htim2, TIM_CHANNEL_1);这个函数做了两件事启动定时器计数并使能指定通道的捕获中断。只调用HAL_TIM_Base_Start_IT()不会开启捕获中断只调用HAL_TIM_IC_Start()也不会使能中断。这是新手最容易漏掉的一步。如果要同时处理溢出中断还需要确保定时器基础中断是开启的。这里直接使用同一个定时器实例HAL 在内部处理了对应关系的使能。4.4 捕获回调保存边沿时刻并在第二次边沿时完成周期计算void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2 htim-Channel HAL_TIM_ACTIVE_CHANNEL_1) { g_capture_buf[g_capture_index] HAL_TIM_ReadCapturedValue(htim2, TIM_CHANNEL_1); if (g_capture_index 0) { g_overflow_cnt 0; /* 第一次边沿清空溢出计数 */ g_capture_index 1; } else { g_capture_index 0; g_measure_done 1; /* 第二次边沿告诉主循环可以计算 */ } } }这里有一个需要说明的细节HAL_TIM_ReadCapturedValue()返回的是捕获寄存器 CCR 中的值不是当前计数器值。捕获寄存器是在硬件检测到边沿的那一刻被锁存的所以读取它得到的是“边沿对应的时刻”而不是“中断里读取的时刻”。这是输入捕获的精度来源。为了简化逻辑代码在第一次边沿时清零g_overflow_cnt。但严格来说边沿捕获时刻和溢出中断执行时刻之间存在微小的时间差极高频场景下可能出现一个周期内多次溢出的漏记。学习阶段这个代码足够使用提高精度的方法在排错章节补充。4.5 溢出回调记录计数器翻转次数void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2) { g_overflow_cnt; } }注意计数器从 ARR 回到 0 时触发更新事件此时会进入这个回调。g_overflow_cnt只有在第一次捕获清零后开始累加第二次捕获时停止累加所以它表示的是“两次边沿之间的完整溢出次数”。4.6 主循环计算频率并输出到串口while (1) { if (g_measure_done) { g_measure_done 0; uint32_t ticks 0; if (g_capture_buf[1] g_capture_buf[0]) { ticks g_capture_buf[1] - g_capture_buf[0]; } else { ticks (g_capture_buf[1] (htim2.Init.Period 1)) - g_capture_buf[0]; } ticks g_overflow_cnt * (htim2.Init.Period 1); if (ticks 0) { g_freq_hz (double)TIM2_IC_CLOCK_HZ / (double)ticks; printf(freq %.2f Hz, ticks %lu\r\n, g_freq_hz, (unsigned long)ticks); } g_overflow_cnt 0; g_capture_index 0; } }这里处理了两类情况capture_buf[1] capture_buf[0]第二次捕获发生在同一计数周期内没有经过溢出直接用差值。capture_buf[1] capture_buf[0]第二次捕获发生在计数器翻转之后需要加上(ARR 1)补偿。再加上g_overflow_cnt * (ARR 1)后ticks就是两个上升沿之间的完整计数单位数量。4.7 关键函数和参数速查表函数或参数作用常见误用HAL_TIM_IC_Start_IT启动定时器并开启捕获中断只启动定时器不启动捕获HAL_TIM_ReadCapturedValue读取捕获寄存器 CCR误以为读的是当前计数器值HAL_TIM_PeriodElapsedCallback溢出回调忘记判断定时器实例htim2.Init.Period自动重装值 ARR频率计算时漏加 ARR1g_overflow_cnt * (ARR 1)补偿溢出周期溢出计数和捕获计数不同步5. 用内部 PWM 输出作为信号源做闭环验证5.1 为什么建议先用内部 PWM 自测外部信号发生器在信号质量、输出电压范围上更可控但并非所有人手边都有。STM32 内部不同的定时器可以同时工作用 TIM1 输出 PWM用 TIM2 做输入捕获一根杜邦线就能完成闭环验证。这种自测方式的好处是你可以精确知道自己输出的 PWM 频率输入捕获测出的频率和输出频率对比立刻能判断配置和代码是否正常。5.2 在 CubeMX 中增加 TIM1 PWM 输出配置在 Pinout 视图中选择 TIM1 Channel1设置为 PWM Generation CH1。参数建议Prescaler79配合 80 MHz 时钟得到 1 MHzCounter Period999这样 PWM 频率为 1 MHz / 1000 1 kHzPulse500占空比 50%。在这个配置下TIM1 输出 1 kHz、50% 占空比的方波。具体引脚以 CubeMX 生成的 Pinout 为准。5.3 在 main 函数中启动 PWM并接线HAL_TIM_PWM_Start(htim1, TIM_CHANNEL_1);然后在硬件上把 TIM1_CH1 对应的引脚用杜邦线接到 TIM2_CH1 对应的引脚共地是必须的。如果两个引脚不在同一个连接器附近优先使用板上的 GND 引脚连接。5.4 预期结果和判定标准上述配置下串口应周期性打印freq 1000.00 Hz, ticks 1000ticks 1000说明两个上升沿之间计数到 1000 个单位和 1 kHz 完全对应。只要误差在 1 Hz 以内说明配置链路正确。接着验证几个关键场景测试场景修改方式预期结果提高频率减小 TIM1 Period 为 99输出约 10 kHz捕获应能测出降低频率增大 TIM1 Period 为 9999输出约 100 Hz周期 ticks 变大改变占空比修改 Pulse频率不应变化说明频率测量不受占空比影响拔掉杜邦线断开信号不再打印或进入超时处理这个验证过程覆盖了高频、低频、占空比变化和信号断开四类场景。5.5 频率不准时的校准思路如果测得频率和理论值有明显偏差应优先检查定时器时钟频率是否与代码中TIM2_IC_CLOCK_HZ一致。80 MHz 的配置下如果实际用的是 72 MHz测出的频率就会系统性偏高或偏低。校准方法查看 CubeMX 时钟树中 TIM2 的 Kernel Clock 实际值修改TIM2_IC_CLOCK_HZ宏为实际值用一段频率已知的信号复核。如果测量值在某个频率点突然跳变优先检查溢出计数是否漏记具体排查思路放在下一节。6. 频率不对、不打印、卡死从现象倒推原因6.1 捕获中断触发但频率始终为 0现象程序运行串口有输出但频率一直是 0.00 Hz。检查顺序确认信号确实到达捕获引脚用万用表或示波器查看引脚是否有电平跳变确认 CubeMX 中 TIM2_CH1 的引脚映射是否和实际接线一致确认HAL_TIM_IC_Start_IT(htim2, TIM_CHANNEL_1)是否在初始化之后被调用确认串口打印的数据类型格式化是否正确printf重定向是否完成。常见原因引脚映射错误或输入模式未使能。CubeMX 生成的MX_GPIO_Init()不会自动把复用功能配好定时器引脚的复用是在HAL_TIM_IC_Init()里完成的。如果手动改了引脚模式可能导致复用失效。6.2 频率正确但偶尔跳变现象大部分时间频率正确偶尔跳出异常大的值或异常小的值。可能原因捕获引脚存在毛刺边沿被多次触发溢出计数和捕获值不同步两个上升沿之间出现多次溢出但溢出中断被更高优先级中断长期抢占。处理方式在 CubeMX 中增大Input Capture Filter参数例如设置为 4 或 8让硬件过滤窄脉冲噪声软件上增加判断如果计算出的ticks明显偏离上一次值丢弃本次结果检查中断优先级配置避免长时间关中断或高优先级中断占用导致溢出中断丢失。6.3 高频信号测不准误差越来越大现象低频时测量准确频率升高后误差逐渐增大。原因分析高频信号意味着两个上升沿之间的ticks很小。如果ticks只有几十个单位定时器计数分辨率有限微小的延迟或噪声都会造成明显误差。另外中断回调执行期间的延迟虽然不会影响捕获值本身但会影响g_overflow_cnt的读取时机极端情况下会多算或少算一次溢出。改进建议降低预分频提高计数器分辨率如果信号频率超过一定范围考虑改用两个定时器通道的 PWM 输入模式在中断回调中先读捕获值再读溢出计数并在主循环中校验溢出计数是否合理。6.4 开启串口打印后卡死现象单独测量正常加入串口打印后程序运行变慢或卡死。常见原因printf重定向没有做好串口发送阻塞在等待标志位串口中断优先级和定时器中断优先级冲突导致死锁在中断回调中调用了printf串口阻塞导致中断无法退出。推荐做法中断回调中只保存捕获值和溢出计数不要做任何打印或延时。所有格式化输出放在主循环中完成。6.5 排错速查表问题现象优先检查项处理方式无任何捕获中断引脚复用、捕获中断使能检查 CubeMX 引脚和HAL_TIM_IC_Start_IT频率为 0信号是否到达、打印格式示波器测量引脚检查串口重定向频率跳变噪声、滤波参数打开 IC Filter软件丢弃异常值高频误差大预分频、溢出计数降低 PSC检查 ARR 与溢出补偿串口卡死串口重定向、中断嵌套打印移到主循环减少阻塞7. 再进一步用 PWM 输入模式同时测频率和占空比7.1 PWM 输入模式的原理前面用两个上升沿测量频率只能得到频率得不到占空比。如果既要频率又要占空比可以配置 PWM 输入模式。PWM 输入模式使用同一个定时器的两个捕获通道通道 1 捕获上升沿通道 2 捕获下降沿硬件上只需要一个外部引脚内部把两路捕获分别映射到同一个引脚。捕获寄存器 CCR1 记录周期长度CCR2 记录高电平宽度。对应关系如下频率 定时器时钟 / CCR1 占空比 CCR2 / CCR1 * 100%7.2 HAL 库中的 PWM 输入配置在 CubeMX 中将 TIM2 Channel1 配置为 Input Capture indirect modeChannel2 配置为 PWM input。实际连接外部信号的仍是 Channel1 的引脚。代码中启动方式HAL_TIM_PWM_Start_IT(htim2, TIM_CHANNEL_1); HAL_TIM_PWM_Start_IT(htim2, TIM_CHANNEL_2);在回调中读取void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2) { uint32_t period HAL_TIM_ReadCapturedValue(htim2, TIM_CHANNEL_1); uint32_t pulse HAL_TIM_ReadCapturedValue(htim2, TIM_CHANNEL_2); if (period 0) { g_duty (double)pulse / (double)period * 100.0; g_freq_hz (double)TIM2_IC_CLOCK_HZ / (double)period; } } }这种模式省去了手动判断下降沿和上升沿的软件逻辑占空比和周期由硬件同时捕获精度更高是工程中更推荐的做法。7.3 两种测量模式的选型建议需求推荐模式说明只测频率单通道输入捕获逻辑简单占用资源少同时测频率和占空比PWM 输入模式硬件同时捕获周期和脉宽多路信号同步测频多通道输入捕获加 DMA需要进一步处理 DMA 中断高频低占空比信号考虑外部时钟或高频定时器先确认定时器时钟上限8. 实践建议从能跑到可靠测量的差距在哪8.1 先按这个清单完成学习环境检查实际调试时很多问题并不是代码写错而是环境没有对齐。建议按顺序检查CubeMX 中的芯片型号是否确实为 STM32C5A3R时钟树中 TIM2 Kernel Clock 数值是否和代码宏一致捕获引脚是否映射到目标 GPIO且杜邦线连接正确输入信号的电压范围是否满足 GPIO 的电气规范HAL_TIM_IC_Start_IT是否在main中调用串口重定向是否可用波特率是否终端一致中断回调中是否只做简单赋值没有打印和延时。8.2 从开发板移到生产板之前需要补的功课学习环境的代码能跑通和生产环境稳定运行之间还有明显差距。进入生产环境前至少补上这些点输入信号前端增加限流电阻和钳位保护避免过压损坏 GPIO使用输入捕获滤波参数抑制毛刺不要依赖软件滤波溢出计数和捕获读取使用临界区保护或至少在主循环中做数据一致性校验增加超时机制如果长时间没有捕获中断需要给出告警而不是一直显示旧频率代码中不要用硬编码的TIM2_IC_CLOCK_HZ建议通过宏统一管理并注释来源准备好异常值过滤例如连续测量结果偏离超过 20% 时丢弃重测。8.3 最高频场景和低频场景要分别处理输入捕获没有一种参数能覆盖所有频率范围。高频信号需要减小预分频来提高分辨率低频信号需要增加计数器周期或依赖溢出计数。实际项目中应根据信号量级分组配置信号频率范围推荐做法1 Hz 以下加大 ARR依赖溢出计数测量时间窗口要足够长1 Hz - 100 kHzPSC 适中保证计数时钟为信号频率的百倍以上100 kHz 以上降低 PSC必要时使用带时钟分频的定时器或外部输入时钟模式一个实用经验计数时钟频率最好大于信号频率的 100 倍否则ticks数量太少百分之一的分辨率都难保证。8.4 下一步建议练习跑通单通道输入捕获后可以按这个顺序继续深入改成 PWM 输入模式同时输出频率和占空比用两个 GPIO 输入分别在 TIM2 和 TIM3 上做双路频率测量加入 DMA 批量读取捕获值降低中断频率把测量结果通过状态机封装成模块方便移植到其他 STM32 型号结合电机控制场景把测出的频率换算成转速并加入 PID 闭环。对新手来说最有价值的练习不是继续堆功能而是把现有代码完整地拆掉重写一遍。你会发现第二次写的时候对捕获时机、溢出补偿和中断职责的理解会完全不同。回头再看 STM32C5A3R 的参考手册中 TIM 章节很多原来跳过的细节都会变得清晰。
返回列表