yanjiesh 发表于 2013-12-3 10:46:07

SetSysClockTo72(void) 解析

本帖最后由 yanjiesh 于 2013-12-3 10:46 编辑

/**
* @briefSets System clock frequency to 72MHz and configure HCLK, PCLK2
*         and PCLK1 prescalers.
* @note   This function should be used only after reset.
* @paramNone
* @retval None
*/
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/   
/* Enable HSE */   
RCC->CR |= ((uint32_t)RCC_CR_HSEON);   // RCC_CR_HSEON 定义为 0x00010000, 即CR寄存器的第十六位设为1.R寄存器的第十六位设为1.

/* Wait till HSE is ready and if Time out is reached exit */
do
{
    HSEStatus = RCC->CR & RCC_CR_HSERDY;                                // RCC_CR_HSERDY 定义为 ((uint32_t)0x00020000),即CR 寄存器的第十七位为1,表示External high-speed clock ready flag.
    StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));                        //HSE_STARTUP_TIMEOUT   定义为 ((uint16_t)0x0500) /*!< Time out for HSE start up */

if ((RCC->CR & RCC_CR_HSERDY) != RESET)                //typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;换句话 成功了就执行以下内容

{
    HSEStatus = (uint32_t)0x01;
}
else
{
    HSEStatus = (uint32_t)0x00;
}

if (HSEStatus == (uint32_t)0x01)                                //成功时,,,
{
    /* Enable Prefetch Buffer */
    FLASH->ACR |= FLASH_ACR_PRFTBE;                        // #defineFLASH_ACR_PRFTBE                  ((uint8_t)0x10)               /*!< Prefetch Buffer Enable */
/* ● 等待时间:可以随时更改的用于读取操作的等待状态的数量。
    ● 预取缓冲区(2个64位):在每一次复位以后被自动打开,由于每个缓冲区的大小(64位)与闪存的带宽相同,因此只通过需一次读闪存的操作即可更新整个缓冲区的内容。由于预取缓冲区的存在,CPU可以工作在更高的主频。CPU每次取指最多为32位的字,取一条指令时,下一条指令已经在缓冲区中等待。
    ● 半周期:用于功耗优化。
*/

    /* Flash 2 wait state */
    FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);                    //#defineFLASH_ACR_LATENCY                   ((uint8_t)0x03)               /*!< LATENCY bits (Latency) */
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;                                    //#defineFLASH_ACR_LATENCY_2               ((uint8_t)0x02)               /*!< Bit 1 */
                                                                                                                // 请教高手 FLASH->ACR 是一个寄存器吗? 好像手册里没能找到啊?哪位能告知下 谢谢。
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;                                                //#defineRCC_CFGR_HPRE_DIV1                  ((uint32_t)0x00000000)      /*!< SYSCLK not divided */
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;                                        //#defineRCC_CFGR_PPRE2_DIV1               ((uint32_t)0x00000000)      /*!< HCLK not divided */

      /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;                                        //#defineRCC_CFGR_PPRE1_DIV2               ((uint32_t)0x00000400)      /*!< HCLK divided by 2 */以上三个分频设置均在RCC_CFGR寄存器中。位置分别是:bit7:4的AHB分频;Bit13:11                                                              的APB2 和 Bit 10:8 的 APB1。

#ifdef STM32F10X_CL
    /* Configure PLLs ------------------------------------------------------*/
    /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
    /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
    /* #defineRCC_CFGR2_PREDIV2                  ((uint32_t)0x000000F0)      !< PREDIV2 bits 反相与后即0x0000 不分频 */
    /*#defineRCC_CFGR2_PLL2MUL                  ((uint32_t)0x00000F00)      !< PLL2MUL bits反相与后为0x0000,保留。*/
    /* #defineRCC_CFGR2_PREDIV1                  ((uint32_t)0x0000000F)      !< PREDIV1 bits反相与后即0x0000 不分频。*/
    /* #defineRCC_CFGR2_PREDIV1SRC               ((uint32_t)0x00010000)   bit16=1,反相与后表明HSE作为PREDIV1的时钟源 !< PREDIV1 entry clock source */

    RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |                       
                              RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
/*#defineRCC_CFGR2_PREDIV2_DIV5             ((uint32_t)0x00000040)       PREDIV2: 0x0100, 即5分频。< PREDIV2 input clock divided by 5 */
/*#defineRCC_CFGR2_PLL2MUL8               ((uint32_t)0x00000600)         PLL2MUL:0x0110,即 PLL2 8倍频。!< PLL2 input clock * 8 */
/* #defineRCC_CFGR2_PREDIV1SRC_PLL2          ((uint32_t)0x00010000)      bit16=1 表明PLL2 是 PREDIV1的输入时钟源。!< PLL2 selected as PREDIV1 entry clock source */
/*#defineRCC_CFGR2_PREDIV1_DIV5             ((uint32_t)0x00000004)      PREDIV1:0x0100,即5分频。!< PREDIV1 input clock divided by 5 */
    RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
                           RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/*PLL2和PLL3由HSE通过一个可配置的分频器提供时钟。必须在使能每个PLL之前完成PLL的配置(选择时钟源、预分频系数和倍频系数等),同时应该在它们的输入时钟稳定(就绪位)后才能使能。一旦使能了PLL,这些参数将不能再被改变。
        当改变主PLL的输入时钟源时,必须在选中了新的时钟源(通过时钟配置寄存器(RCC_CFGR) 的PLLSRC位)之后才能关闭原来的时钟源。
       如果使能了时钟中断寄存器(RCC_CIR),可以在PLL就绪时产生一个中断。
*/
    /* Enable PLL2 */
    RCC->CR |= RCC_CR_PLL2ON;      // #defineRCC_CR_PLL2ON                     ((uint32_t)0x04000000)      /*!< PLL2 enable */
   
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }

    /* #defineRCC_CFGR_PLLXTPRE               ((uint32_t)0x00020000)       !< HSE divider for PLL entry */
    /* #defineRCC_CFGR_PLLSRC                     ((uint32_t)0x00010000)       !< PLL entry clock source */
    /*#defineRCC_CFGR_PLLMULL                  ((uint32_t)0x003C0000)      0x0000 0000 0011 1100 0000 0000 0000 0000   !< PLLMUL bits (PLL multiplication factor) */
    /* 以上操作即为复位相关设置住*/
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
   /*    #defineRCC_CFGR_PLLXTPRE_PREDIV1          ((uint32_t)0x00000000)       !< PREDIV1 clock not divided for PLL entry */
   /*   #defineRCC_CFGR_PLLSRC_PREDIV1            ((uint32_t)0x00010000)      !< PREDIV1 clock selected as PLL entry clock source */
   /* #defineRCC_CFGR_PLLMULL9                  ((uint32_t)0x001C0000)    0x0000 0000 0001 1100 0000 0000 0000 0000 PLLMUL: 0x0111   !< PLL input clock * 9 */
   RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
                            RCC_CFGR_PLLMULL9);
#else   
    /*PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
                                        RCC_CFGR_PLLMULL));
    RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */

    /* Enable PLL */
/*#defineRCC_CR_PLLON                        ((uint32_t)0x01000000)    0x0000 0001    !< PLL enable */

    RCC->CR |= RCC_CR_PLLON;

    /* Wait till PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
   
    /* Select PLL as system clock source */
/* #defineRCC_CFGR_SW                         ((uint32_t)0x00000003)      !< SW bits (System clock Switch)*/

    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));                //本句为设置HSI作为系统时钟
/* #defineRCC_CFGR_SW_PLL                     ((uint32_t)0x00000002)      !< PLL selected as system clock */
    RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;                                    //本句设置PLL输出为系统时钟

    /* Wait till PLL is used as system clock source */

/* #defineRCC_CFGR_SWS                        ((uint32_t)0x0000000C)       !< SWS bits (System Clock Switch Status) */

    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)   //如果检测到CFGR寄存器的bit3:2位是10--即PLL输出作为系统时钟,即可跳出等待动作,结束本函数。
    {
    }
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
         configuration. User can add here some code to deal with this error */
}
}

yanjiesh 发表于 2013-12-4 08:53:23

自己补充一下 学了很久 但是一直能深入 阻碍主要是C语言的技能水平 逐步学习后 想与大家交流下

yanjiesh 发表于 2013-12-5 13:02:05

看来 此帖不吸引人 要么高手不愿赐教 要么新手也是看了头晕 呵呵 只当抛砖引玉了 {:lol:}
页: [1]
查看完整版本: SetSysClockTo72(void) 解析