I.MX6ULL时钟(clock)与定时器(EPITGPT)
一、基础概念
定时器 (EPIT/GPT)
通过对已知频率时钟信号进行计数,实现定时、延时或事件计数的硬件模块 / 软件机制clock (时钟)
产生稳定周期性振荡信号的电路,为数字电路提供同步时序基准(类似节拍器)RTC (实时时钟)
微处理器中独立于主电源的模块,用于在系统断电后维持精确的日历和时间信息
二、时钟系统硬件组件
- 时钟源:晶体振荡器
原理:石英晶体切割成音叉结构,施加电压后产生稳定振荡,提供基准频率(如 24MHz)
- PLL (锁相环电路)
功能:对输入时钟进行倍频,输出高频信号
应用:将低频基准时钟提升至系统所需高频(如 IMX6ULL 的 PLL1 可输出 1056MHz)
- Prescaler (分频器)
功能:对输入时钟进行整数分频(降低频率),输出频率 = 输入频率 / 分频系数。
- PFD (相位分数分频器)
功能:支持分数分频,可升频或降频,输出频率更灵活。
通过查阅手册查询时钟树
本次实验目标频率
所用到的时钟配置及时钟根配置
三、IMX6ULL 时钟配置(代码相关)
内核时钟(ARM PLL)配置步骤
(1) 选择osc_clk,使step_clk为24MHz (2) 将PLL1输出临时切换为step_clk,让ARM工作在24MHz (3) 配置PLL1为1056MHz(先设置二分频,再调倍频因子,避免频率起伏过大,导致内核故障卡死) (4) 切换回pll1_main_clk作为最终时钟源
主要 PLL 与 PFD
- 528 PLL:通过 CCM_ANALOG_PFD_528n 配置衍生时钟
- 480 PLL:通过 CCM_ANALOG_PFD_480n 配置衍生时钟
关键时钟根配置
- AHB_CLK_ROOT (132M):由 CBCMR [PRE_PERIPH_CLK_SEL]、CBCDR [PERIPH_CLK_SEL] 和 CBCDR [AHB_PODF] 控制
- IPG_CLK_ROOT (66M):由 CBCDR [IPG_PODF] 分频控制
- PERCLK_CLK_ROOT (66M):由 CSCMR1 [PERCLK_CLK_SEL] 和 CSCMR1 [PERCLK_PODF] 控制
程序代码实现:
void clock_init(void)
{//ARM核心工作时钟配置//配置CCM_CACRR寄存器(ARM时钟分频器)CCM->CACRR &= ~(7 << 0); //111 bit0~bit2全清0CCM->CACRR |= (1 << 0); //设置2分频001 bit0置1//配置CCM_CCSR寄存器(时钟控制状态)CCM->CCSR &= ~(1 << 8); //CCSR bit8清0 CCM->CCSR |= (1 << 2); //设置bit2 置1 选择PLL_ARM作为时钟源//PLL_ARM锁相环配置unsigned int t = CCM_ANALOG->PLL_ARM; //读取当前PLL_ARM寄存器值存入t中t &= ~(0x7F << 0); //清除DIV_SELECT字段(bit0-6)t |= (88 << 0); //设置DIV_SELECT=88(PLL输出频率=24MHz*(DIV_SELECT/2))t |= (1 << 13); //使能PLL(bit13,PLL_ENABLE)t &= ~(3 << 14); //清除BYPASS模式(bit14-15置1)CCM_ANALOG->PLL_ARM = t; //写回配置// 计算:PLL_ARM输出 = 24MHz * 88 / 2 = 1056MHzCCM->CCSR &= ~(1 << 2); //清除bit2(STEP_SEL),切换回默认时钟源//528 PLL 528MHz域PFD配置 t = CCM_ANALOG->PFD_528;t &= ~((0x3F << 0) | (0x3F << 8) | (0x3F << 16) | (0x3F << 24)); //清除所有PFD的分频系数t |= ((27 << 0) | (16 << 8) | (24 << 16) | (32 << 24)); //设置各PFD分频系数/*PFD0分频系数=27 (528 * 18/27=352MHz)FD1分频系数=16 (528 * 18/16=594MHz)PFD2分频系数=24 (528 * 18/24=396MHz)FD3分频系数=32 (528 * 18/32=297MHz)*/ CCM_ANALOG->PFD_528 = t;//480 PPL 480MHz域PFD配置 t = CCM_ANALOG->PFD_480;t &= ~((0x3F << 0) | (0x3F << 8) | (0x3F << 16) | (0x3F << 24));t |= ((12 << 0) | (16 << 8) | (17 << 16) | (19 << 24));/*PFD0分频系数=12 (480 * 18/12=720MHz)PFD1分频系数=16 (480 * 18/16=540MHz)PFD2分频系数=17 (480 * 18/17≈508MHz)PFD3分频系数=19 (480 * 18/19≈454MHz)*/ CCM_ANALOG->PFD_480 = t;//AHB_CLK_ROOT时钟根配置CCM->CBCMR &= ~(3 << 18); // 清除bit18-19(PRE_PERIPH_CLK_SEL)清0CCM->CBCMR |= (1 << 18); //设置为01 bit 18置1t = CCM->CBCDR;t &= ~(1 << 25); // 清除bit25(PERIPH_CLK_SEL),选择PRE_PERIPH_CLKt &= ~(7 << 10); // 清除bit10-12(AHB_PODF),准备设置AHB分频t |= (2 << 10); // 设置AHB_PODF=010(3分频),AHB_CLK = 396MHz / 3 = 132MHz//IPG_CLK_ROOTt &= ~(3 << 8); // 清除bit8-9(IPG_PODF)t |= (1 << 8); // 设置IPG_PODF=01(2分频),IPG_CLK = AHB_CLK / 2 = 66MHzCCM->CBCDR = t;//PERCLK_CLK_ROOTt = CCM->CSCMR1;t &= ~(1 << 6); // 清除bit6(PERCLK_CLK_SEL),选择IPG_CLK作为源t &= ~(0x3F << 0); // 清除bit0-5(PERCLK_PODF),准备设置分频CCM->CSCMR1 = t;cg_init();
}
四、定时器工作原理
51单片机定时器
- 8 位定时器:支持自动重装,溢出后自动加载初值
- 16 位定时器:溢出后需在中断服务程序中手动重装初值
I.MX6ULL 定时器
EPIT(增强型周期中断定时器)
原理:对输入时钟(如 IPG_CLK)分频后计数,计数到 0 触发中断(可自动重载)
应用:1s 定时中断,在中断服务函数中反转 LED 灯状态
程序代码实现:
void epit1_irq_handler(void)
{if((EPIT1->SR & (1 << 0)) !=0) {led_nor();//中断处理EPIT1->SR |= (1 << 0); //清除中断 写1清0}
}void epit1_init(void)
{unsigned int t; t = EPIT1->CR; // 获取当前控制寄存器(CR)的值// 配置EPIT1控制寄存器(CR)t &= ~(3 << 24); // bit24-25清0(时钟源选择)t |= (1 << 24); // 设置24位(选择Peripheral时钟)t |= (1 << 17); // 设置17位(计数器从LR重新加载)t &= ~(0xFFF << 4); // bit4-15(设置分频值)t |= (65 << 4); // 设置分频值为65+1=66Mt |= (1 << 3); // 设置bit3(比较中断使能)t |= (1 << 2); // 设置bit2(比较功能使能)t |= (1 << 1); // 设置bit1(计数器从加载值开始)EPIT1->CR = t;EPIT1->LR = 1000000; // 设置加载寄存器(LR)值为1000000EPIT1->CMPR = 0; // 设置比较寄存器(CMPR)值为0EPIT1->CNR = 1000000; // 设置计数器(CNR)初始值为1000000//注册中断处理函数system_interrupt_register(EPIT1_IRQn, epit1_irq_handler);//2.GIC中断使能GIC_EnableIRQ(EPIT1_IRQn);GIC_SetPriority(EPIT1_IRQn, 0);//enableEPIT1->CR |= (1 << 0);
}
GPT(通用目的定时器)
功能:支持输入捕获和比较输出
应用:自由运行模式下编写精准延时函数
程序代码实现:
void reset_gpt1(void)
{GPT1->CR |= (1 << 15); // 设置CR寄存器的bit15(软件复位)while(((GPT1->CR) & (1 << 15)) != 0); // 等待复位完成(bit15自动清零)
}void gpt1_init(void)
{reset_gpt1(); // 先复位GPT1定时器unsigned int t;t = GPT1->CR;t &= ~((7 << 26) | (3 << 18) | (1 << 1)); // bit26-28(时钟源选择)、bit18-19(工作模式)、bit1(Free-run模式)清0t |= (1 << 9); // 设置bit9(自由运行模式)t &= ~(7 << 6); // bit6-8清0(输入捕获设置)t |= (1 << 6); // 设置bit6(递增计数模式)GPT1->CR = t;// 配置预分频寄存器(PR)GPT1->PR &= ~(0xFFF << 0); // bit0-11清0(分频值)GPT1->PR |= (65 << 0); // 设置分频值为65+1=66MGPT1->CNT = 0; // 清零计数器GPT1->CR |= (1 << 0); // 使能GPT1定时器(CR寄存器的第0位)
}void delay_us(unsigned int us) //微秒延时
{unsigned int counter = 0;unsigned int old_counter ;unsigned int new_counter ;old_counter = GPT1->CNT; // 获取当前计数器值while(1){new_counter = GPT1->CNT;if(old_counter != new_counter){ // 处理计数器回滚情况(32位计数器溢出)if(new_counter < old_counter) //回滚{counter += 0xFFFFFFFF - old_counter + new_counter;}else{counter += new_counter - old_counter;}// 检查是否达到要求的延时时间if(counter >= us){return;}old_counter = new_counter;}}
}void delay_ms(unsigned int ms) //毫秒延时
{while(ms--){delay_us(1000);}
}
总结:
1.什么是 PLL、Prescaler、PFD,它们各自的作用是什么?
- PLL(Phase-Locked Loop,锁相环):一种频率合成电路,由相位比较器、低通滤波器和压控振荡器(VCO)组成,通过反馈机制将输入参考时钟(如晶体振荡器)的频率倍增到更高的目标频率 <倍频>
作用是为芯片内部不同模块(如 CPU、外设)提供稳定且精确的高频时钟,满足各模块对时钟频率的特定需求。
- Prescaler(预分频器):一种将输入时钟频率按固定比例降低(如 1/2、1/4、1/8 等)的电路 <分频>
作用是将高频时钟(如 PLL 输出)分频为较低频率,适配对时钟频率要求较低的外设(如 UART、SPI),同时降低相关模块的功耗或满足外设的时序约束。
- PFD(Phase Frequency Detec,相位分数分频器):PLL 中的核心组件,用于比较输入参考时钟与 VCO 输出经分频后的反馈时钟的相位和频率差异,并输出对应的误差信号 <倍频/分频>
作用是通过检测相位和频率差,控制低通滤波器和 VCO,使 VCO 输出频率稳定在目标值,确保 PLL 输出时钟的准确性和稳定性。
2.IMX6ULL 中有几个 PLL?几个 PFD?
- PLL 数量:IMX6ULL 包含 7 个 PLL,分别是 ARM PLL、PERIPH PLL、USB1 PLL、USB2 PLL、ENET PLL、AUDIO PLL、VIDEO PLL。
- PFD 数量:IMX6ULL 中,PERIPH PLL 和 ARM PLL 各包含 4 个 PFD(PFD0~PFD3),总计 8 个 PFD,用于从对应 PLL 输出分频得到多种衍生时钟,供不同外设使用。
3.简述 ARM PLL 的配置流程
在I.MX6ULL中ARM PLL 的配置流程如下:
- 使能 PLL 电源:通过 CCM(时钟控制模块)的电源管理寄存器(如 CCM_CCGR0)为 ARM PLL 模块供电,确保其正常工作。
- 配置参考时钟源:选择 ARM PLL 的输入参考时钟,IMX6ULL 中默认参考时钟为外部 24MHz 晶体振荡器。
- 设置分频与倍频参数:通过 CCM_ANALOG_PLL_ARM 寄存器配置分频系数(P)和倍频系数(M),目标输出频率计算公式为 “输出频率 = 参考时钟频率 ×M/P”。
- 等待 PLL 锁定:配置完成后,通过读取 PLL 状态寄存器(如 CCM_ANALOG_PLL_ARM_LOCK),检测 PLL 是否锁定(即输出频率稳定),直至锁定标志位有效。
- 切换 CPU 时钟源:将 CPU 的时钟源从初始的低功耗内部 RC 振荡器切换到 ARM PLL 输出,完成配置。
4.IMX6ULL 中的 EPIT 和 GPT 的工作原理是什么?
- EPIT(增强型周期中断定时器):专注于产生周期性中断,用于定时触发任务(如系统定时、周期性采样) 工作原理:由预设时钟源(如 PLL 分频后的时钟)驱动 32 位计数器递减计数;用户通过寄存器设置比较值和加载值,当计数器值递减至与比较值匹配时,产生中断信号;同时支持自动重加载模式,中断后计数器自动加载预设的初始值,继续递减计数,实现周期性中断。
- GPT(通用定时器):功能灵活,支持多种工作模式(计数、PWM、输入捕获等) 工作原理:可选择内部时钟(如 PLL 分频时钟)或外部引脚输入作为时钟源,驱动 32 位计数器递增计数;支持比较匹配(当计数器值与比较寄存器值相等时,输出 PWM 信号或产生中断)、输入捕获(检测外部信号边沿时,记录计数器当前值作为时间戳)、自由运行(计数器持续递增,溢出后归零)等模式;通过配置相关寄存器(如分频系数、计数方向、触发条件),适配多样化的定时或脉冲检测需求。