1. 什么是 EPIT 和 GPT?

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

在这里插入图片描述

  • EPIT (Enhanced Periodic Interrupt Timer)增强型周期中断定时器。顾名思义,它主要用于产生精确的周期性中断,非常适合用来实现系统心跳、任务调度、PWM 信号生成或精确延时等场景。GPT定时器
  • 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,并可以触发溢出中断。

3. GPT 定时器代码解析

代码逻辑

  1. 复位:确保 GPT 模块从一个已知的初始状态开始。
  2. 模式选择:配置为 Free-Run 模式,计数器从 0 向上计数到最大值后自动回绕。
  3. 时钟配置:选择 ipg_clk 作为时钟源。假设 ipg_clk 频率为 66MHz,经过 66 分频后,GPT 的计数频率变为 66MHz / 66 = 1MHz,即每 1 微秒计数器加 1。
  4. 使能:最后使能 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 的值开始加载。

工作流程

  1. 使能后,计数器从 LR(1,000,000)开始向下计数。
  2. 当计数到与 CMPR(0)相等时,触发中断。
  3. 在中断处理函数中,翻转 LED 状态。
  4. 由于开启了自动重载(RLD),计数器会再次从 LR 加载 1,000,000,开始新一轮计数。
  5. 假设时钟频率为 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 模式)
核心功能 精确周期性中断 周期性中断、输入捕获、输出比较
典型应用 系统心跳、任务调度、按键消抖 脉冲测量、波形生成、通用定时

更多推荐