当前位置: 首页 > news >正文

I.MX6ULL时钟(clock)与定时器(EPITGPT)

一、基础概念
  1. 定时器 (EPIT/GPT)
    通过对已知频率时钟信号进行计数,实现定时、延时或事件计数的硬件模块 / 软件机制

  2. clock (时钟)
    产生稳定周期性振荡信号的电路,为数字电路提供同步时序基准(类似节拍器)

  3. RTC (实时时钟)
    微处理器中独立于主电源的模块,用于在系统断电后维持精确的日历和时间信息

二、时钟系统硬件组件
  • 时钟源:晶体振荡器

原理:石英晶体切割成音叉结构,施加电压后产生稳定振荡,提供基准频率(如 24MHz)

  • PLL (锁相环电路)

功能:对输入时钟进行倍频,输出高频信号

应用:将低频基准时钟提升至系统所需高频(如 IMX6ULL 的 PLL1 可输出 1056MHz)

  • Prescaler (分频器)

功能:对输入时钟进行整数分频(降低频率),输出频率 = 输入频率 / 分频系数。

  • PFD (相位分数分频器)

功能:支持分数分频,可升频或降频,输出频率更灵活。

通过查阅手册查询时钟树

本次实验目标频率

所用到的时钟配置及时钟根配置

三、IMX6ULL 时钟配置(代码相关)
  1. 内核时钟(ARM PLL)配置步骤

    (1) 选择osc_clk,使step_clk为24MHz  
    (2) 将PLL1输出临时切换为step_clk,让ARM工作在24MHz  
    (3) 配置PLL1为1056MHz(先设置二分频,再调倍频因子,避免频率起伏过大,导致内核故障卡死)  
    (4) 切换回pll1_main_clk作为最终时钟源  
    
  2. 主要 PLL 与 PFD

    • 528 PLL:通过 CCM_ANALOG_PFD_528n 配置衍生时钟
    • 480 PLL:通过 CCM_ANALOG_PFD_480n 配置衍生时钟
  3. 关键时钟根配置

    • 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 的配置流程如下:

  1. 使能 PLL 电源:通过 CCM(时钟控制模块)的电源管理寄存器(如 CCM_CCGR0)为 ARM PLL 模块供电,确保其正常工作。
  2. 配置参考时钟源:选择 ARM PLL 的输入参考时钟,IMX6ULL 中默认参考时钟为外部 24MHz 晶体振荡器。
  3. 设置分频与倍频参数:通过 CCM_ANALOG_PLL_ARM 寄存器配置分频系数(P)和倍频系数(M),目标输出频率计算公式为 “输出频率 = 参考时钟频率 ×M/P”。
  4. 等待 PLL 锁定:配置完成后,通过读取 PLL 状态寄存器(如 CCM_ANALOG_PLL_ARM_LOCK),检测 PLL 是否锁定(即输出频率稳定),直至锁定标志位有效。
  5. 切换 CPU 时钟源:将 CPU 的时钟源从初始的低功耗内部 RC 振荡器切换到 ARM PLL 输出,完成配置。

4.IMX6ULL 中的 EPIT 和 GPT 的工作原理是什么?

  • EPIT(增强型周期中断定时器):专注于产生周期性中断,用于定时触发任务(如系统定时、周期性采样)        工作原理:由预设时钟源(如 PLL 分频后的时钟)驱动 32 位计数器递减计数;用户通过寄存器设置比较值和加载值,当计数器值递减至与比较值匹配时,产生中断信号;同时支持自动重加载模式,中断后计数器自动加载预设的初始值,继续递减计数,实现周期性中断。
  • GPT(通用定时器):功能灵活,支持多种工作模式(计数、PWM、输入捕获等)      工作原理:可选择内部时钟(如 PLL 分频时钟)或外部引脚输入作为时钟源,驱动 32 位计数器递增计数;支持比较匹配(当计数器值与比较寄存器值相等时,输出 PWM 信号或产生中断)、输入捕获(检测外部信号边沿时,记录计数器当前值作为时间戳)、自由运行(计数器持续递增,溢出后归零)等模式;通过配置相关寄存器(如分频系数、计数方向、触发条件),适配多样化的定时或脉冲检测需求。

文章转载自:

http://LCSDV3vt.bmtyn.cn
http://Gwur1CLt.bmtyn.cn
http://Y3muKi4w.bmtyn.cn
http://cMWzp5pJ.bmtyn.cn
http://NkOAp96h.bmtyn.cn
http://pkDdaFKc.bmtyn.cn
http://s4N4h6vc.bmtyn.cn
http://UjDRMkHI.bmtyn.cn
http://ExXqfUUt.bmtyn.cn
http://4tQhJnGH.bmtyn.cn
http://YRmBL2m9.bmtyn.cn
http://GHSXE2gb.bmtyn.cn
http://QSO00ncB.bmtyn.cn
http://FioBQ6zf.bmtyn.cn
http://tLVFQIFd.bmtyn.cn
http://gkVR3i9T.bmtyn.cn
http://HkGAJpB6.bmtyn.cn
http://5KZY11xK.bmtyn.cn
http://PVqAjPB1.bmtyn.cn
http://xCuHHmEP.bmtyn.cn
http://9NuVW4ep.bmtyn.cn
http://YMuApEBm.bmtyn.cn
http://evt8PRE3.bmtyn.cn
http://7mtzs3Y5.bmtyn.cn
http://tt8QV96G.bmtyn.cn
http://MhpyJ8Xl.bmtyn.cn
http://1s0Dn6V8.bmtyn.cn
http://TZsJKZGu.bmtyn.cn
http://pvsWlvBQ.bmtyn.cn
http://8BxxZDgb.bmtyn.cn
http://www.dtcms.com/a/383768.html

相关文章:

  • STM32_06_Systick定时器
  • 用 Java 学会 Protocol Buffers从 0 到 1 的完整实战
  • 237.删除链表中的节点
  • 【Vue2手录14】导航守卫
  • Qt如何读写xml文件,几种方式对比,读写xml的Demo工程
  • 子网划分专项训练-1,eNSP实验,vlan/dhcp,IP规划
  • 云原生改造实战:Spring Boot 应用的 Kubernetes 迁移全指南
  • 看门狗的驱动原理
  • [论文阅读] 人工智能 + 软件工程 | 大语言模型驱动的多来源漏洞影响库识别研究解析
  • 【前缀和+哈希表】P3131 [USACO16JAN] Subsequences Summing to Sevens S
  • 05.【Linux系统编程】进程(进程概念、进程状态(注意僵尸和孤儿)、进程优先级、进程切换和调度)
  • 【从零开始java学习|小结】记录学习和编程中的问题
  • 图像拼接案例,抠图案例
  • 分层解耦讲解
  • 安装Hadoop中遇到的一些问题和解决
  • 音视频-色域
  • 返利软件的分布式缓存架构:Redis集群在高并发场景下的优化策略
  • 如何让知识上传与查询更便捷
  • set/multiset容器
  • 区块链:搭建简单Fabric网络并调用智能合约
  • Keepalived的详细实操安装流程及其配置文件选项的详解
  • windows下,podman迁移镜像文件位置
  • 技能补全之正则表达式
  • Altium Designer(AD24)打开工程文件的几种方法
  • 26考研——内存管理(3)
  • 知识库缺乏维护和清理机制会造成哪些后果
  • android studio 华为 安装app 层层验证
  • 机器学习(三):决策树
  • 气缸夹爪机构分析
  • np.sum(e_x, axis=-1, keepdims=True)