HC32F4 时钟的控制
以下时钟的控制是以官方的参考例程为准,具体需要什么频率自己设置:
1.如果不进行时钟的初始化,默认走的是内部的中速时钟 8MHZ,所有的时钟都是8MHZ。上电初始化调 用 system_hc32f4a0.c 里的 SystemCoreClockUpdate() 函数,进行时钟的初始化。
void SystemCoreClockUpdate(void)
{
…
tmp = M4_CMU->CKSWR & CMU_CKSWR_CKSW;
switch(tmp) // tmp = 1
{
case 0x00U: /* use internal high speed RC /
SystemCoreClock = HRC_VALUE;
break;
case 0x01U: / use internal middle speed RC /
SystemCoreClock = MRC_VALUE; // 调用该分支
break;
case 0x02U: / use internal low speed RC */
SystemCoreClock = LRC_VALUE;
break;
…
}
}
2.以usart 文件夹下 usart_polling 工程里的例程为例,进行讲解:
void BSP_CLK_Init(void)
{
stc_clk_xtal_init_t stcXtalInit;
stc_clk_pllh_init_t stcPLLHInit;
/* PCLK0, HCLK Max 240MHz */
/* PCLK1, PCLK4 Max 120MHz */
/* PCLK2, PCLK3 Max 60MHz */
/* EX BUS Max 120MHz */
CLK_ClkDiv(CLK_CATE_ALL, \
(CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 | \
CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 | \
CLK_HCLK_DIV1));
CLK_XtalStructInit(&stcXtalInit);
/* Config Xtal and enable Xtal */
stcXtalInit.u8XtalMode = CLK_XTALMODE_OSC;
stcXtalInit.u8XtalDrv = CLK_XTALDRV_LOW; // 低速外部时钟
stcXtalInit.u8XtalState = CLK_XTAL_ON; // 开启外部时钟
stcXtalInit.u8XtalStb = CLK_XTALSTB_2MS;
CLK_XtalInit(&stcXtalInit); // 重新配置为外部时钟
(void)CLK_PLLHStructInit(&stcPLLHInit);
/* VCO = (8/1)*120 = 960MHz*/
stcPLLHInit.u8PLLState = CLK_PLLH_ON;
stcPLLHInit.PLLCFGR = 0UL;
stcPLLHInit.PLLCFGR_f.PLLM = 1UL - 1UL;
stcPLLHInit.PLLCFGR_f.PLLN = 120UL - 1UL;
stcPLLHInit.PLLCFGR_f.PLLP = 4UL - 1UL;
stcPLLHInit.PLLCFGR_f.PLLQ = 4UL - 1UL;
stcPLLHInit.PLLCFGR_f.PLLR = 4UL - 1UL;
stcPLLHInit.PLLCFGR_f.PLLSRC = CLK_PLLSRC_XTAL;
(void)CLK_PLLHInit(&stcPLLHInit); //重新配置参数
…省略
CLK_SetSysClkSrc(CLK_SYSCLKSOURCE_PLLH); 调用初始化时钟
}
再次调用以下函数
void CLK_SetSysClkSrc(uint8_t u8Src)
{
…
SystemCoreClockUpdate();
}
通过再次调用 SystemCoreClockUpdate(); 完成外部时钟配置的初始化:
void SystemCoreClockUpdate(void)
{
…
tmp = M4_CMU->CKSWR & CMU_CKSWR_CKSW;
switch(tmp) // tmp = 5
{
....................
case 0x05U: /* use PLLH */
/* PLLCLK = ((pllsrc / pllm) * plln) / pllp */
pllp = (uint32_t)((M4_CMU->PLLHCFGR >> CMU_PLLHCFGR_PLLHP_POS) & 0x0FUL);
plln = (uint32_t)((M4_CMU->PLLHCFGR >> CMU_PLLHCFGR_PLLHN_POS) & 0xFFUL);
pllm = (uint32_t)((M4_CMU->PLLHCFGR >> CMU_PLLHCFGR_PLLHM_POS) & 0x03UL);
/* use external high speed OSC as PLL source */
if (0UL == bM4_CMU->PLLHCFGR_b.PLLSRC)
{
SystemCoreClock = (XTAL_VALUE) / (pllm + 1UL) * (plln + 1UL) / (pllp + 1UL); // SystemCoreClock = 240 MHZ
}
/* use internal high RC as PLL source */
else
{
SystemCoreClock = (HRC_VALUE) / (pllm + 1UL) * (plln + 1UL) / (pllp + 1UL);
}
break;
default:
break;
}
}
得到系统时钟是:ystemCoreClock = 240 MHZ
通过分频函数 CLK_ClkDiv(CLK_CATE_ALL,
(CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 |
CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2 | CLK_EXCLK_DIV2 |
CLK_HCLK_DIV1));
可以的到如下的频率,
/* PCLK0, HCLK Max 240MHz /
/ PCLK1, PCLK4 Max 120MHz /
/ PCLK2, PCLK3 Max 60MHz */
3.还可以通过 CLK_GetClockFreq(); 获得每个时钟源的频率
stc_clk_freq_t CklFreq;
CLK_GetClockFreq(&CklFreq);
en_result_t CLK_GetClockFreq(stc_clk_freq_t *pstcClkFreq)
{
en_result_t enRet = Ok;
uint32_t plln;
uint32_t pllp;
uint32_t pllm;
if (NULL == pstcClkFreq)
{
enRet = ErrorInvalidParameter;
}
else
{
switch (READ_REG8_BIT(M4_CMU->CKSWR, CMU_CKSWR_CKSW))
{
case CLK_SYSCLKSOURCE_HRC:
/* HRC is used to system clock */
pstcClkFreq->sysclkFreq = HRC_VALUE;
break;
case CLK_SYSCLKSOURCE_MRC:
/* MRC is used to system clock */
pstcClkFreq->sysclkFreq = MRC_VALUE;
break;
case CLK_SYSCLKSOURCE_LRC:
/* LRC is used to system clock */
pstcClkFreq->sysclkFreq = LRC_VALUE;
break;
case CLK_SYSCLKSOURCE_XTAL:
/* XTAL is used to system clock */
pstcClkFreq->sysclkFreq = XTAL_VALUE;
break;
case CLK_SYSCLKSOURCE_XTAL32:
/* XTAL32 is used to system clock */
pstcClkFreq->sysclkFreq = HRC_VALUE;
break;
case CLK_SYSCLKSOURCE_PLLH:
/* PLLHP is used as system clock. */
pllp = (uint32_t)((M4_CMU->PLLHCFGR >> CMU_PLLHCFGR_PLLHP_POS) & 0x0FUL);
plln = (uint32_t)((M4_CMU->PLLHCFGR >> CMU_PLLHCFGR_PLLHN_POS) & 0xFFUL);
pllm = (uint32_t)((M4_CMU->PLLHCFGR >> CMU_PLLHCFGR_PLLHM_POS) & 0x03UL);
/* fpll = ((pllin / pllm) * plln) / pllp */
if (CLK_PLLSRC_XTAL == READ_REG32_BIT(M4_CMU->PLLHCFGR, CMU_PLLHCFGR_PLLSRC))
{
pstcClkFreq->sysclkFreq = ((XTAL_VALUE/(pllm + 1UL))*(plln + 1UL))/(pllp + 1UL);
}
else
{
pstcClkFreq->sysclkFreq = ((HRC_VALUE/(pllm + 1UL))*(plln + 1UL))/(pllp + 1UL);
}
break;
default:
break;
}
/* Get hclk. */
pstcClkFreq->hclkFreq = pstcClkFreq->sysclkFreq >> \
(READ_REG32_BIT(M4_CMU->SCFGR, CMU_SCFGR_HCLKS) >> CMU_SCFGR_HCLKS_POS);
/* Get exck. */
pstcClkFreq->exckFreq = pstcClkFreq->sysclkFreq >> \
(READ_REG32_BIT(M4_CMU->SCFGR, CMU_SCFGR_EXCKS) >> CMU_SCFGR_EXCKS_POS);
/* Get pclk0. */
pstcClkFreq->pclk0Freq = pstcClkFreq->sysclkFreq >> \
(READ_REG32_BIT(M4_CMU->SCFGR, CMU_SCFGR_PCLK0S) >> CMU_SCFGR_PCLK0S_POS);
/* Get pclk1. */
pstcClkFreq->pclk1Freq = pstcClkFreq->sysclkFreq >> \
(READ_REG32_BIT(M4_CMU->SCFGR, CMU_SCFGR_PCLK1S) >> CMU_SCFGR_PCLK1S_POS);
/* Get pclk2. */
pstcClkFreq->pclk2Freq = pstcClkFreq->sysclkFreq >> \
(READ_REG32_BIT(M4_CMU->SCFGR, CMU_SCFGR_PCLK2S) >> CMU_SCFGR_PCLK2S_POS);
/* Get pclk3. */
pstcClkFreq->pclk3Freq = pstcClkFreq->sysclkFreq >> \
(READ_REG32_BIT(M4_CMU->SCFGR, CMU_SCFGR_PCLK3S) >> CMU_SCFGR_PCLK3S_POS);
/* Get pclk4. */
pstcClkFreq->pclk4Freq = pstcClkFreq->sysclkFreq >> \
(READ_REG32_BIT(M4_CMU->SCFGR, CMU_SCFGR_PCLK4S) >> CMU_SCFGR_PCLK4S_POS);
}
return enRet;
}
4.以上所有的参考函数都是通过单步仿真,数据真实有效,希望能够帮助到你。