搜索
bottom↓
回复: 2

SetSysClockTo72(void) 解析

[复制链接]

出0入0汤圆

发表于 2013-12-3 10:46:07 | 显示全部楼层 |阅读模式
本帖最后由 yanjiesh 于 2013-12-3 10:46 编辑

/**
  * @brief  Sets System clock frequency to 72MHz and configure HCLK, PCLK2
  *         and PCLK1 prescalers.
  * @note   This function should be used only after reset.
  * @param  None
  * @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;                        // #define  FLASH_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);                    //#define  FLASH_ACR_LATENCY                   ((uint8_t)0x03)               /*!< LATENCY[2:0] bits (Latency) */
    FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;                                    //#define  FLASH_ACR_LATENCY_2                 ((uint8_t)0x02)               /*!< Bit 1 */
                                                                                                                // 请教高手 FLASH->ACR 是一个寄存器吗? 好像手册里没能找到啊?哪位能告知下 谢谢。
    /* HCLK = SYSCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;                                                //#define  RCC_CFGR_HPRE_DIV1                  ((uint32_t)0x00000000)        /*!< SYSCLK not divided */
      
    /* PCLK2 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;                                        //#define  RCC_CFGR_PPRE2_DIV1                 ((uint32_t)0x00000000)        /*!< HCLK not divided */

        /* PCLK1 = HCLK */
    RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;                                        //#define  RCC_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 */
    /* #define  RCC_CFGR2_PREDIV2                  ((uint32_t)0x000000F0)        !< PREDIV2[3:0] bits 反相与后即0x0000 不分频 */
    /*  #define  RCC_CFGR2_PLL2MUL                  ((uint32_t)0x00000F00)      !< PLL2MUL[3:0] bits  反相与后为0x0000,保留。*/
    /* #define  RCC_CFGR2_PREDIV1                  ((uint32_t)0x0000000F)        !< PREDIV1[3:0] bits  反相与后即0x0000 不分频。*/
    /* #define  RCC_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);
/*  #define  RCC_CFGR2_PREDIV2_DIV5             ((uint32_t)0x00000040)       PREDIV2: 0x0100, 即5分频。< PREDIV2 input clock divided by 5 */
/*  #define  RCC_CFGR2_PLL2MUL8                 ((uint32_t)0x00000600)         PLL2MUL:0x0110,即 PLL2 8倍频。!< PLL2 input clock * 8 */
/* #define  RCC_CFGR2_PREDIV1SRC_PLL2          ((uint32_t)0x00010000)        bit16=1 表明PLL2 是 PREDIV1的输入时钟源。!< PLL2 selected as PREDIV1 entry clock source */
/*  #define  RCC_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;        // #define  RCC_CR_PLL2ON                       ((uint32_t)0x04000000)        /*!< PLL2 enable */
   
    /* Wait till PLL2 is ready */
    while((RCC->CR & RCC_CR_PLL2RDY) == 0)
    {
    }

    /* #define  RCC_CFGR_PLLXTPRE                 ((uint32_t)0x00020000)       !< HSE divider for PLL entry */
    /* #define  RCC_CFGR_PLLSRC                     ((uint32_t)0x00010000)       !< PLL entry clock source */
    /*  #define  RCC_CFGR_PLLMULL                  ((uint32_t)0x003C0000)      0x0000 0000 0011 1100 0000 0000 0000 0000   !< PLLMUL[3:0] bits (PLL multiplication factor) */
    /* 以上操作即为复位相关设置住*/

   /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
    RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
   /*    #define  RCC_CFGR_PLLXTPRE_PREDIV1          ((uint32_t)0x00000000)       !< PREDIV1 clock not divided for PLL entry */
   /*   #define  RCC_CFGR_PLLSRC_PREDIV1            ((uint32_t)0x00010000)        !< PREDIV1 clock selected as PLL entry clock source */
   /* #define  RCC_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 */
  /*  #define  RCC_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 */
/* #define  RCC_CFGR_SW                         ((uint32_t)0x00000003)        !< SW[1:0] bits (System clock Switch)  */

    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));                //本句为设置HSI作为系统时钟
/* #define  RCC_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 */

/* #define  RCC_CFGR_SWS                        ((uint32_t)0x0000000C)       !< SWS[1:0] 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 */
  }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2013-12-4 08:53:23 | 显示全部楼层
自己补充一下 学了很久 但是一直能深入 阻碍主要是C语言的技能水平 逐步学习后 想与大家交流下

出0入0汤圆

 楼主| 发表于 2013-12-5 13:02:05 | 显示全部楼层
看来 此帖不吸引人 要么高手不愿赐教 要么新手也是看了头晕 呵呵 只当抛砖引玉了
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-29 11:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表