文章目录
- 一.概要
- 二.GD32F103C8T6单片机时钟源介绍
- 二.GD32F103C8T6单片机外部高频晶振配置
- 三.GD32F103C8T6单片机内部高频晶振配置
- 四.GD32F103C8T6单片机使用内部8M晶振实验
- 五.工程源代码下载
- 六.小结
一.概要
GD32单片机的时钟源包括多种选项,时钟控制单元提供了一系列频率的时钟功能,包括一个内部8M RC振荡器时钟(IRC8M)、一个外部高速晶体振荡器时钟(HXTAL)、一个内部40K RC振荡器时钟(IRC40K)、一个外部低速晶体振荡器时钟(LXTAL)、一个锁相环(PLL)、一个HXTAL时钟监视器、时钟预分频器、时钟多路复用器和时钟门控电路。
二.GD32F103C8T6单片机时钟源介绍
IRC40K:低速内部时钟,IRC40K RC振荡器时钟担当一个低功耗时钟源的角色,它的时钟频率大约40 kHz,为独立看门狗定时器和实时时钟电路提供时钟。
IRC8M:高速内部8MHz时钟,内部8MHz RC振荡器时钟,简称IRC8M时钟,拥有8MHz的固定频率,设备上电后CPU默认选择的时钟源就是IRC8M时钟。他精度比较低,容易受温度影响,在CAN,USART等对时钟精度要求高的场合不适用。
HXTAL:高速外部时钟,4到16MHz的外部振荡器可为系统提供更为精确的主时钟。
PLL(Phase Locked Loop)锁相环时钟:
PLL时钟的源可以是IRC8M或HXTAL。PLL可以对输入的时钟信号进行倍频,以产生更高频率的时钟信号,从而提高系统的性能。
LXTAL:低速外部时钟,LXTAL晶体一般是一个32.768kHz的低速外部晶体或陶瓷谐振器。它为实时时钟电路提供一个低功耗且精确的时钟源。
AHB、APB和Cortex™-M3时钟都源自系统时钟(CK_SYS),系统时钟的时钟源可以选择IRC8M、HXTAL或PLL。系统时钟的最大运行时钟频率可以达到108MHz。独立看门狗定时器有独立的时钟源(IRC40K),实时时钟(RTC)使用IRC40K、LXTAL或HXTAL的128分频作为时钟源。
二.GD32F103C8T6单片机外部高频晶振配置
4到16M的外部高速晶体振荡器可为系统时钟提供更为精确时钟源。带有特定频率的晶体必须靠近两个HXTAL的引脚连接。和晶体连接的外部电阻和电容必须根据所选择的振荡器来调整。
HXTAL晶体振荡器可以通过设置控制寄存器RCU_CTL的HXTALEN位来启动或关闭,在控制寄存器RCU_CTL中的HXTALSTB位用来指示外部高速振荡器是否已稳定。在启动时,直到这一位被硬件置‘1’,时钟才被释放出来。这个特定的延迟时间被称为振荡器的启动时间。
/* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN;
/* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout));
三.GD32F103C8T6单片机内部高频晶振配置
内部8MHz RC振荡器时钟,简称IRC8M时钟,拥有8MHz的固定频率,设备上电后CPU默认选择其做为系统时钟源。IRC8M RC振荡器能够在不需要任何外部器件的条件下为用户提供更低成本类型的时钟源。IRC8M RC振荡器可以通过设置控制寄存器(RCU_CTL)中的IRC8MEN位被启动和关闭。控制寄存器RCU_CTL中的IRC8MSTB位用来指示IRC8M内部RC振荡器是否稳定。IRC8M振荡器的启动时间比HXTAL晶体振荡器要更短。
工厂会校准IRC8M时钟频率的精度,但是它的精度仍然比HXTAL时钟要差。用户可以根据需求、环境条件和成本决定选择哪个时钟作为系统时钟源。
/* enable IRC8M */
RCU_CTL |= RCU_CTL_IRC8MEN;
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
}
while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
四.GD32F103C8T6单片机使用内部8M晶振实验
STLINK接GD32F103C8T6开发板,STLINK接电脑USB口。
主要代码:
/***************************************************************************//**
文件: main.c
作者: Zhengyu https://gzwelink.taobao.com
版本: V1.0.0
时间: 202101201
平台:MINI-GD32F103C8T6开发板
*******************************************************************************/
#include "gd32f10x.h"
#include "gd32f10x_libopt.h"
#include "systick.h"
int main(void)
{
rcu_apb2_clock_config(RCU_APB2_CKAHB_DIV1);//设置主频108M(#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000)),8M内部晶振
systick_config();//配置1ms SysTick
rcu_periph_clock_enable(RCU_AF);//AF时钟使能
gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE);//下载口NJTRST引脚当做普通I/O口
rcu_periph_clock_enable(RCU_GPIOB);//GPIOB时钟打开
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4);//PB4配置成输出
while(1)
{
delay_1ms(1000);//等待1000ms
gpio_bit_set(GPIOB, GPIO_PIN_4);//PB4输出高
delay_1ms(1000);
gpio_bit_reset(GPIOB, GPIO_PIN_4);//PB4输出低
}
}
#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_48M_PLL_IRC8M (uint32_t)(48000000)
//#define __SYSTEM_CLOCK_72M_PLL_IRC8M (uint32_t)(72000000)
#define __SYSTEM_CLOCK_108M_PLL_IRC8M (uint32_t)(108000000)
/* use HXTAL (XD series CK_HXTAL = 8M, CL series CK_HXTAL = 25M) */
//#define __SYSTEM_CLOCK_HXTAL (uint32_t)(__HXTAL)
//#define __SYSTEM_CLOCK_24M_PLL_HXTAL (uint32_t)(24000000)
//#define __SYSTEM_CLOCK_36M_PLL_HXTAL (uint32_t)(36000000)
//#define __SYSTEM_CLOCK_48M_PLL_HXTAL (uint32_t)(48000000)
//#define __SYSTEM_CLOCK_56M_PLL_HXTAL (uint32_t)(56000000)
//#define __SYSTEM_CLOCK_72M_PLL_HXTAL (uint32_t)(72000000)
//#define __SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000)
//#define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000)
/*!
\brief configure the system clock to 108M by PLL which selects IRC8M as its clock source
\param[in] none
\param[out] none
\retval none
*/
static void system_clock_108m_irc8m(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U;
/* enable IRC8M */
RCU_CTL |= RCU_CTL_IRC8MEN;
/* wait until IRC8M is stable or the startup time is longer than IRC8M_STARTUP_TIMEOUT */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
}
while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));
/* if fail */
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
while(1){
}
}
/* IRC8M is stable */
/* AHB = SYSCLK */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
/* APB2 = AHB/1 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB/2 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV2;
/* CK_PLL = (CK_IRC8M/2) * 27 = 108 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLMF | RCU_CFG0_PLLMF_4);
RCU_CFG0 |= RCU_PLL_MUL27;
/* enable PLL */
RCU_CTL |= RCU_CTL_PLLEN;
/* wait until PLL is stable */
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
}
/* select PLL as system clock */
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_PLL;
/* wait until PLL is selected as system clock */
while(0U == (RCU_CFG0 & RCU_SCSS_PLL)){
}
}
实验结果:
可以看到LED D1灯(PB4引脚驱动)能间隔闪烁,间隔时间1s
五.工程源代码下载
通过网盘分享的文件:23.GPIO输出实验(8M内部晶振).zip
链接: https://pan.baidu.com/s/1a0FYU6g-etPINJOF5F_pPA 提取码: ixts
如果链接失效,可以联系博主给最新链接
程序下载下来之后解压就行
六.小结
一般我们在实际产品开发中,都会使用外部晶振,但有时候会遇到降低BOM成本,减少板子空间,增加单片机的GPIO利用率的场合,就可能会使用内部晶振。