一.时钟控制模块
4个层次配置芯片时钟
- 晶振时钟
- PLL与PFD时钟
- PLL选择时钟
- 根时钟/外设时钟
1.1晶振时钟
系统时钟来源
- RTC时钟源:32.768KHz,连接RTC模块,进行时间计算。
- 系统时钟:24MHz,芯片主晶振

1.2PLL和PFD倍频时钟
7路锁相环电路
- ARM_PLL:驱动 ARM 内核
- 528_PLL:倍频参数固定为22,系统总线时钟
- USB1_PLL:驱动第一个 USB 物理层
- AUDIO_PLL:驱动音频接口
- VIDEO_PLL:驱动视频接口
- ENET_PLL:驱动外部以太网接口
- USB2_PLL:驱动第二个 USB 物理层
10.3.1 Centralized components of clock management system
 
18.6 CCM Memory Map/Register Definition
-  CCM_ANALOG_PLL_XXX - 设置PPL时钟主频(pll1_main_clk)
- 使能PLL时钟输出
 
-  CCM_ANALOG_PFD_XXX - 设置PPL下PFD的分频系数
 
1.3PLL选择时钟
对 PLL1 和 PLL3 的输出进行选择、对 PLL4 和 PLL5 进行分频
-  cpu内核时钟来于PLL1时钟。 
-  刚上电时,PLL1时钟未初始化,arm内核先使用24M晶振频率,等PLL1时钟稳定输出后,再切换回PLL1时钟。 
CCM_CCSR:选择pll1_sw_clk、step_clk时钟源
- step_clk时钟源设置为24M晶振
- pll1_main_clk时钟源设置为 step_clk或pll1_main_clk
18.5.1.5.1 Clock Switcher
1.4外设时钟
给外设设置时钟源,外设时钟源是可以有多个选择的:
- 梯形图标表示上一级时钟源配置
- 正方形图标表示分频系数
图标旁边标明了相关寄存器
18.3 CCM Clock Tree

二.时钟模块编程流程
2.1设置晶振时钟
设置晶振时钟,实质上是让CPU运行PLL1时钟,将CPU运行到ARM PLL时钟上。因为CPU默认使用24MHz的芯片主晶振。
 /******************* 第一层时钟设置--晶振时钟***********************/
    /*CCM中包括很多关于时钟的寄存器 */
    if ((CCM->CCSR & (0x01 << 2)) == 0) //CPU 使用的是 ARM PLL
    {
        /*将CPU时钟切换到XTAL (OSC) 时钟*/                   
        CCM->CCSR &= ~(0x01 << 8); //控制CCSR: step_sel ,选择 osc_clk 作为时钟源
        CCM->CCSR |= (0x01 << 2);  //设置GLITCHLESS MUX 选择 step_clk 作为时钟源
    }
2.2设置PLL时钟
主要是设置七路PPL时钟
   /******************* 第二层时钟设置--PLL时钟***********************/
   
    /*设置PLL1输出时钟为792MHz,它将作为CPU时钟*/
    CCM_ANALOG->PLL_ARM |= (0x42 << 0);
    /*将CPU 时钟重新切换到 ARM PLL*/
    CCM->CCSR &= ~(0x01 << 2);
    /*设置时钟分频系数为0,即不分频*/
    CCM->CACRR &= ~(0x07 << 0); //清零分频寄存器   不分频
   //CCM->CACRR |= (0x07 << 0);     // 8分频
    /*设置PLL2(System PLL) 输出时钟*/
    /* Configure SYS PLL to 528M */
    CCM_ANALOG->PLL_SYS_SS &= ~(0x8000);     //使能PLL2 PFD输出
    CCM_ANALOG->PLL_SYS_NUM &= ~(0x3FFFFFFF);//设置分频系数为0,即不分频。
    CCM_ANALOG->PLL_SYS |= (0x2000); //使能PLL2 输出
    CCM_ANALOG->PLL_SYS |= (1 << 0); //设置输出频率为528M
    while ((CCM_ANALOG->PLL_SYS & (0x80000000)) == 0) //等待设置生效
    {
    }
    /*设置PLL3(System PLL) 输出时钟*/
    /* Configure USB PLL to 480M */
    CCM_ANALOG->PLL_USB1 |= (0x2000);    //使能 PLL3时钟输出
    CCM_ANALOG->PLL_USB1 |= (0x1000);    //PLL3上电使能
    CCM_ANALOG->PLL_USB1 |= (0x40);      // 使能USBPHYn
    CCM_ANALOG->PLL_USB1 &= ~(0x01 << 0);//设置输出频率为480MHz
    while ((CCM_ANALOG->PLL_SYS & (0x80000000)) == 0)//等待设置生效
    {
    }
    /*关闭暂时不使用的 PLL4 、PLL5  、PLL6 、PLL7*/
    CCM_ANALOG->PLL_AUDIO = (0x1000);    //关闭PLL4
    CCM_ANALOG->PLL_VIDEO = (0x1000);    //关闭PLL5
    CCM_ANALOG->PLL_ENET =  (0x1000);    //关闭PLL6
    CCM_ANALOG->PLL_USB2 =  (0x00);           //关闭PLL7
2.3设置PFD时钟
细分每一路的PLL时钟
    /******************第三层时钟设置--PFD*******************/
    /*禁用PLL2 的所有PFD输出*/
    CCM_ANALOG->PFD_528 |=(0x80U) ;      //关闭PLL2 PFD0
    CCM_ANALOG->PFD_528 |=(0x8000U) ;    //关闭PLL2 PFD1
    // CCM_ANALOG->PFD_528 |=(0x800000U) ;  //关闭PLL2 PFD2 ,DDR使用的是该时钟源,关闭后程序不能运行。暂时不关闭
    CCM_ANALOG->PFD_528 |=(0x80000000U); //关闭PLL2 PFD3
    
    /*设置PLL2 的PFD输出频率*/
    CCM_ANALOG->PFD_528 &= ~(0x3FU); //清零PLL2 PFD0 时钟分频
    CCM_ANALOG->PFD_528 &= ~(0x3F00U); //清零PLL2 PFD1 时钟分频
    CCM_ANALOG->PFD_528 &= ~(0x3F00U); //清零PLL2 PFD2 时钟分频
    CCM_ANALOG->PFD_528 &= ~(0x3F00U); //清零PLL2 PFD3 时钟分频
    CCM_ANALOG->PFD_528 |= (0x1B << 0); //设置PLL2 PFD0 输出频率为 352M
    CCM_ANALOG->PFD_528 |= (0x10 << 8); //设置PLL2 PFD0 输出频率为 594M
    CCM_ANALOG->PFD_528 |= (0x18 << 16); //设置PLL2 PFD0 输出频率为 396M
    CCM_ANALOG->PFD_528 |= (0x30 << 24); //设置PLL2 PFD0 输出频率为 198M
    /*启用PLL2 的所有PFD输出*/
    CCM_ANALOG->PFD_528 &= ~(0x80U) ;      //开启PLL2 PFD0
    CCM_ANALOG->PFD_528 &= ~(0x8000U) ;    //开启PLL2 PFD1
    CCM_ANALOG->PFD_528 &= ~(0x800000U) ;  //开启PLL2 PFD2
    CCM_ANALOG->PFD_528 &= ~(0x80000000U); //开启PLL2 PFD3
    /*禁用PLL3 的所有PFD输出*/
    CCM_ANALOG->PFD_480 |=(0x80U) ;      //关闭PLL3 PFD0
    CCM_ANALOG->PFD_480 |=(0x8000U) ;    //关闭PLL3 PFD1
    CCM_ANALOG->PFD_480 |=(0x800000U) ;  //关闭PLL3 PFD2
    CCM_ANALOG->PFD_480 |=(0x80000000U); //关闭PLL3 PFD3
    /*设置PLL3 的PFD输出频率*/
    CCM_ANALOG->PFD_480 &= ~(0x3FU);   //清零PLL3 PFD0 时钟分频
    CCM_ANALOG->PFD_480 &= ~(0x3F00U); //清零PLL3 PFD1 时钟分频
    CCM_ANALOG->PFD_480 &= ~(0x3F00U); //清零PLL3 PFD2 时钟分频
    CCM_ANALOG->PFD_480 &= ~(0x3F00U); //清零PLL3 PFD3 时钟分频
    CCM_ANALOG->PFD_480 |= (0xC << 0); //设置PLL3 PFD0 输出频率为 720M
    CCM_ANALOG->PFD_480 |= (0x10 << 8); //设置PLL3 PFD0 输出频率为 540M
    CCM_ANALOG->PFD_480 |= (0x11 << 16); //设置PLL3 PFD0 输出频率为 508.2M
    CCM_ANALOG->PFD_480 |= (0x13 << 24); //设置PLL3 PFD0 输出频率为 454.7M
    /*启用PLL3 的所有PFD输出*/
    CCM_ANALOG->PFD_480 &= ~(0x80U) ;      //开启PLL3 PFD0
    CCM_ANALOG->PFD_480 &= ~(0x8000U) ;    //开启PLL3 PFD1
    CCM_ANALOG->PFD_480 &= ~(0x800000U) ;  //开启PLL3 PFD2
    CCM_ANALOG->PFD_480 &= ~(0x80000000U); //开启PLL3 PFD3
  
2.4外设时钟设置
选择具体的时钟和最后的分频。
    /******************第四层时钟设置--外设****************/
    CCM->CSCDR1 &= ~(0x01 << 6); //设置UART选择 PLL3 / 6 = 80MHz
    CCM->CSCDR1 &= ~(0x3F);     //清零
    CCM->CSCDR1 |= ~(0x01 << 0); //设置串口根时钟分频值为1,UART根时钟频率为:80M / (dev + 1) = 40MHz



















![C语言经典练习3——[NOIP2008]ISBN号码与圣诞树](https://img-blog.csdnimg.cn/direct/2bdf598137354eb0a783f47140c5e4df.png)