这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 物联网技术 » 【武汉芯源CW32】OTA升级系列之四时钟转换以及Systick微秒精确延时

共8条 1/1 1 跳转至

【武汉芯源CW32】OTA升级系列之四时钟转换以及Systick微秒精确延时

助工
2024-10-07 23:16:31     打赏

【时钟】

CW32L083 内置多路时钟产生电路,通过分频器和多路选择器产生各种不同频率的时钟给 CPU 及各外设使用。系统时钟树结构示意图如图 4-1 系统内部时钟树所示。

系统内部时钟 SysClk 经过分频为 CPU 内核提供高级高性能总线时钟 HCLK,HCLK 时钟经过分频为数字及模拟外

设提供高级外设时钟 PCLK。

系统时钟 SYSCLK 有 5 个时钟源:

● 外部高速振荡器时钟(HSE)

● 外部低速振荡器时钟(LSE)

● HSI 时钟,由内部高速 RC 振荡器时钟(HSIOSC)经过分频产生

● 内部低速 RC 振荡器时钟(LSI)

● PLL 锁相环时钟,由 HSE 时钟或 HSI 时钟经锁相环 PLL 倍频(2~12 倍)产生

image.png

【时钟源选择】

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

image.png

【代码编写】

由于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时钟。

【测试】

在设置时钟成功后,使用打印函数进行验证:

image.png

说明,时钟切换是成功的。

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

1728308079120.jpg

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");
	}
	

}

image.png

【总结】

本篇分享了如何切换HSE时钟,与SysTick实现精准延时。为后面的工程打好基础。

【附源代码】

RCC.zip





关键词: 武汉芯源     时钟     Systick     微秒     精确     延时    

专家
2024-10-08 00:59:38     打赏
2楼

感谢分享


专家
2024-10-08 01:15:57     打赏
3楼

感谢分享


专家
2024-10-08 02:10:53     打赏
4楼

感谢楼主分享


专家
2024-10-08 10:10:44     打赏
5楼

感谢分享


院士
2024-10-10 18:12:32     打赏
6楼

谢谢分享学习了。


专家
2024-10-16 14:12:08     打赏
7楼

内部高速 RC 振荡器时钟(HSIOSC)的精度怎么样?会被温度变化影响不?


专家
2024-10-16 18:52:52     打赏
8楼

这种处理,能获得准确的微秒延时,学习了,谢谢!


共8条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]