首页 > 其他分享 >CH32V307 使用PLL2配置系统时钟

CH32V307 使用PLL2配置系统时钟

时间:2023-11-04 14:23:36浏览次数:34  
标签:PREDIV1 HSE tmpreg CH32V307 时钟 uint32 PLL2 RCC

在进行系统时钟配置时,可以选择HSI、HSE、PLL作为系统时钟来源。而PLL时钟来源有几下几种,如下图:

 

以下为CH32V307时钟树框图,如下图:

 

关于使用HSE或HSI作为系统时钟,在CH32V307 EVT都有相应例程,在system_ch32v30x.c文件中直接使用相关宏定义即可,如下图:

 

本篇文章主要讲解使用PLL2配置系统时钟的配置方式,以配置96MHz系统时钟为例,代码如下。注意该方式只适用于CH32V305、307系列,其他CH32V30x系列时钟框图不同,该方法不适用。

/*********************************************************************
 * @fn      SetSysClockTo96
 *
 * @brief   Sets System clock frequency to 96MHz and configure HCLK, PCLK2 and PCLK1 prescalers.
 *
 * @return  none
 */
static void SetSysClockTo96(void)
{
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

  RCC->CTLR |= ((uint32_t)RCC_HSEON);

  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CTLR & RCC_HSERDY;
    StartUpCounter++;
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CTLR & RCC_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }

  if (HSEStatus == (uint32_t)0x01)
  {
    /* HCLK = SYSCLK */
    RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV1;
    /* PCLK2 = HCLK */
    RCC->CFGR0 |= (uint32_t)RCC_PPRE2_DIV1;
    /* PCLK1 = HCLK */
    RCC->CFGR0 |= (uint32_t)RCC_PPRE1_DIV2;

#ifdef CH32V30x_D8C
    RCC_PREDIV2Config(RCC_PREDIV2_Div1);

    RCC_PLL2Config(RCC_PLL2Mul_4);

    RCC_PLL2Cmd(ENABLE);
    while((RCC->CTLR & (1<<27)) == 0)
    {
    }

#endif


    RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_PLLSRC | RCC_PLLXTPRE |
                                        RCC_PLLMULL));

#ifdef CH32V30x_D8
        /*  PLL configuration: PLLCLK = HSE * 12 = 96 MHz */
        RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL12);
#else
        /* PLL configuration: PLLCLK = HSE/1*4/2*6 = 96 MHz */
        RCC->CFGR0 |= (uint32_t)(RCC_PLLSRC_HSE | RCC_PLLXTPRE_HSE | RCC_PLLMULL6_EXTEN);
        RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div2);
#endif

    /* Enable PLL */
    RCC->CTLR |= RCC_PLLON;
    /* Wait till PLL is ready */
    while((RCC->CTLR & RCC_PLLRDY) == 0)
    {
    }
    /* Select PLL as system clock source */
    RCC->CFGR0 &= (uint32_t)((uint32_t)~(RCC_SW));
    RCC->CFGR0 |= (uint32_t)RCC_SW_PLL;
    /* Wait till PLL is used as system clock source */
    while ((RCC->CFGR0 & (uint32_t)RCC_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
         */
  }
}

 

该部分代码在使用HSE配置系统时钟的基本上修改,加粗标红部分为添加部分。关于这几行代码,解释如下:

RCC_PREDIV2Config(RCC_PREDIV2_Div1);

/*********************************************************************
* @fn RCC_PREDIV2Config
*
* @brief Configures the PREDIV2 division factor.
*
* @param RCC_PREDIV2_Div - specifies the PREDIV2 clock division factor.
* This parameter can be RCC_PREDIV2_Divx where x:[1,16]
* Note-
* - This function must be used only when both PLL2 and PLL3 are disabled.
*
* @return none
*/
void RCC_PREDIV2Config(uint32_t RCC_PREDIV2_Div)
{
uint32_t tmpreg = 0;

tmpreg = RCC->CFGR2;
tmpreg &= ~CFGR2_PREDIV2;
tmpreg |= RCC_PREDIV2_Div;
RCC->CFGR2 = tmpreg;
}

该函数主要对 时钟配置寄存器2(RCC_CFGR2)进行配置,设置PREDIV2分频因子为1分频,即不分频。

 

RCC_PLL2Config(RCC_PLL2Mul_4);

/*********************************************************************
 * @fn      RCC_PLL2Config
 *
 * @brief   Configures the PLL2 multiplication factor.
 *
 * @param   RCC_PLL2Mul - specifies the PLL2 multiplication factor.
 *            This parameter can be RCC_PLL2Mul_x where x:{[8,14], 16, 20}
 *          Note-
 *          - This function must be used only when the PLL2 is disabled.
 *
 * @return  none
 */
void RCC_PLL2Config(uint32_t RCC_PLL2Mul)
{
    uint32_t tmpreg = 0;

    tmpreg = RCC->CFGR2;
    tmpreg &= ~CFGR2_PLL2MUL;
    tmpreg |= RCC_PLL2Mul;
    RCC->CFGR2 = tmpreg;
}

该函数主要对 时钟配置寄存器2(RCC_CFGR2)进行配置,设置PLL2倍频因子,此处设置4倍频。

 

RCC_PLL2Cmd(ENABLE);

/*********************************************************************
* @fn RCC_PLL2Cmd
*
* @brief Enables or disables the PLL2.
*
* @param NewState - new state of the PLL2. This parameter can be
* ENABLE or DISABLE.
* Note-
* - The PLL2 can not be disabled if it is used indirectly as system clock
* (i.e. it is used as PLL clock entry that is used as System clock).
*
* @return none
*/
void RCC_PLL2Cmd(FunctionalState NewState)
{
if(NewState)
{
RCC->CTLR |= (1 << 26);
}
else
{
RCC->CTLR &= ~(1 << 26);
}
}

该函数主要对 时钟控制寄存器(RCC_CTLR)进行配置,使能开启PLL2时钟。

 

        while((RCC->CTLR & (1<<27)) == 0)
        {
        }

该函数主要等待PLL2时钟就绪锁定,如下图:

 

RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div2);

/*********************************************************************
 * @fn      RCC_PREDIV1Config
 *
 * @brief   Configures the PREDIV1 division factor.
 *
 * @param   RCC_PREDIV1_Source - specifies the PREDIV1 clock source.
 *            RCC_PREDIV1_Source_HSE - HSE selected as PREDIV1 clock
 *            RCC_PREDIV1_Source_PLL2 - PLL2 selected as PREDIV1 clock
 *          RCC_PREDIV1_Div - specifies the PREDIV1 clock division factor.
 *            This parameter can be RCC_PREDIV1_Divx where x[1,16]
 *         Note- 
 *         - This function must be used only when the PLL is disabled.
 *
 * @return  none
 */
void RCC_PREDIV1Config(uint32_t RCC_PREDIV1_Source, uint32_t RCC_PREDIV1_Div)
{
    uint32_t tmpreg = 0;

    tmpreg = RCC->CFGR2;
    tmpreg &= ~(CFGR2_PREDIV1 | CFGR2_PREDIV1SRC);
    tmpreg |= RCC_PREDIV1_Source | RCC_PREDIV1_Div;
    RCC->CFGR2 = tmpreg;
}

该函数主要对 时钟配置寄存器2(RCC_CFGR2)进行配置,设置PREDIV1 分频因子为2分频,同时设置PREDIV1的时钟源为PLL2。

 

以上为相关函数的介绍,根据下图圈出部分,如下图:

 可计算出系统时钟大小为:HSE/1*4/2*6,即8Mhz/1*4/2*6=96Mhz

 

标签:PREDIV1,HSE,tmpreg,CH32V307,时钟,uint32,PLL2,RCC
From: https://www.cnblogs.com/liaigu/p/17809282.html

相关文章

  • 嵌入式系统中的时钟:时间的精准管理
    江河入海,知识涌动,这是我参与江海计划的第8篇。时钟在嵌入式系统中扮演着至关重要的角色。它不仅仅用于跟踪时间,还用于同步各种操作和事件。本文将介绍嵌入式系统中时钟的基本原理,并提供代码示例,演示如何在嵌入式系统中使用时钟功能。时钟概述嵌入式系统中的时钟可以分为两种类型:实......
  • 第九周Linux教材第五章学习笔记——定时器及时钟服务
    第五章 定时器及时钟服务5.1硬件定时器定时器是硬件设备,包括时钟源和可编程计数器。时钟源通常是一个晶体振荡器,会产生周期性电信号,以精确的频率驱动计数器。使用一个倒计时值对计数器进行编程,每个时钟信号减1。当计数减为0时,计数器向CPU生成一个定时器中断,将计数值重新加......
  • MAX7219点阵屏四合一—基于CH32V307的应用
    参考链接:https://blog.csdn.net/weixin_46957846/article/details/127352759本篇文章为基于CH32V307的MAX7219级联应用,代码是基于上参考链接代码基础上修改,若有侵权请联系及时删除。该应用测试所用模块为一个四级级联模块,参考链接代码下载应用4个点阵模块均显示均显示同一个字符......
  • [macos]macos 浮动时钟 floating clock
    http://www.splook.com/Software/名字叫 SimpleFloatingClock ......
  • 关于STM32时钟的问题记录
    关于STM32时钟的问题    在读别人建立大型的STM32工程时,会看到主函数中会首先执行一个RCC_Init()的函数,跳转过去之后发现是配置时钟的相关函数。而我自己在写STM32相关代码的时候,似乎从来没有注意过这个问题,我猜想在STM32程序开始执行的时候,也就是复位之后,会首先执行时钟......
  • 指令平均时钟数和运算速度的计算
    题目某计算机的时钟频率未400MHZ,测试该计算机的程序使用4种类型的指令,每种指令的数量及所需指令时钟数(CPI)如下表所示,则该计算机的指令平均时钟数为_____,该计算机的运算速度为_____指令类型指令数目每条指令所需时钟数11600001230000......
  • 一个简单的时钟程序
    publicclassSample2{ privateColorblack=Display.getCurrent().getSystemColor(SWT.COLOR_BLACK); privateColorwhite=Display.getCurrent().getSystemColor(SWT.COLOR_WHITE); privateColoryellow=Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);......
  • 基于labview的数字时钟设计
      1.电子时钟模块   (1)用七个squareled根据的顺序建立一个数字单元,放进簇里,复制粘贴11个。如下图:   (2)创立一个字符串a。 (3)用ctrl+e快捷键打开后面板,画一个whileloop,接下来的操作都在whileloop里完成。 (4)找到FormatDate/TimeString函数,用%y年%m月%......
  • 不受系统时钟影响的精确睡眠
    需求多线程编程需要控制某个线程的执行频率采用系统内建的std::this_thread::sleep_for()函数会受到系统时钟跳变的影响希望使用一个单调递增的时钟作为参考进行休眠。实现截取一段manclock_gettime的原文:CLOCK_REALTIMESystem-wideclockthatm......
  • 10-多比特信号的跨时钟域处理
    1.两级触发器的问题2.多比特跨时钟域的处理方法FIFO是处理跨时钟问题的最常用问题3.格雷码编码处理跨时钟域4.异步FIFO5.多比特跨时钟域的握手处理......