EPIT 与 GPT定时器定时的实现
·
1. 什么是 EPIT 和 GPT?
在嵌入式系统,尤其是基于 i.MX6ULL 这类 ARM Cortex-A7 内核的处理器开发中,定时器是必不可少的资源。EPIT 和 GPT 是 i.MX6ULL 处理器内部集成的两个非常重要的通用定时器模块。

- EPIT (Enhanced Periodic Interrupt Timer):增强型周期中断定时器。顾名思义,它主要用于产生精确的周期性中断,非常适合用来实现系统心跳、任务调度、PWM 信号生成或精确延时等场景。

- GPT (General Purpose Timer):通用定时器。它的功能更为丰富,除了可以像 EPIT 一样产生周期性中断外,还支持输入捕获和输出比较功能,常用于测量脉冲宽度、频率或生成特定波形。
简单来说,EPIT 是一个专注于“定时中断”的专用定时器,而 GPT 则是一个功能更全面的“多面手”定时器。
2. EPIT 和 GPT 的位数与计数方向
这是一个非常关键的技术细节,直接关系到定时器的精度和用法。
- 位数:EPIT 和 GPT 都是 32 位 定时器。这意味着它们的计数器可以从 0 计数到 4,294,967,295(2^32 - 1),提供了非常长的定时范围。
- 计数方向:
- EPIT:是一个向下计数的定时器。它的工作原理是:将加载寄存器(
LR)的值加载到计数器,然后每个时钟周期计数器减 1,直到减到 0 或与比较寄存器(CMPR)的值相等时触发中断。 - GPT:在 Free-Run(自由运行)模式下,GPT 是一个向上计数的定时器。计数器从 0 开始,每个时钟周期加 1,直到达到最大值(0xFFFFFFFF)后溢出回 0,并可以触发溢出中断。
- EPIT:是一个向下计数的定时器。它的工作原理是:将加载寄存器(
3. GPT 定时器代码解析
代码逻辑:
- 复位:确保 GPT 模块从一个已知的初始状态开始。
- 模式选择:配置为 Free-Run 模式,计数器从 0 向上计数到最大值后自动回绕。
- 时钟配置:选择
ipg_clk作为时钟源。假设ipg_clk频率为 66MHz,经过 66 分频后,GPT 的计数频率变为66MHz / 66 = 1MHz,即每 1 微秒计数器加 1。 - 使能:最后使能 GPT,计数器开始工作。
#include "gpt.h"
#include "MCIMX6Y2.h"
#include "core_ca7.h"
void gpt_init(void)
{
GPT1->CR = 0; // 1. 清零控制寄存器,复位所有配置
GPT1->CR |= (1 << 15); // 2. 设置复位位 (SWR),软件复位 GPT 模块
while ((GPT1->CR & (1 << 15)) != 0); // 3. 等待复位完成(硬件自动清除该位)
GPT1->CR |= (1 << 9); // 4. 设置 FRR 位,选择 Free-Run 模式(向上计数)
GPT1->CR |= (1 << 6); // 5. 设置 CLKSRC 位,选择时钟源为 ipg_clk
GPT1->PR = 65; // 6. 设置预分频寄存器,进行 66 分频 (PR + 1)
GPT1->CR |= (1 << 0); // 7. 设置 EN 位,使能 GPT 定时器开始工作
}
4. EPIT 定时器代码解析
EPIT 的初始化代码稍显复杂,因为它一次性配置了多个功能位。
#include "epit.h"
#include "led.h"
#include "interrupt.h"
#include "MCIMX6Y2.h"
#include "core_ca7.h"
// EPIT 中断处理函数
void epit_interrupt_handler(void)
{
if ((EPIT1->SR & (1 << 0)) != 0) // 检查是否发生了比较中断
{
led_nor(); // 执行 LED 翻转操作
}
EPIT1->SR |= (1 << 0); // 清除中断标志位
}
void epit_init(void)
{
// 1. 一次性配置控制寄存器
EPIT1->CR = 0;
EPIT1->CR |= (1 << 24) | (1 << 17) | (65 << 4) | (1 << 3) | (1 << 2) | (1 << 1);
EPIT1->LR = 1000000; // 2. 设置加载值为 1,000,000
EPIT1->CMPR = 0; // 3. 设置比较值为 0
// 4. 注册中断服务函数
system_interrupt_register(EPIT1_IRQn, epit_interrupt_handler);
// 5. 设置中断优先级
GIC_SetPriority(EPIT1_IRQn, 1);
// 6. 使能中断
GIC_EnableIRQ(EPIT1_IRQn);
// 7. 使能 EPIT 定时器
EPIT1->CR |= (1 << 0);
}
代码逻辑与关键位解析:
(1 << 24):设置CLKSRC位,选择时钟源。(1 << 17):设置IOVW位,当 EPIT 被重新使能时,立即重新加载LR的值。(65 << 4):设置预分频值PRESCALAR。与 GPT 类似,实际分频系数为65 + 1 = 66。(1 << 3):设置RLD位,使能自动重载模式。当计数器计数到 0 时,自动从LR重新加载计数值。(1 << 2):设置OM位,选择输出模式。(1 << 1):设置ENMOD位,使能 EPIT 时,计数器从LR的值开始加载。
工作流程:
- 使能后,计数器从
LR(1,000,000)开始向下计数。 - 当计数到与
CMPR(0)相等时,触发中断。 - 在中断处理函数中,翻转 LED 状态。
- 由于开启了自动重载(
RLD),计数器会再次从LR加载 1,000,000,开始新一轮计数。 - 假设时钟频率为 66MHz,66 分频后为 1MHz,那么定时周期为
1,000,000 / 1,000,000 = 1秒。因此,LED 会以 1 秒的间隔翻转。
5. 总结
| 特性 | EPIT | GPT |
|---|---|---|
| 全称 | Enhanced Periodic Interrupt Timer | General Purpose Timer |
| 位数 | 32 位 | 32 位 |
| 计数方向 | 向下计数 | 向上计数 (Free-Run 模式) |
| 核心功能 | 精确周期性中断 | 周期性中断、输入捕获、输出比较 |
| 典型应用 | 系统心跳、任务调度、按键消抖 | 脉冲测量、波形生成、通用定时 |
更多推荐

所有评论(0)