发新帖本帖赏金 30.00元(功能说明)我要提问
返回列表
打印
[CW32L083系列]

CW32L083评估板学习-3.了解系统时钟与延时函数的实现

[复制链接]
982|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#申请原创# @21小跑堂
3.了解系统时钟与延时函数的实现
3.1认识CW32L083的时钟源
CW32L083可选择5种时钟源,包括HSE、LSE、PLL、HSI、LSI

HSE是外部高速时钟,有两种工作模式

可以使用的晶振频率如下

评估板上焊接了一颗16MHz的晶振作为高速时钟源
LSE是外部低速时钟,与HSE类似也有两种工作模式

评估板上接的是32.768K的晶振作为低速时钟源
HSI是内部高速时钟,由内部RC振荡器产生并分频而来,不需要外部电路,比HSE时钟的成本低,启动速度快,HSIOSC时钟频率固定为48MHz,频率精度低于HSE时钟
LSI是内部低速时钟,由内部低速RC振荡器产生,默认频率为 32.8kHz,与HSI类似内部低速RC振荡器不需要外部电路,比LSE时钟的成本低,但精度低于LSE时钟
PLL可对输入时钟源进行倍频输出,通过PLL可以使用最高64MHz的时钟,可用的时钟源有

3.2使用不同的时钟源
在之前创建的工程中并没有特意的配置时钟,通过手册可以知道通电默认使用的HSI频率为8MHz

使用MCO_OUT(PA08)输出HCLK的512分频波形

int32_t main(void)
{
    RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
    RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
    RCC_MCO_OUT(RCC_MCO_SRC_HCLK,RCC_MCO_DIV512);
    while(1)
    {
    }
}
查看输出的波形

15.625KHz x 512 = 8000KHz = 8MHz
接下来使用内部48MHz时钟不分频初始化,需要注意的是CW32的FLASH存储器支持最快24MHz的操作时钟,当系统时钟设置超过24MHz后要设置FLASH的等待周期,且此操作必须在时钟频率切换之前执行,这里输出时改用1024分频

void RCC_HSI_init()
{
    //< 当使用的时钟源HCLK大于24M,小于等于48MHz:设置FLASH 读等待周期为2 cycle >
    __RCC_FLASH_CLK_ENABLE();
    FLASH_SetLatency(FLASH_Latency_2);
    /* HSI使能 */
    RCC_HSI_Enable(RCC_HSIOSC_DIV1); //1分频要在设置之前设置FLASH读等待周期
    RCC_SystemCoreClockUpdate(48000000);
}
int32_t main(void)
{
        RCC_HSI_init();
    RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
    RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
    RCC_MCO_OUT(RCC_MCO_SRC_HCLK,RCC_MCO_DIV1024);
    while(1)
    {
    }
}
输出波形

45.455KHz x 1024 = 46545.92KHz = 46.5MHz
再来用外部16MHz晶振来初始化

void RCC_HSE_16M_init()
{
    RCC_HSE_Enable( RCC_HSE_MODE_OSC, 16000000, RCC_HSE_DRIVER_NORMAL, RCC_HSE_FLT_CLOSE);
    RCC_SysClk_Switch( RCC_SYSCLKSRC_HSE );
    RCC_HSI_Disable();
    RCC_SystemCoreClockUpdate(16000000);
}
int32_t main(void)
{
        RCC_HSE_16M_init();
    RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
    RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
    RCC_MCO_OUT(RCC_MCO_SRC_HCLK,RCC_MCO_DIV1024);
    while(1)
    {
    }
}
输出波形

15.625KHz x 1024 = 16000KHz = 16MHz
接下来使用外部时钟PLL到64MHz

void RCC_HSE_16M_PLL64M_init()
{
    //< 当使用的时钟源HCLK大于48M,小于等于72MHz:设置FLASH 读等待周期为3 cycle >
    __RCC_FLASH_CLK_ENABLE();
    FLASH_SetLatency(FLASH_Latency_3);
    RCC_HSE_Enable( RCC_HSE_MODE_OSC, 16000000, RCC_HSE_DRIVER_NORMAL, RCC_HSE_FLT_CLOSE);
    RCC_PLL_Enable(RCC_PLLSOURCE_HSEOSC,16000000,RCC_PLL_MUL_4);
    RCC_SysClk_Switch( RCC_SYSCLKSRC_PLL );
    RCC_HSI_Disable();
    RCC_SystemCoreClockUpdate(64000000);
}
int32_t main(void)
{
        RCC_HSE_16M_PLL64M_init();
    RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
    RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
    RCC_MCO_OUT(RCC_MCO_SRC_HCLK,RCC_MCO_DIV1024);
    while(1)
    {
    }
}
输出波形

62.5KHz x 1024 = 64000KHz = 64MHz
接下来用内部48MHz时钟6分频得到8MHz再倍频到64MHz

void RCC_HSI_PLL64M_init()
{
    //< 当使用的时钟源HCLK大于48M,小于等于72MHz:设置FLASH 读等待周期为3 cycle >
    __RCC_FLASH_CLK_ENABLE();
    FLASH_SetLatency(FLASH_Latency_3);
    RCC_HSI_Enable(RCC_HSIOSC_DIV6);
    RCC_PLL_Enable(RCC_PLLSOURCE_HSI,8000000,RCC_PLL_MUL_8);
    RCC_SysClk_Switch( RCC_SYSCLKSRC_PLL );
    RCC_SystemCoreClockUpdate(64000000);
}
int32_t main(void)
{
        RCC_HSI_PLL64M_init();
    RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
    RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
    RCC_MCO_OUT(RCC_MCO_SRC_HCLK,RCC_MCO_DIV1024);
    while(1)
    {
    }
}
输出波形

62.5KHz x 1024 = 64000KHz = 64MHz
使用内部低速时钟LSI

void RCC_LSI_init()
{
    RCC_LSI_Enable();
    RCC_SysClk_Switch(RCC_SYSCLKSRC_LSI);
    RCC_HSI_Disable();
    RCC_SystemCoreClockUpdate(32800);
}
int32_t main(void)
{
        RCC_LSI_init();
    RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
    RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
    RCC_MCO_OUT(RCC_MCO_SRC_HCLK,RCC_MCO_DIV1);
    while(1)
    {
    }
}
输出波形

使用外部低速晶振

void RCC_LSE_init()
{
    RCC_LSE_Enable(RCC_LSE_MODE_OSC,RCC_LSE_AMP_LARGER,RCC_LSE_DRIVER_LARGER);
    RCC_SysClk_Switch(RCC_SYSCLKSRC_LSE);
    RCC_HSI_Disable();
    RCC_SystemCoreClockUpdate(32768);
}
int32_t main(void)
{
        RCC_LSE_init();
    RCC_HCLKPRS_Config(RCC_HCLK_DIV1);
    RCC_PCLKPRS_Config(RCC_PCLK_DIV1);
    RCC_MCO_OUT(RCC_MCO_SRC_HCLK,RCC_MCO_DIV1);
    while(1)
    {
    }
}
输出波形

3.3延时函数的实现
L083的system_cw32l083.c中有一个FirmwareDelay方法用于延时

但是这个并不好控制具体延时多长时间,利用SysTick可以做一个Arm内核的通用延时方法,SysTick定时器(又名系统滴答定时器)是存在于ARM Cotex-M系列内核中的定时器。具体实现方法

extern uint32_t SystemCoreClock;
void yuyy_delay_us(uint16_t us)
{
    uint32_t temp;
    SysTick->CTRL = 0x0;               /*!< disable systick function */
    SysTick->LOAD = us * (SystemCoreClock/1000000);         /*!< time count for 1us with SYSCLK */
    SysTick->VAL  = 0x00;              /*!< clear counter */
    SysTick->CTRL = 0x5;               /*!< start discrease with Polling */
    do
    {
        temp = SysTick->CTRL;
    }
    while ((temp & 0x01) && !(temp & (1 << 16))); /*!< wait time count done */
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;    /*!< Close Counter */
    SysTick->VAL   = 0X00;
}

void yuyy_delay_ms(uint16_t ms)
{
    while(ms--)
        yuyy_delay_us(1000);
}
这个延时方法我已经在M0 M3 M4 M33的MCU上都使用过了,移植基本不用改动,只要注意修改时钟源后更新系统时钟就行了

使用特权

评论回复

打赏榜单

21小跑堂 打赏了 30.00 元 2023-08-23
理由:恭喜通过原创审核!期待你更多的原创作品~

评论
21小跑堂 2023-8-23 16:56 回复TA
概述CW32L083的时钟系统,并基于滴答定时器实现延时函数 
沙发
chenjun89| | 2023-8-5 23:58 | 只看该作者
这个是虚拟示波器的波形

使用特权

评论回复
板凳
weifeng90| | 2023-8-6 08:45 | 只看该作者
波形上的点是怎么回事?

使用特权

评论回复
地板
yuyy1989|  楼主 | 2023-8-6 10:13 | 只看该作者
weifeng90 发表于 2023-8-6 08:45
波形上的点是怎么回事?

就是采样点,因为不是真正的示波器,做不到太细

使用特权

评论回复
5
lulugl| | 2023-8-6 11:22 | 只看该作者
非常详细呀,点赞!

使用特权

评论回复
6
中国龙芯CDX| | 2023-8-7 12:43 | 只看该作者
SysTick定时器经常是使用延时程序进行的函数编写

使用特权

评论回复
7
小夏天的大西瓜| | 2023-8-26 11:50 | 只看该作者
楼主设置的第一个为48Mhz实测为46.5MHZ,这个是不是说频率越高误差越大?

使用特权

评论回复
8
yuyy1989|  楼主 | 2023-8-26 20:09 | 只看该作者
小夏天的大西瓜 发表于 2023-8-26 11:50
楼主设置的第一个为48Mhz实测为46.5MHZ,这个是不是说频率越高误差越大?

应该是虚拟示波器不准

使用特权

评论回复
9
星辰大海不退缩| | 2023-8-27 20:23 | 只看该作者
时钟源是不是选择高速时钟比较多

使用特权

评论回复
10
AdaMaYun| | 2023-8-27 21:47 | 只看该作者
理论上这些频率不是基础8M的基础上分频得到的嘛

使用特权

评论回复
11
OKAKAKO| | 2023-8-27 22:09 | 只看该作者
AdaMaYun 发表于 2023-8-27 21:47
理论上这些频率不是基础8M的基础上分频得到的嘛

理论上应该都是经过分频得到的相关时钟数据

使用特权

评论回复
12
tpgf| | 2023-9-4 13:19 | 只看该作者
是否可以写一个自适应的延时函数呢

使用特权

评论回复
13
yuyy1989|  楼主 | 2023-9-4 14:15 | 只看该作者
tpgf 发表于 2023-9-4 13:19
是否可以写一个自适应的延时函数呢

这个已经是自适应的了,修改时钟源后调用RCC_SystemCoreClockUpdate更新系统时钟就行了,不用修改延时函数的代码

使用特权

评论回复
14
nawu| | 2023-9-4 16:35 | 只看该作者
延时函数的时钟都可以选择哪种呢

使用特权

评论回复
15
aoyi| | 2023-9-4 16:43 | 只看该作者
虚拟示波器比较不容易带入干扰信号吧

使用特权

评论回复
16
zljiu| | 2023-9-4 16:53 | 只看该作者
小夏天的大西瓜 发表于 2023-8-26 11:50
楼主设置的第一个为48Mhz实测为46.5MHZ,这个是不是说频率越高误差越大?

不同的频率误差应该是不相同的 跟频率的大小没有关系

使用特权

评论回复
17
gwsan| | 2023-9-4 17:09 | 只看该作者
一般情况下在延时函数中跳不出来的原因是什么呢

使用特权

评论回复
18
tfqi| | 2023-9-4 19:00 | 只看该作者
单次延时函数能延时的时间是多长呢

使用特权

评论回复
发新帖 本帖赏金 30.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

85

主题

450

帖子

4

粉丝