ARM-07-i.MX6ULL-EPIT定时器和GPT
这张图是 → 多路选择器选时钟(可选关闭、IPG 时钟、32K 时钟、高速时钟) → 12 位预分频器(分频系数 1~4096) → 32 位计数器(从加载寄存器值开始向下计数) → 与比较寄存器值匹配时触发比较器 → 比较触发中断(ITIF/ITIE)和输出引脚(EPITn_OUT) → 计数到 0 时自动从加载寄存器重载,继续计数:时钟 → 分频 → 计数 → 比较 → 中断/输出
一,EPIT定时器
这张图是 i.MX6ULL 芯片中 EPIT 定时器模块的框图

(1)EPIT 定时器工作原理:
-
时钟源 → 多路选择器选时钟(可选关闭、IPG 时钟、32K 时钟、高速时钟)
-
分频 → 12 位预分频器(分频系数 1~4096)
-
计数 → 32 位计数器(从加载寄存器值开始向下计数)
-
比较 → 与比较寄存器值匹配时触发比较器
-
输出控制 → 比较触发中断(ITIF/ITIE)和输出引脚(EPITn_OUT)
-
重载 → 计数到 0 时自动从加载寄存器重载,继续计数
核心流程:时钟 → 分频 → 计数 → 比较 → 中断/输出 → 重载循环
应用:定时中断、PWM 生成、精确延时。

Set-and-forget mode(设置即忘模式)
一次性配置加载值和比较值,定时器自动循环工作,无需软件反复干预。
Free-running mode(自由运行模式)
计数器从初始值不断递减→归零→自动重载,持续循环计数,永不停止。
配置定时器
(2)EPITx_CR





(3)配置代码
void epit1_init(irq_handler_t handler)
{
// 配置EPIT1控制寄存器(EPIT1->CR)
unsigned int tmp = EPIT1->CR;
// 清除时钟源选择位(CLCKSRC, bit25:24)
tmp &= ~(0x3 << 24);
// 设置时钟源为Peripheral时钟(ipg_clk, 66MHz),CLCKSRC=01
tmp |= (0x1 << 24);
// 使能比较中断(OIEN, bit17)
tmp |= (1 << 17);
// 清除分频值(PRESCALAR, bit15:4)
tmp &= ~(0xfff << 4);
// 设置分频值=65 → 66分频(65+1),时钟=66MHz/66=1MHz(1us计数)
tmp |= (65 << 4);
// 设置工作模式为set-and-forget(bit3=1)
tmp |= (1 << 3);
// 使能比较中断(bit2=1)
tmp |= (1 << 2);
// 设置计数器初始值来源为加载寄存器(ENMOD, bit1=1)
tmp |= (1 << 1);
// 写入配置到CR
EPIT1->CR = tmp;
// 设置加载寄存器(LR)=1000000 → 计数1秒(1MHz计数频率)
EPIT1->LR = 1000000;
// 设置当前计数值(CNR)=1000000 → 初始值与LR相同
EPIT1->CNR = 1000000;
// 设置比较值(CMPR)=0 → 计数到0时产生中断
EPIT1->CMPR = 0;
// 注册EPIT1中断处理函数
request_irq(EPIT1_IRQn, handler);
// 使能EPIT1(EN, bit0=1)
EPIT1->CR |= (1 << 0);
}
二 ,GPT
GPT也有两种工作模式:
(1)GPT 控制寄存器 (GPTx_CR)
SWR(bit15):软件复位位。写 1 复位 GPT,复位完成后硬件自动清零。
FRR(bit9):运行模式选择。0=比较通道1工作在重启模式,1=所有通道工作在自由运行模式。
CLKSRC(bit8:6):时钟源选择。1=ipg_clk(我们的选择)。
ENMOD(bit1):使能模式。0=关闭时保留计数值,1=关闭时清零计数器。
EN(bit0):使能位。1=启动定时器,0=停止。





(2)GPT 预分频寄存器 (GPTx_PR)
-
PRESCALER(bit11:0):12 位分频值。范围 0~4095,对应 1~4096 分频。我们设 65 实现 66 ()分频(65+1)。


(3)配置代码如下
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
#include "gpt.h"
// 软件复位GPT1,置位SWR(bit15)后等待其自动清零(复位完成)
static inline void gpt1_reset(void)
{
GPT1->CR |= (1 << 15); // SWR(bit15)=1,复位GPT
while((GPT1->CR & (1 << 15))); // 等待SWR自动清零
}
// 初始化GPT1:复位→配置CR/PR→使能定时器
void gpt1_init(void)
{
gpt1_reset(); // 复位GPT1
unsigned int tmp = GPT1->CR;
// 清除中断掩码位IMx(bit20~28)和输出模式位OMx(bit16~19)
tmp &= ~(0x1ff << 20);
tmp &= ~(0xf << 16);
// 配置工作模式和时钟源
tmp |= (1 << 9); // FRR(bit9)=1:所有比较通道自由运行模式
tmp &= ~(0x7 << 6); // 清除CLKSRC(bit8:6)
tmp |= (1 << 6); // CLKSRC(bit8:6)=001,选择ipg_clk(66MHz)时钟源
tmp &= ~(1 << 1); // ENMOD(bit1)=0:关闭时保留计数值
GPT1->CR = tmp; // 写入配置
// 配置预分频器
tmp = GPT1->PR; // 预分频寄存器
tmp &= ~(0xfff << 0);// 清除PRESCALER(bit11:0)
tmp |= (65 << 0); // 分频值=65 → 66分频(65+1),时钟=66MHz/66=1MHz(1us计数)
GPT1->PR = tmp;
GPT1->CR |= (1 << 0); // EN(bit0)=1:使能GPT1定时器
}
// 微秒级延时:通过读取GPT1_CNT差值计算时间(处理32位溢出)
void inline delay_us(unsigned int num)
{
unsigned int counter = 0;
unsigned int cur_couter = 0;
unsigned int old_couter = GPT1->CNT; // 记录初始计数值
while(1)
{
cur_couter = GPT1->CNT;
if(cur_couter == old_couter)
continue;
// 计算计数值增量(处理溢出:cur < old 时说明溢出,加0xffffffff)
if(cur_couter > old_couter)
counter += cur_couter - old_couter;
else
counter += cur_couter + 0xffffffff - old_couter;
if(counter >= num) // 达到目标延时则退出
return;
old_couter = cur_couter;
}
}
// 毫秒级延时:循环调用delay_us(1000)
void delay_ms(unsigned int num)
{
while(num--)
{
delay_us(1000);
}
}
更多推荐



所有评论(0)