【时钟】
CW32L083 内置多路时钟产生电路,通过分频器和多路选择器产生各种不同频率的时钟给 CPU 及各外设使用。系统时钟树结构示意图如图 4-1 系统内部时钟树所示。
系统内部时钟 SysClk 经过分频为 CPU 内核提供高级高性能总线时钟 HCLK,HCLK 时钟经过分频为数字及模拟外
设提供高级外设时钟 PCLK。
系统时钟 SYSCLK 有 5 个时钟源:
● 外部高速振荡器时钟(HSE)
● 外部低速振荡器时钟(LSE)
● HSI 时钟,由内部高速 RC 振荡器时钟(HSIOSC)经过分频产生
● 内部低速 RC 振荡器时钟(LSI)
● PLL 锁相环时钟,由 HSE 时钟或 HSI 时钟经锁相环 PLL 倍频(2~12 倍)产生

【时钟源选择】
CW32L083最高可以跑到64MHz,开发板上板载了16M晶振。因此本次使用外部晶振做为MCU的时钟源,使用PLL进行4倍扩频产生HCLK64M

【代码编写】
由于Flash在不同的时钟需要指定相应的读取延时,所以需要引入cw32l083_flash固件库。并使用RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_FLASH, ENABLE); //打开FLASH时钟,
我们开机时是使用HSI时钟的,所以选RCC_HSE_Enable切换到HSE。再使用RCC_PLL_Enable开启PLL,同时设置FLASH延时为2。代码如下。
void RCC_Config(void)
{
uint8_t res;
//以下从HSI切换到HSE
RCC_AHBPeriphClk_Enable(RCC_AHB_PERIPH_FLASH, ENABLE); //打开FLASH时钟
//以下从HSI切换到PLL
RCC_HSE_Enable(RCC_HSE_MODE_OSC, 16000000, RCC_HSE_DRIVER_NORMAL, RCC_HSE_FLT_CLOSE); //开启外部高速时钟HSE,实际频率需要根据实际晶体频率进行填写
RCC_PLL_Enable(RCC_PLLSOURCE_HSEOSC, 16000000, RCC_PLL_MUL_4); //开启PLL,PLL时钟来源为HSE
FLASH_SetLatency(FLASH_Latency_3); //频率大于24M需要配置FlashWait=2
res = RCC_SysClk_Switch(RCC_SYSCLKSRC_PLL); //切换系统时钟到PLL
if (res == 0x00) //切换系统时钟成功
{
RCC_HSI_Disable(); //切换时钟到PLL后关闭源时钟HSI
}
}如果时钟选择成功,则关闭HSI时钟。
【测试】
在设置时钟成功后,使用打印函数进行验证:

说明,时钟切换是成功的。
时钟切换好后,我们需要用到精确的us延时,因此,添加delay.c/h函数到工程之中。根据相关寄存器图:

1、我们先使用设置systick的时钟,设定1us 溢出一次
void Delay_Init(void)
{
/* SystemFrequency / 1000 1ms溢出一次
* SystemFrequency / 100000 10us溢出一次
* SystemFrequency / 1000000 1us溢出一次
*/
SysTick_Config(RCC_Sysctrl_GetHClkFreq()/1000000);
}2、编写微秒延时,首先向LOAD寄存器,延后向VAL寄存器写入0x00,再打开CTRL位的SysTick_CTRL_ENABLE_Msk。最后等待SysTick_CTRL_COUNTFLAG_Msk置位。
void Delay_US(uint16_t us)
{
SysTick->LOAD = us*64;
SysTick->VAL = 0x00;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while( !(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
}
void Delay_MS(uint16_t ms)
{
while(ms--)
{
Delay_US(1000);
}
}【验证】
在主函数中延时1000毫秒,在串口打印时间,可以看到延时准确:
int32_t main(void)
{
led.LED_Port = CW_GPIOC;
led.LED_Pin = GPIO_PIN_3;
LED_Init(&led);
RCC_Config();
Delay_Init();
UART1_Init(961200);
CW_U1_printf("hello world\r\n");
CW_U1_printf("%d,%c,%x\n",0x30,0x30,0x30);
CW_U1_printf("%s\n%s\n",__FILE__,__TIME__);
CW_U1_printf("HCLK(Hz):%d\r\n",RCC_Sysctrl_GetHClkFreq());
CW_U1_printf("PCLK(Hz):%d\r\n",RCC_Sysctrl_GetPClkFreq());
while(1)
{
led.LED_Toggle(&led);
Delay_MS(1000);
CW_U1_printf("hello world\r\n");
}
}
【总结】
本篇分享了如何切换HSE时钟,与SysTick实现精准延时。为后面的工程打好基础。
【附源代码】
我要赚赏金
