小白也能看懂的 CW32F003 定时器时钟知识与计算手册
系统时钟是 “原始心跳”,预分频器是 “减速齿轮”,计数频率是 “实际工作心跳”,CNT 是 “当前读数”,ARR 是 “终点”。计算步骤:先选好算的计数频率→算 PSC(减 1)→算 ARR(减 1)。
·
一、开篇:定时器是什么?能做什么?
你可以把定时器想象成单片机里的「高精度智能秒表」,它是嵌入式开发里最常用的核心外设之一,能帮我们完成很多重要的工作:
- 基础定时:比如每隔 1 秒让 LED 闪一下,每隔 100 毫秒采集一次传感器数据。
- PWM 波形输出:比如做的 LED 呼吸灯(通过改变 PWM 占空比调节亮度)、电机调速、舵机控制。
- 外部信号测量:比如测量一个方波信号的频率、脉宽。
本文就结合CW32F003 GTIM 通用定时器、48MHz 系统时钟、1kHz PWM 呼吸灯 项目,用大白话 + 类比 + 图表,把定时器的时钟知识和计算方法讲得明明白白。
二、核心概念扫盲(配生活类比)
在开始计算之前,我们先把 4 个最核心的概念搞清楚,这是后面所有计算的基础。
1. 系统时钟(PCLK):芯片的「原始超快心跳」
- 定义:单片机给定时器提供的原始时钟信号,是定时器的 “动力来源”。
- CW32F003 默认值:48MHz(每秒跳 48,000,000 次,非常快!)。
2. 预分频系数(PSC 硬件值):给心跳「减速的齿轮」
3. 定时器计数频率(TCLK):计数器的「实际工作心跳」
- 定义:经过预分频器 “减速” 后,计数器 CNT 每秒钟自动加多少次,单位是 Hz(次 / 秒)。
- 生活类比:就像体育老师的「高精度秒表」,如果计数频率是 1MHz,就是每秒 “滴答” 1,000,000 次,每 1 微秒(μs)走 1 格。
- CW32F003 常用值:我们一般会把它设成1MHz(1μs 加 1 次),因为这样算 ARR 的时候特别方便,不用算小数。
4. 三个核心寄存器:PSC/CNT/ARR
这三个寄存器是定时器的 “心脏”,对应 GTIM 功能框图上半部分,用一个表格 + 一个简单的信号流向图来说明:
表格
| 寄存器名称 | 英文全称 | 核心作用 | 生活类比(秒表) |
|---|---|---|---|
| PSC | Prescaler | 预分频器寄存器,存储「预分频系数 - 1」的值 | 秒表的 “模式切换键”,切换秒针走的速度 |
| CNT | Counter | 当前计数值寄存器,自动从 0 开始往上加 | 秒表的 “当前读数指针” |
| ARR | Auto-Reload Register | 自动重装载值寄存器,存储计数的 “终点值”,CNT 数到这里会自动清零 | 秒表的 “倒计时终点”,到了就自动重置 |
定时器信号流向图(必看!):

graph LR
A[系统时钟<br/>PCLK<br/>48MHz] --> B[预分频器<br/>PSC寄存器<br/>减速]
B --> C[定时器计数频率<br/>TCLK<br/>比如1MHz]
C --> D[计数器<br/>CNT<br/>自动+1]
E[重装载寄存器<br/>ARR<br/>存储终点值] --> D
D -->|数到ARR就清零| D
D --> F[溢出事件<br/>触发PWM输出/中断]
三、万能公式推导(一步步来,小白也能推)
我们的目标是:已知系统时钟频率和目标 PWM 频率,算出 PSC 寄存器值和 ARR 寄存器值。
第一步:推导「预分频系数」和「PSC 寄存器值」
我们的思路是:先把高频的系统时钟,分频成一个好算的整数计数频率(比如 1MHz、10MHz),方便后面算 ARR。
- 预分频系数的公式:预分频系数的作用是 “把系统时钟分成 N 份取 1 份”,所以:预分频系数系统时钟频率你想要的定时器计数频率
- PSC 寄存器值的公式(关键!为什么要减 1?):这里是新手最容易踩坑的地方,我们结合硬件设计解释:
- 单片机的 PSC 寄存器是从 0 开始编号的(就像数组的下标从 0 开始,楼层的 0 层)。
- 当你给 PSC 写
0时,硬件实际是1分频(不分频)。 - 当你给 PSC 写
1时,硬件实际是2分频。 - 所以:PSC 寄存器值 = 预分频系数 - 1
第二步:推导「ARR 寄存器值」
现在我们有了好算的定时器计数频率,接下来算 ARR,决定最终的 PWM 频率。
- PWM 周期的公式:PWM 周期就是 CNT 从 0 数到 ARR 再回到 0 的总时间,CNT 每加 1 次的时间是
1/定时器计数频率,一共要加ARR+1次(因为从 0 到 ARR 是 ARR+1 个数),所以:周期定时器计数频率 - PWM 频率的公式:频率是周期的倒数(1 秒有多少个周期),所以:频率定时器计数频率
- ARR 寄存器值的公式(变形一下):我们把上面的公式变形,已知目标 PWM 频率,求 ARR:寄存器值定时器计数频率目标频率
四、实战计算演练
已知条件
- 系统时钟(PCLK):48MHz(CW32F003 默认)
- 目标 PWM 频率:1kHz(周期 1ms,呼吸灯用)
- 我们选的「好算的定时器计数频率」:1MHz(1μs 加 1 次)
计算过程(一步步来)
第一部分:算 PSC(预分频器)
- 算预分频系数:预分频系数
- 算 PSC 寄存器值(别忘了减 1!):寄存器值
- 对应你的代码:
GTIM_InitStruct.Prescaler = GTIM_PRESCALER_DIV48; // 库函数宏,本质就是写47
第二部分:算 ARR(自动重装载值)
- 算 ARR 寄存器值:寄存器值
- 对应你的代码:
GTIM_InitStruct.ReloadValue = 999;
第三部分:验证一下(确保没错)
我们把算出来的 PSC 和 ARR 代回 PWM 频率公式,验证一下:频率完美!完全符合我们的需求!
五、额外补充:占空比怎么算?(CCR 寄存器)
做呼吸灯还用到了 CCR 比较寄存器,,非常简单:
- CCR 作用:决定 PWM 的「高电平时间」或「低电平时间」。
- 占空比公式:占空比寄存器值寄存器值
- 对应你的项目(50% 占空比):寄存器值
- 对应你的代码:
GTIM_SetCompare4(500);
六、结合 GTIM 功能框图,再加深理解
我们把之前讲的所有概念,对应到CW32F003 GTIM 功能框图上,你就能彻底看懂硬件是怎么工作的了:
- 时钟来源:框图左上角的
PCLK就是系统时钟(48MHz),通过选择器进入预分频器。 - 预分频器:框图里写着「/1, …, /32768」的模块,由
CR0.PRS控制,对应我们算的 PSC。 - 核心计数器:框图中间的「16 位计数器 CNT」,自动从 0 开始加,对应我们的 CNT 寄存器。
- 重装载寄存器:框图里的「重载寄存器 ARR」,给 CNT 设终点,对应我们的 ARR 寄存器。
- PWM 输出通道:框图最下面的「CH4 捕获比较」和「输出控制」模块,对应我们的 CCR 寄存器和 PC02 引脚输出。

七、常见问题与避坑指南(小白必看)
1. 坑点一:PSC 寄存器值忘记减 1
- 现象:PWM 频率是预期的一半,或者完全不对。
- 解决:永远记住
PSC寄存器值 = 预分频系数 - 1。
2. 坑点二:GPIO 引脚没有设为复用推挽输出
- 现象:代码配置都对,但 PC02 引脚没有 PWM 波形输出,灯不亮。
- 解决:必须把 GPIO 设为
GPIO_MODE_AF_PP(复用推挽输出),普通推挽输出是连不上定时器的。
3. 坑点三:PWM 极性和 LED 接线不匹配
- 现象:灯常亮或者常灭,不会呼吸。
- 解决:灌电流接法(LED 负极接 PC02)设为低电平有效,拉电流接法设为高电平有效。
八、总结与快速查表
1. 一句话总结
- 系统时钟是 “原始心跳”,预分频器是 “减速齿轮”,计数频率是 “实际工作心跳”,CNT 是 “当前读数”,ARR 是 “终点”。
- 计算步骤:先选好算的计数频率→算 PSC(减 1)→算 ARR(减 1)。
2. 快速计算表(CW32F003 48MHz 系统时钟)
表格
| 目标 PWM 频率 | 推荐计数频率 | 预分频系数 | PSC 寄存器值 | ARR 寄存器值 |
|---|---|---|---|---|
| 1kHz | 1MHz | 48 | 47 | 999 |
| 2kHz | 1MHz | 48 | 47 | 499 |
| 5kHz | 1MHz | 48 | 47 | 199 |
| 10kHz | 1MHz | 48 | 47 | 99 |
| 100Hz | 48kHz | 1000 | 999 | 479 |
更多推荐



所有评论(0)