一、3个容易混的概念
定时器是对已知频率的时钟信号计数,用来实现定时、延时或事件计数,分硬件模块和软件机制两类。
时钟是产生稳定周期性振荡信号的电路,像节拍器,为数字电路提供同步时序基准。
RTC 是实时时钟,主电源关掉后仍能提供日历和时间信息,和定时器不是一回事。
二、时钟是怎么来的
一条时钟链路要经过四类器件:
- 晶振,把石英晶体切成音叉状,加电压后产生稳定振荡。板上的 osc_clk 是 24MHz。
- PLL 锁相环,负责倍频。24MHz 的晶振跑不动 528MHz 的核,靠 PLL 把频率乘上去。
- Prescaler 分频器,把高速时钟降下来给慢速外设用。
- PFD 相位分数分频器,输出频率可升可降,i.MX6ULL 里有 528 PLL 和 480 PLL 两组,分别对应两个 PLL 输出。
三、ARM PLL 的配置流程
把 ARM 核从 24MHz 拉到 528MHz,顺序不能错,否则会跑飞。
- 先选 osc_clk,让 step_clk 为 24MHz。
- 把 PLL1 的输出切换到 step_clk,让 ARM 暂时降频到 24MHz 运行。
- 配置 PLL1 倍频到 1056,也就是 528 的两倍。
- 配置完成后,再把时钟源切回 pll1_main_clk。
第三步有个大坑:设置倍频因子之前,必须先把 PLL 之后的二分频配好,否则中间那一刻核会跑到 1056MHz,超出额定频率,直接故障。
所以改时钟的通则是先降频到安全区,改完参数再升回去,这个顺序在任何芯片上都适用。
四、三类总线时钟
PLL 出来之后,还要经过几个选择器和分频器,才变成外设真正用的时钟。
AHB_CLK_ROOT 是 132MHz,看 CBCMR 的 PRE_PERIPH_CLK_SEL、CBCDR 的 PERIPH_CLK_SEL 和 AHB_PODF 三个位。
IPG_CLK_ROOT 是 66MHz,看 CBCDR 的 IPG_PODF。
PERCLK_CLK_ROOT 也是 66MHz,看 CSCMR1 的 PERCLK_CLK_SEL 和 PERCLK_PODF。
AHB 挂高速外设,IPG 是大多数片上外设的工作时钟,PERCLK 常给定时器用。写 EPIT、GPT 时算分频系数,用的就是这里查到的输入频率。
顺带记两个容易混的单位换算:频率是 1000 乘 1000 等于 1MHz,容量是 1024 乘 1024 等于 1MByte,一个十进制一个二进制。
五、EPIT 增强型周期中断定时器
EPIT 的特点是硬件自动重装,计数器减到 0 自动载入初值并产生中断,适合做周期性任务。
对比 51 单片机的定时器:51 是 8 位可自动重装,16 位要在中断服务程序里手动重装;EPIT 相当于把重装这件事做进了硬件。
典型实验是产生 1 秒中断,在中断服务函数里翻转 LED。流程还是老三样:查手册配置控制寄存器,设定时钟源、分频和工作模式;写装载寄存器定计数值;开中断并配置 GIC 使能对应中断号;最后在向量表里挂上服务函数。
六、GPT 通用目的定时器
GPT 除了定时,还支持输入捕获和比较输出,功能比 EPIT 更全,32 位计数器,可以向上或向下计数。
捕获是引脚上出现边沿时把当前计数值锁存下来,用来测脉宽、测频率。比较是计数值到达设定值时翻转输出引脚或触发中断,用来输出 PWM 波形。
实验里用自由运行模式做精准延时:让计数器一直跑,需要延时时读一次当前值,然后循环比较,直到差值达到目标。这比 while 空转准得多,因为它基于真实时钟频率,而不是指令周期估算。
重点总结
- 时钟链是晶振、PLL 倍频、分频器和 PFD 分频,缺一环都出不来目标频率。
- 改 PLL 必须按切到安全时钟、先配二分频、再改倍频、最后切回的顺序,顺序错了直接跑飞。
- AHB 132M、IPG 66M、PERCLK 66M 是三条常用总线时钟,算分频前先确认输入源。
- EPIT 硬件自动重装,适合周期中断;GPT 支持捕获和比较,适合测时和输出波形。
- 精准延时用 GPT 自由运行计数,不要再靠 while 空转。