四、GD32 MCU 常见外设介绍(1)RCU 时钟介绍

系统架构

1.RCU 时钟介绍

众所周知,时钟是MCU能正常运行的基本条件,就好比心跳或脉搏,为所有的工作单元提供时间 基数。时钟控制单元提供了一系列频率的时钟功能,包括多个内部RC振荡器时钟(IRC)、一个外部 高速晶体振荡器时钟(HXTAL)、一个外部低速晶体振荡器时钟(LXTAL)、一个或多个锁相环(PLL) 一个HXTAL时钟和LXTAL时钟监视器、时钟预分频器、时钟多路复用器和时钟门控电路等。 本章,我们将通过一个“输出HXTAL时钟信号” 的实验来熟悉RCU的工作流程。

1.1RCU 配置

GD32系列MCU在启动后首先会执行Reset Handler,紧接着就会执行SystemInit()函数,而时钟的初始化,就是在这个函数中进行,其主要的功能是配置系统时钟CK_SYS(即主频),AHB、APB1以及APB2时钟。SystemInit()函数由GD32官方库提供,不同系列的MCU有一些差别,但实现方式基本相同:首先将RCU关于CK_SYS,AHB、APB1以及APB2时钟配置的一些寄存器恢复到默认值,然后再执行system_clock_config()函数,用于具体的时钟配置。

实际上用户可以不用过于关心上述的实现方式,因为GD32库已经为您提供了多种时钟源及时钟选择,您只需按照以下步骤即可将时钟设置为您期望的值(以GD32F30x为例,其他系列类似):

(1) 在system_gd32f30x.c中,用户可通过选择宏来进行预设的时钟配置,如下图代码清单时钟配置选择宏定义,选择了HXTAL作为PLL时钟源,且配置CK_SYS为120MHz。

/* system frequency define */
#define __IRC8M (IRC8M_VALUE) /* internal 8 MHz RC oscillator frequency */
#define __HXTAL (HXTAL_VALUE) /* high speed crystal oscillator frequency */
#define __SYS_OSC_CLK (__IRC8M) /* main oscillator frequency */
/* select a system clock by uncommenting the following line */
/* use IRC8M */
//#define __SYSTEM_CLOCK_IRC8M (uint32_t)(__IRC8M) 
//#define __SYSTEM_CLOCK_48M_PLL_IRC8M (uint32_t)(48000000)
//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000)
//#define __SYSTEM_CLOCK_120M_PLL_IRC8M (uint32_t)(120000000)
/* use HXTAL(XD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */
//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL)
//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000)
//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000)
#define __SYSTEM_CLOCK_120M_PLL_HXTAL (uint32_t)(120000000)

但这种情况下您使用的外部晶振需要是默认值,此值由HXTAL_VALUE定义,如为8000000,那么您应该选择8MHz的外部晶振。

当然,您可以使用其他规格的外部晶振,这种情况下就需要去修改RCU配置函数里面的一些参数,主要是分频和倍频系数,以达到期望的配置,具体如何修改,可以结合GD32的User manual中定义的RCU寄存器来对配置函数进行分析。

(2) 设置HXTAL_VALUE的值。

此数值和RCU的初始化其实并没有太大关系,但如果您使用的外部晶振不是默认值,那么除了按照步骤(1)修改配置参数外,您还必须将此HXTAL_VALUE的值修改为实际的外部晶振频率,这是因为在一些通信外设配置时,库函数会调用HXTAL_VALUE值来设置波特率,如此值设置错误,会导致通信异常。

1.2.非默认外部晶振配置时钟实例

GD32各系列固件库都已提供配置系统时钟的函数。需要注意的是,在使用外部晶振时,固件库中HXTAL_VALUE值规定了 外部晶振的默认值,以 GD32F30x系列为例,如下图代码清单HXTAL_VALUE选择宏定义所示,当芯片为非互联型(GD32F303)时,默认使用的外部晶振频率为8MHz,当芯片为互联型(GD32F305/307)时,默认使用的外部晶振频率为25MHz。

#ifdef GD32F30X_CL 
#define HXTAL_VALUE ((uint32_t)25000000) 
#else 
#define HXTAL_VALUE ((uint32_t)8000000)

那么,当我们使用非默认值的外部晶振时,该如何修改时钟配置函数呢?以GD32F303为例,首先我们先看下GD32F303的时钟树,如图所示。

预分频器可以配置AHB、APB2和APB1域的时钟频率。 AHB、APB2、APB1域的最高时钟频率分别为120MHz、120MHz、60MHz。RCU通过AHB时钟(HCLK)8分频后作为Cortex系统定时器(SysTick)的外部时钟。通过对SysTick控制和状态寄存器的设置,可选择上述时钟或AHB(HCLK)时钟作为SysTick时钟。

ADC时钟由APB2时钟经2、4、6、8、12、16分频或由AHB时钟经5、6、10、20分频获得,它们是通过设置RCU_CFG0和RCU_CFG1寄存器的ADCPSC位来选择。

SDIO, EXMC的时钟由CK_AHB提供。

TIMER时钟由CK_APB1和CK_APB2时钟分频获得,如果APBx(x=0,1)的分频系数不为1,则TIMER时钟为CK_APBx(x=0,1)的两倍。

USBD的时钟由CK48M时钟提供。通过配置 RCU_ADDCTL寄存器的CK48MSEL及PLL48MSEL位可以选择CK_PLL时钟或IRC48M时钟做为CK48M的时钟源。

CTC时钟由IRC48M时钟提供,通过CTC单元,可以实现IRC48M时钟精度的自动调整。

I2S的时钟由CK_SYS提供。

通过配置RCU_BDCTL寄存器的RTCSRC位, RTC时钟可以选择由LXTAL时钟、IRC40K时钟或HXTAL时钟的128分频提供。RTC时钟选择HXTAL时钟的128分频做为时钟源后,当1.2V内核电压域掉电时,时钟将停止。 RTC时钟选择IRC40K时钟做为时钟源后,当VDD掉电时,时钟将停止。

RTC时钟选择LXTAL时钟做为时钟源后,当VDD和VBAT都掉电时,时钟将停止。

当FWDGT启动时, FWDGT时钟被强制选择由IRC40K时钟做为时钟源。

现在,我们结合图GD32F303系统时钟树对时钟树进行分析:

(1) 标注A为CK_SYS,即系统主时钟,它一条线连接至CK_I2S,给I2S外设提供时钟,另一条线经过AHB分频器,输出到CK_AHB,即标注B。

(2) CK_AHB为AHB总线时钟,AHB总线时钟或直连,或经过APB1/APB2分频,给标注C位置的外设提供时钟。

(3) 那么,CK_SYS从何而来呢,我们看标注A的左边,CK_SYS通过SCS位域选择CK_IRC8M、CK_PLL、CK_HXTAL作为时钟来源,其中CK_IRC8M来源于标注D,即IRC8M(MCU内部8M RC时钟);CK_HXTAL来源于标注F,即HXTAL(外部时钟);CK_PLL的来源较复杂,我们单独拿出来说。

(4) CK_PLL来源于锁相环倍频器输出,倍频系数通过PLLMF位域选择,而PLLMF来源于两个地方,一个为 IRC8M 的 2 分 频 , 另 外 一 个 为 预 分 频 器 PREDV0 , 而 PREDV0 来 源 于 标 注 E, 即CK_IRC48M(内部48M RC时钟)和标注F,即HXTAL(外部高速时钟)。

(5) 通过以上分析可以得出结论,CK_PLL的时钟源为D:IRC8M、E:IRC48M、F:HXTAL,用户通过相关寄存器设置选择时钟线。

(6) 和前面分析相同,RTC的时钟来自于F:HXTAL的128分频、G:LXTAL(外部32.768K低速时钟)、F:IRC40K(内部40K RC时钟);FWDGT的时钟来源于F:IRC40K。

(7) 标注I位置为时钟输出线,它的作用是将MCU内部的一些时钟信号线输出到特定IO口上(大部分系列MCU的PA8口都可被设置为时钟输出口0,有些系列MCU含有两组输出IO,具体IO配置请参考各系列MCU Datasheet)用来给其他器件提供基准时钟。由图中可看出通过设置位域CK_OUT0,输出的时钟包括CK_PLL、CK_IRC8M、CK_HXTAL、CK_PLL的2分频。

结合以上分析,我们来看下GD32F30x固件库时钟配置函数(因篇幅有限,只贴出各分频和倍频配置部分),还是以GD32F303芯片为例,如下图代码清单时钟配置部分代码所示:

/* select HXTAL/2 as clock source */
RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0);
/* CK_PLL = (CK_HXTAL/2) * 30 = 120 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL30;

 可以看出,8MHz的HXTAL经过预分频器PREDV0分频成4MHz,再通过锁相环PLL倍频30倍到了120MHz。

那么,当您选择其他规格的外部晶振,比如12MHz,则可以先通过预分频器PREDV0分频成6MHz,再通过锁相环PLL倍频20倍即可,如代码清单 0-4. 使用12MHz外部晶振配置120M系统时钟所示。

/* select HXTAL/2 as clock source */
RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PREDV0);
RCU_CFG0 |= (RCU_PLLSRC_HXTAL_IRC48M | RCU_CFG0_PREDV0);
/* CK_PLL = (CK_HXTAL/2) * 20 = 120 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4 | RCU_CFG0_PLLMF_5);
RCU_CFG0 |= RCU_PLL_MUL20;

当然,在修改完配置函数后,别忘了将HXTAL_VALUE值改为12000000。

需要注意的是,在进行时钟配置时,要严格按照Datasheet中规定的时钟范围进行配置,如GD32F303的 HXTAL的选 择范 围是4~32MHz, PLL的输 入范 围是 1~25MHz,输出范围是16~120Mhz,所以当使用32MHz的外部晶振时,不进行预分频,而直接倍频是不被允许的。

1.3.硬件连接说明

本章通过“输出HXTAL时钟信号”实验来熟悉RCU的工作流程。

通过前面内容讲解可知,本章实验为“输出HXTAL时钟信号”,即通过PA8口将HXTAL输出,我们使用示波器,将探头连接到PA8口,从示波器上读取PA8口波形即可。

1.4.软件配置说明

本小节讲解RCU_Example例程中RCU的配置说明,主要包括外设时钟配置、GPIO引脚配置、主函数介绍以及运行结果。

软件设计的流程如下:

(1)使能GPIOA时钟

(2)初始化PA8,将此端口设置为备用功能模式(AFIO)

(3)通过调用库函数选择HXTAL作为PA8时钟信号源

外设时钟配置

void rcu_config(void)
{
/* enable the GPIOA clock */
rcu_periph_clock_enable(RCU_GPIOA);
}

GPIO 引脚配置 

代码清单 0-6. RCU 例程引脚配置

void gpio_config(void)
{
/* configure PA8 port */ 
#if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X 
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
#elif GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X
gpio_mode_set(GPIOA,GPIO_MODE_AF,GPIO_PUPD_NONE,GPIO_PIN_8);
gpio_af_set(GPIOA,GPIO_AF_0,GPIO_PIN_8);
#endif
}

GPIO的配置说明,请参考GPIO章节。

主函数说明

代码清单 0-7 . RCU 例程主函数

int main(void)
{
rcu_config();
gpio_config();
#if defined GD32F10X_HD || GD32F30X_HD || GD32E10X
rcu_ckout0_config(RCU_CKOUT0SRC_HXTAL);
#elif defined GD32F20X_CL || GD32F4XX
rcu_ckout0_config(RCU_CKOUT0SRC_HXTAL,RCU_CKOUT0_DIV1);
#elif GD32F1X0 || GD32F3X0 || GD32E23X
rcu_ckout_config(RCU_CKOUTSRC_HXTAL,RCU_CKOUT_DIV1);
#endifwhile(1){}
}

如代码清单RCU例程主函数,该主函数主要分成四部分,RCU时钟配置、GPIO配置、RCU输出相关库函数调用和while(1)主循环,其中RCU输出相关库函数请读者结合各系列MCU Datasheet、User Manual进行RCU例程的分析。

注意:因为是输出HXTAL,所以必须要使能HXTAL,否则PA8将无波形输出。一个简单的办法是将HXTAL作为CK_SYS时钟源,请参考本章第一节内容。

1.5.运行结果

如图所示 RCU 例程运行结果为 RCU 例程运行结果,可看出,PA8 口正确输出了 HXTAL 波形。

本章内容每日持续更新,如有兴趣,请关注收藏

更多GD32 MCU相关咨询:https://www.gd32bbs.com/ 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/48324.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何提升短视频的曝光量和获客效能?云微客来解决

在流量至上的当下,短视频凭借其优势,迅速成为了众多企业获客引流的核心营销手段。进入短视频赛道后,如何提升短视频的曝光量和获客效能,就成为了众多企业亟待解决的焦点。 如果你不想投入大量的广告预算,还想在短视频平…

【Linux】进程间通信及管道详细介绍(上)

前言 本节我们开始学习进程间通信相关的知识,并详细探讨一下管道,学习匿名管道和命名管道的原理和代码实现等相关操作… 目录 1. 进程间通信背景1.1 进程通信的目的: 2 管道的引入:2.1 匿名管道:2.1.1 匿名管道的原理&…

【中项】系统集成项目管理工程师-第5章 软件工程-5.1软件工程定义与5.2软件需求

前言:系统集成项目管理工程师专业,现分享一些教材知识点。觉得文章还不错的喜欢点赞收藏的同时帮忙点点关注。 软考同样是国家人社部和工信部组织的国家级考试,全称为“全国计算机与软件专业技术资格(水平)考试”&…

【数据结构】AVL树(图文解析 + 代码实现)

目录 1、AVL树的概念 2、AVL树结点的定义 3、AVL树的插入 4、AVL树的旋转 4.1 左单旋 4.2 右单旋 4.3 右左双旋 4.4 左右双旋 5、AVL树的验证 6、AVL树的性能 前面对map/multimap/set/multiset进行了简单的介绍,会大仙,这几个容器有个共同点是…

【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !

目录 C语言指针精讲1. 什么是指针?1.1 指针的内存模型1.1.1 指针演示输出 1.2 指针运算1.2.1 指针算术运算输出1.2.2 指针与数组的关系输出 1.3 指针类型1.3.1 不同类型的指针示例输出1.3.2 void 指针输出 1.4 指针与内存管理动态内存分配输出 1.5 指针与内存泄漏1.…

vue 两个页面切换, 再回到当前页,还是离开前的数据

1、要保证页面的name 和 建路由的大小写一致 2、页面不用生命周期--activated 调接口刷新

在 Kubernetes 中设置 Pod 优先级及其调度策略详解

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] &#x1f4f1…

【论文解读】大模型算法发展

一、简要介绍 论文研究了自深度学习出现以来,预训练语言模型的算法的改进速度。使用Wikitext和Penn Treebank上超过200个语言模型评估的数据集(2012-2023年),论文发现达到设定性能阈值所需的计算大约每8个月减半一次,95%置信区间约为5到14个月…

雪花算法 集群uid重复问题 uid-generator-spring-boot-starter

1、在生成环境 在某个业务使用该插件生成uid,由于业务整合了 mybatis-plus模块 2、该业务是分部署集群部署以及使用的多线程获取uid,使用中发现唯一建冲突,生成的uid有重复。 然后查看日志发现 workerId 始终为0 怀疑是生成workerId出了问题。 查看跟…

开发日志:windows修复SSL漏洞CVE-2016-2183(3389端口)

漏洞危害: 具有足够资源的中间人攻击者可利用此漏洞,通过“birthday”攻击检测会在固定密码与已知纯文本之间泄露 XOR 的冲突,进而泄露密码文本(例如安全 HTTPS Cookie),并可能导致劫持经认证的会话。 参见《支持SSL 64位块大小的密码套件(SWEET32)-修复方案》 参考…

主流树模型讲解、行列抽样、特征重要性梳理总结

本文旨在总结一下常见树模型的行、列抽样特点以及特征重要性的计算方式,也会带着过一遍算法基本原理,一些细节很容易忘记啊。 主要是分类和回归两类任务,相信能搜索这篇文章的你,应该对树模型有一定的了解。 可以搜索 总结 &…

老鼠后五毒也来凑热闹!网红食品惊现「壁虎头」,胖东来已下架…

上周,老鼠有点忙,比如其连续被曝出,出现在了方便面知名品牌的调料包、知名连锁餐饮品牌的黄焖鸡饭中。‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 在小柴「被「添加」进方便面、黄焖鸡饭?老鼠最近忙疯了……」这篇文章的评论区,柴油…

计算机视觉与面部识别:技术、应用与未来发展

引言 在当今数字化时代,计算机视觉技术迅速发展,成为人工智能领域的一个重要分支。计算机视觉旨在让机器理解和解释视觉信息,模拟人类的视觉系统。它在各行各业中发挥着重要作用,从自动驾驶汽车到智能监控系统,再到医疗…

Python:对常见报错导致的崩溃的处理

Python的注释: mac用cmd/即可 # 注释内容 代码正常运行会报以0退出,如果是1,则表示代码崩溃 age int(input(Age: )) print(age) 如果输入非数字,程序会崩溃,也就是破坏了程序,终止运行 解决方案&#xf…

贪心算法(三) ---cmp_to_key, 力扣452,力扣179

目录 cmp_to_key 比较函数 键函数 cmp_to_key 的作用 使用 cmp_to_key 代码解释 力扣452 ---射气球 题目 分析 代码 力扣179 ---最大数 题目 分析 代码 cmp_to_key 在Python中,cmp_to_key 是一个函数,它将一个比较函数转换成一个键函数…

Problems retrieving the embeddings data form OpenAI API Batch embedding job

题意:从OpenAI API批量嵌入作业中检索嵌入数据时遇到问题 问题背景: I have to embed over 300,000 products description for a multi-classification project. I split the descriptions onto chunks of 34,337 descriptions to be under the Batch e…

Nginx优化、防盗链

目录 Nginx优化 隐藏版本信息 网站缓存 日志切割 超时时间 更改进程数 网页压缩 防盗链 在使用源码软件包安装过Nginx服务,具体步骤看上一篇文章 功能模块位置 在Nginx的解压目录下的auto目录内的options文件可以查看Nginx可以安装的功能模块 [rootlocal…

数据结构初阶-单链表

链表的结构非常多样,以下情况组合起来就有8种(2 x 2 x 2)链表结构: 而我们主要要熟悉的单链表与双向链表的全称分别为:不带头单向不循环链表,带头双向循环链表,当我们对这两种链表熟悉后&#x…

重生之我们在ES顶端相遇第5章-常用字段类型

思维导图 前置 在第4章,我们提到了 keyword(一笔带过)。在本章,我们将介绍 ES 的字段类型。全面的带大家了解 ES 各个字段类型的使用场景。 字段类型 ES 支持以下字段类型(仅介绍开发中常用,更多内容请自…

AI App Store-AI用户评价-多维度打分对比pk-AI社区

C端用户、创作者、AI达人们在选择众多国内外AI厂商的服务时候往往感到一头雾水,那么多功能接近的AI应用(智能对话类、文档总结类、文生图、AI搜索引擎) 究竟在不同用户需求场景下表现怎么样。大部分人如果有需求都会所有平台都尝试一遍,比如一个博主生成…