一、定时器里有几个关键寄存器
┌─────────────────────────────────────────┐ │ TIM8 定时器 │ │ │ │ CNT ← 计数器:一直在跑,每 tick +1 │ │ ARR ← 自动重装值:CNT 到这里就归零 │ │ PSC ← 预分频器:决定 CNT 跑多快 │ │ │ │ CCR1 ← 捕获/比较寄存器 1 │ │ CCR2 ← 捕获/比较寄存器 2 │ │ CCR3 ← 捕获/比较寄存器 3 │ │ CCR4 ← 捕获/比较寄存器 4 │ │ │ └─────────────────────────────────────────┘CCR 不是用来计数的。计数的是 CNT。CCR 是一个锁存容器,用来在特定时刻"拍照"存下 CNT 的值。
二、CNT 和 CCR 的关系
你可以这样理解:
寄存器 | 类比 | 作用 |
CNT | 秒表的指针 | 一直在走,从 0 数到 65535 再归零,循环往复 |
CCR | 照相机 | 在信号边沿到来的瞬间,拍一张照片,把此刻 CNT 的值"冻"住存下来 |
ARR | 秒表的刻度上限 | CNT 数到这里就归零重新开始 |
所以 CCR 存的不是时间本身,而是边沿发生那一刻 CNT 的计数值。
三、我原本的理解
"定时器根据指定的周期测量通道的电平"
这个描述更像是定时采样/轮询——每隔一段时间去看一下引脚是高还是低。这跟输入捕获完全不同。
定时采样
定时器每隔 1ms 中断 → 中断里读 GPIO 电平 → 记录高/低问题:精度取决于采样频率,而且根本不知道边沿精确发生在哪个时刻。
输入捕获(实际的方式)
信号边沿自动触发 → 硬件瞬间把 CNT 值锁存到 CCR → 通知 CPUCPU 完全不需要轮询。是硬件在信号变化的那一瞬间自动完成的,零延迟,精度到 1 个时钟 tick。
四、输入捕获测 PWM 的完整原理
步骤图解
假设 50Hz PWM 信号(周期 20ms,高电平 1500μs):
信号: ┌──────────┐ ┌──────────┐ │ 高电平 │ 低电平 │ 高电平 │ ─────┘ 1500μs └──────────────────────────────┘ └──── ↑ ↑ 上升沿 下降沿CNT 在后台一直从 0 往上数:0, 1, 2, 3, ... 65535, 0, 1, 2, ...
① 上升沿到来时
信号: ────────┐ │ ↑ 上升沿!硬件自动把此刻的 CNT 值存到 CCR 此时 CNT = 8000 → CCR = 8000(拍了第一张照片)② 下降沿到来时
信号: │ │ └──────── 下降沿!硬件又自动存 CNT 到 CCR 此时 CNT = 9500 → CCR = 9500(拍了第二张照片)③ 软件做减法
脉宽 = 第二次 CCR - 第一次 CCR = 9500 - 8000 = 1500 因为 CNT 是 1MHz(1μs/tick),所以 1500 就是 1500μs ✅五、对应代码
在 rc_ch_isr 里:
// 上升沿来了:把"第一张照片"存起来 rc->rising_time = capture; // capture 就是此刻 CCR 的值(= CNT 的快照) rc->rising_valid = 1; // 切换为等下降沿 TIM_SET_CAPTUREPOLARITY(htim, channel, TIM_ICPOLARITY_FALLING); // ... // 下降沿来了:拿到"第二张照片",做减法 delta = capture - rc->rising_time; // 两张快照的差 = 高电平持续的 tick 数 = 微秒数这里的capture参数来自中断入口:
cap = HAL_TIM_ReadCapturedValue(&g_tim8_handle, TIM_CHANNEL_1); // ↑ 这个函数就是读 CCR1 寄存器的值所以整个流程是:
信号边沿 → 硬件自动 CCR = CNT → 触发中断 → 软件读 CCR → 做减法算脉宽六、"捕获"这个词到底什么意思?
捕获 = 捕获(Capture)CNT 的值。
不是捕获信号,不是捕获电平,而是在信号边沿的瞬间,把计数器的当前值"抓"下来存到 CCR 里。
这就像你在跑步比赛中,裁判在你经过终点线的瞬间按下秒表——他不是在"测量你的速度",而是在记录你到达的那一刻的时间。两次记录做差,就能算出你的速度。
七、一张图总结
信号引脚(PC6) │ │ 边沿检测器(硬件自动工作,不需要CPU参与) │ 检测到边沿? │ │ │ ├── YES → 立刻做 CCR = CNT(拍照) │ │ │ │ │ └── 触发中断通知CPU来取照片 │ │ │ └── NO → 什么都不做 │ CPU 收到中断 → 读 CCR → 做减法 → 得到脉宽(微秒)核心要点:边沿检测和锁存 CCR 都是硬件自动完成的,CPU 只在中断里读结果做减法,所以精度极高、CPU 占用极低。