打印
[其他ST产品]

STM32时钟初始化研究

[复制链接]
169|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
qn7a12|  楼主 | 2023-1-30 21:11 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
时钟是一个MCU的脉搏,研究清楚脉搏才能更清楚的把握整个MCU的运行。本文主要研究STM32F10x系列,利用官方库文件进行初始化设置。开发环境为MDK4.6,库文件V3.5版本,STM32参考手册。

利用MDK自带仿真器,仿真发现。芯片启动首先打开system_stmf10x.c文件,调用void SystemInit(void)函数。下面贴上代码和中文注释

void SystemInit (void)
{
        /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
        /* Set HSION bit */
        RCC->CR |= (uint32_t)0x00000001;        //内部高速时钟使能
       
       
        /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
        //SW:HSI(内部高速8M RC震荡器)作为时钟源
        //AHB(SYSCLK)不分频
        //APB1,APB2不分频
        // PCLK2 2分频后作为ADC时钟
        // HSI时钟2分频后作为PLL输入时钟
        //MCO没有时钟输出
        RCC->CFGR &= (uint32_t)0xF8FF0000;

       
        /* Reset HSEON, CSSON and PLLON bits */
        //HSE振荡器关闭, 时钟安全系统监测器关闭PLL关闭
        RCC->CR &= (uint32_t)0xFEF6FFFF;


        /* Reset HSEBYP bit */
        //清零来旁路外部晶体振荡器。只有在外部4-25MHz振荡器关闭的情况下,才能写入该位。
        RCC->CR &= (uint32_t)0xFFFBFFFF;

       
        /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
        //HSI时钟2分频后作为PLL输入时钟
        //HSE不分频器作为PLL输入
        //0000:PLL 2倍频输出
        //0:PLL时钟1.5倍分频作为USB时钟
        RCC->CFGR &= (uint32_t)0xFF80FFFF;

       
        /* Disable all interrupts and clear pending bits  */
        RCC->CIR = 0x009F0000;

       
        /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
        /* Configure the Flash Latency cycles and enable prefetch buffer */
        SetSysClock();

       
        SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
}



使用特权

评论回复
评论
qn7a12 2023-1-30 22:12 回复TA
———————————————— 版权声明:本文为CSDN博主「notepi」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/wandermen/article/details/46351559 
沙发
qn7a12|  楼主 | 2023-1-30 22:12 | 只看该作者
主要是用于重置RCC寄存器,既重置STM32的时钟树。


初始化重置时钟后的时钟树图:

使用特权

评论回复
板凳
qn7a12|  楼主 | 2023-1-30 22:14 | 只看该作者
上文中还有个函数叫SetSysClock用于设置MCU系统时钟,贴入代码:
static void SetSysClock(void)
{

        #ifdef SYSCLK_FREQ_HSE
          SetSysClockToHSE();
        #elif defined SYSCLK_FREQ_24MHz
          SetSysClockTo24();
        #elif defined SYSCLK_FREQ_36MHz
          SetSysClockTo36();
        #elif defined SYSCLK_FREQ_48MHz
          SetSysClockTo48();
        #elif defined SYSCLK_FREQ_56MHz
          SetSysClockTo56();  
        #elif defined SYSCLK_FREQ_72MHz
          SetSysClockTo72();
        #endif
        /* If none of the define above is enabled, the HSI is used as System clock source (default after reset) */
}

static void SetSysClockTo72(void)
{
        __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

        /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/   


        /* Enable HSE */   
        /*define C_CR_HSEON                        (int32_t)0x00010000)   */
        /*!< External High Speed clock enable */
        //开启HSE振荡器
        RCC->CR |= ((uint32_t)RCC_CR_HSEON);

       
        /* Wait till HSE is ready and if Time out is reached exit */
        //等待HSE起振
        //#define HSEStartUp_TimeOut   HSE_STARTUP_TIMEOUT
        //#define HSE_STARTUP_TIMEOUT   ((uint16_t)0x0500)
        /*!< Time out for HSE start up */
        do
        {
                HSEStatus = RCC->CR & RCC_CR_HSERDY;
                StartUpCounter++;  
        } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

        if ((RCC->CR & RCC_CR_HSERDY) != RESET)
        {
                HSEStatus = (uint32_t)0x01;
        }
        else
        {
                HSEStatus = (uint32_t)0x00;
        }  
       
        if (HSEStatus == (uint32_t)0x01)
        {
                /* Enable Prefetch Buffer */
                FLASH->ACR |= FLASH_ACR_PRFTBE;
               
                /* Flash 2 wait state */
                FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
                FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;  

                /* HCLK = SYSCLK */
                //#define  RCC_CFGR_HPRE_DIV1      ((uint32_t)0x00000000)        /*!< SYSCLK not divided */
                //HCLK  :AHB总线时钟,由系统时钟SYSCLK 分频得到,不分频
                RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;


                /* PCLK2 = HCLK */
                // #define  RCC_CFGR_PPRE2_DIV1    ((uint32_t)0x00000000)        /*!< HCLK not divided */
                //APB2由AHB分频而来,不分频。
                RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

               
                /* PCLK1 = HCLK */
                //#define  RCC_CFGR_PPRE1_DIV2                 ((uint32_t)0x00000400)        /*!< HCLK divided by 2 */
                //APB1由AHB分频而来,2分频。
                RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

                /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
                //设置PLLCLK时钟源为HSE,且PLL9倍频
                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);

               
                /* Enable PLL */
                //使能倍频器
                RCC->CR |= RCC_CR_PLLON;


                /* Wait till PLL is ready */
                //等待PLL稳定运行
                while((RCC->CR & RCC_CR_PLLRDY) == 0)
                {
                }
               
                /* Select PLL as system clock source */
                //设置PLL作为系统时钟源
                RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
                RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;   

                /* Wait till PLL is used as system clock source */
                //等待PLL用于系统时钟源
                while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
                {
                }
                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 */
                }

}

使用特权

评论回复
地板
qn7a12|  楼主 | 2023-1-30 22:18 | 只看该作者
初始化重置时钟后的时钟树图:

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

402

帖子

0

粉丝