5.15 RCC 使用说明
本章说明 N32G033 标准外设库中 RCC 驱动的文件组成、42 个公开函数,以及 LSI_Calibration、RCC_ClockConfig 2 个示例。复位源、时钟树、HSI/LSI 切换与时钟校准原理请配合用户手册的“复位和时钟控制(RCC)”章节阅读,芯片已知问题以勘误手册为准。
5.15.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32g033_std_periph_driver/inc/n32g033_rcc.h |
定义系统时钟源、总线分频、外设时钟门控、MCO 输出、EMC/Glitch 检测与校准等宏,并把 42 个公开函数按功能分为九个声明区段 |
firmware/n32g033_std_periph_driver/src/n32g033_rcc.c |
实现上述 42 个函数:RCC 复位、HSI/LSI 使能与稳定等待、系统时钟与总线分频、外设时钟门控与软复位、MCO 输出、复位标志与中断、EMC/Glitch 检测、时钟源选择与滤波分频、LSI 校准 |
projects/n32g033_EVAL/examples/RCC/ |
RCC 示例根目录,含 LSI_Calibration、RCC_ClockConfig 2 个示例 |
projects/n32g033_EVAL/examples/RCC/RCC_ClockConfig/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32g033_EVAL/bsp/inc/、projects/n32g033_EVAL/bsp/src/ |
板级公共文件,示例通过 log.h 使用串口日志 |
5.15.2 API 参考
以下 42 个公开函数按 n32g033_rcc.h 的声明顺序分为 9 组;每个条目给出功能摘要与 n32g033_rcc.c 中该函数正上方的注释原文。
复位与振荡器使能
RCC_DeInit、RCC_EnableHsi、RCC_WaitHsiStable
振荡器校准
RCC_SetHsiCalibValue、RCC_ConfigLsiCalibSource、RCC_SetLsiCalibValue
系统时钟与总线分频
RCC_ConfigSysclkPres、RCC_ConfigSysclk、RCC_GetSysclkSrc、RCC_ConfigHclk、RCC_ConfigPclk、RCC_ConfigAdcHclk、RCC_GetClocksFreqValue
外设时钟使能与复位
RCC_EnableAHBPeriphClk、RCC_EnableAPBPeriphClk、RCC_EnableAHBPeriphReset、RCC_EnableAPBPeriphReset
时钟输出(MCO)
RCC_ConfigMcoClkPre、RCC_ConfigMco
标志与中断
RCC_GetFlagStatus、RCC_ClearResetFlag、RCC_GetIntStatus、RCC_ClrIntPendingBit
EMC 与 Glitch 检测
RCC_EnableEMCReset、RCC_EnableEMCDetect、RCC_EnableEMCSwitch、RCC_ConfigEMCDetectLevel、RCC_EnableGlitchDetect、RCC_EnableGlitchReset、RCC_EnableGlitchSwitch、RCC_ConfigGlitchDetectLevel、RCC_EnableM0LockupReset
定时器与串口时钟源
RCC_ConfigTimClk、RCC_ConfigTim6Clk、RCC_ConfigUart3Clk
输入滤波与 LSI 校准
RCC_ConfigIOFilter、RCC_ConfigTIM4Filter、RCC_ConfigTIM3Filter、RCC_ConfigTIM1Filter、RCC_ConfigLSICalibPeriod、RCC_EnableLSICalibration、RCC_GetHSICalibPeriod
void RCC_DeInit(void)复位 RCC 寄存器。
name RCC_DeInit.
fun Reset the RCC registers.
param none
return none
void RCC_EnableHsi(FunctionalState Cmd)使能内部高速振荡器(HSI)。
name RCC_EnableHsi.
fun Enables the Internal High Speed oscillator (HSI).
param Cmd:
- ENABLE
- DISABLE
return none
note HSI can not be stopped if it is used directly or through the PLL as system clock.
ErrorStatus RCC_WaitHsiStable(void)等待 HSI 启动完成。
name RCC_WaitHsiStable.
fun Waits for HSI start-up.
param none
return ErrorStatus:
- SUCCESS HSI oscillator is stable and ready to use
- ERROR HSI oscillator not yet ready
void RCC_SetHsiCalibValue(uint16_t calibration_value)调整内部高速振荡器(HSI)的校准值。
name RCC_SetHsiCalibValue.
fun Adjusts the Internal High Speed oscillator (HSI) calibration value.
param calibration_value(the calibration trimming value):
This parameter must be a number between 0 and 0x3FF
return none
void RCC_ConfigLsiCalibSource(uint32_t cal_src)配置 LSI 校准值的来源。
name RCC_ConfigLsiCalibSource.
fun Configures LSI calibration values source.
param cal_src:
- RCC_LSICAL_SRC_AFEC LSI calibration values are sourced from AFEC
- RCC_LSICAL_SRC_TRIM LSI calibration values are sourced from LSITRIM
return none
void RCC_SetLsiCalibValue(uint16_t calibration_value)调整内部低速振荡器(LSI)的校准值。
name RCC_SetLsiCalibValue.
fun Adjusts the Internal Low Speed oscillator (LSI) calibration value.
param calibration_value(the calibration trimming value):
This parameter must be a number between 0 and 0x1FF
return none
void RCC_ConfigSysclkPres(uint32_t sysclk_pres)配置系统时钟(SYSCLK)预分频。
name RCC_ConfigSysclkPres.
fun Configures the system clock (SYSCLK) prescaler.
param sysclk_pres(HSI divider used as system clock):
- RCC_SYSCLK_PRES_DIV1 HSI divide 1 used as system clock
- RCC_SYSCLK_PRES_DIV2 HSI divide 2 used as system clock
return none
void RCC_ConfigSysclk(uint32_t sysclk_source)配置系统时钟(SYSCLK)。
name RCC_ConfigSysclk.
fun Configures the system clock (SYSCLK).
param sysclk_source(clock source used as system clock):
- RCC_SYSCLK_SRC_HSI HSI(or divide 2) selected as system clock
- RCC_SYSCLK_SRC_LSI LSI selected as system clock
return none
uint32_t RCC_GetSysclkSrc(void)返回当前作为系统时钟的时钟源。
name RCC_GetSysclkSrc.
fun Returns the clock source used as system clock.
param none
return (The clock source used as system clock):
- RCC_CFG_SCLKSTS_HSI HSI used as system clock
- RCC_CFG_SCLKSTS_LSI LSI used as system clock
void RCC_ConfigHclk(uint32_t sysclk_div)配置 AHB 时钟(HCLK)。
name RCC_ConfigHclk.
fun Configures the AHB clock (HCLK).
param sysclk_div(AHB clock is derived from the system clock (SYSCLK)):
- RCC_SYSCLK_DIV1 AHB clock = SYSCLK
- RCC_SYSCLK_DIV2 AHB clock = SYSCLK/2
- RCC_SYSCLK_DIV4 AHB clock = SYSCLK/4
- RCC_SYSCLK_DIV8 AHB clock = SYSCLK/8
- RCC_SYSCLK_DIV16 AHB clock = SYSCLK/16
return none
void RCC_ConfigPclk(uint32_t hclk_div)配置低速 APB 时钟(PCLK)。
name RCC_ConfigPclk.
fun Configures the Low Speed APB clock (PCLK).
param hclk_div(APB clock is derived from the AHB clock (HCLK)):
- RCC_HCLK_DIV1 APB clock = HCLK
- RCC_HCLK_DIV2 APB clock = HCLK/2
- RCC_HCLK_DIV4 APB clock = HCLK/4
- RCC_HCLK_DIV8 APB clock = HCLK/8
- RCC_HCLK_DIV16 APB clock = HCLK/16
return none
void RCC_ConfigAdcHclk(uint32_t hclk_prescaler)配置 ADCHCLK 预分频。
name RCC_ConfigAdcHclk.
fun Configures the ADCHCLK prescaler.
param hclk_prescaler(ADCHCLK prescaler):
- RCC_ADCHCLK_DIV2 ADCHPRE[2:0] = 000, HCLK Clock Divided By 2
- RCC_ADCHCLK_DIV4 ADCHPRE[2:0] = 011, HCLK Clock Divided By 4
- RCC_ADCHCLK_DIV8 ADCHPRE[2:0] = 100, HCLK Clock Divided By 8
- RCC_ADCHCLK_DIV16 ADCHPRE[2:0] = 101, HCLK Clock Divided By 16
- RCC_ADCHCLK_DIV32 ADCHPRE[2:0] = 110, HCLK Clock Divided By 32
- RCC_ADCHCLK_DIV_OTHERS ADCHPRE[2:0] = others, HCLK Clock Divided By 32
return none
void RCC_GetClocksFreqValue(RCC_ClocksType* RCC_Clocks)返回片上各时钟的频率。
name RCC_GetClocksFreqValue.
fun Returns the frequencies of different on chip clocks.
param RCC_clocks pointer to a RCC_ClocksType structure which will hold
the clocks frequencies.
return none
void RCC_EnableAHBPeriphClk(uint32_t AHB_periph, FunctionalState Cmd)使能 AHB 外设时钟。
name RCC_EnableAHBPeriphClk.
fun Enables the AHB peripheral clock.
param AHB_periph (AHB peripheral to gates its clock):
- RCC_AHB_PERIPH_SQRT
- RCC_AHB_PERIPH_HDIV
- RCC_AHB_PERIPH_ADC
- RCC_AHB_PERIPH_DMA
param Cmd:
- ENABLE
- DISABLE
return none
void RCC_EnableAPBPeriphClk(uint32_t APB_periph, FunctionalState Cmd)使能高速 APB 外设时钟。
name RCC_EnableAPBPeriphClk.
fun Enables the High Speed APB peripheral clock.
param APB_periph (APB peripheral to gates its clock):
- RCC_APB_PERIPH_GPIO
- RCC_APB_PERIPH_I2C1
- RCC_APB_PERIPH_I2C2
- RCC_APB_PERIPH_PWR
- RCC_APB_PERIPH_SPI1
- RCC_APB_PERIPH_SPI2
- RCC_APB_PERIPH_TIM1
- RCC_APB_PERIPH_TIM3
- RCC_APB_PERIPH_TIM4
- RCC_APB_PERIPH_TIM6
- RCC_APB_PERIPH_UART1
- RCC_APB_PERIPH_UART2
- RCC_APB_PERIPH_UART3
- RCC_APB_PERIPH_COMP
- RCC_APB_PERIPH_COMPFILT
- RCC_APB_PERIPH_OPA
param Cmd:
- ENABLE
- DISABLE
return none.
void RCC_EnableAHBPeriphReset(uint32_t AHB_periph)AHB 外设复位。
name RCC_EnableAHBPeriphReset.
fun AHB peripheral reset.
param AHB_periph specifies the AHB peripheral to reset.
- RCC_AHB_PERIPH_SQRT
- RCC_AHB_PERIPH_HDIV
- RCC_AHB_PERIPH_ADC
return none.
void RCC_EnableAPBPeriphReset(uint32_t APB_periph)低速 APB(APB1)外设复位。
name RCC_EnableAPB1PeriphReset.
fun Low Speed APB (APB1) peripheral reset.
param APB1_periph specifies the APB1 peripheral to reset.
- RCC_APB_PERIPH_GPIO
- RCC_APB_PERIPH_I2C1
- RCC_APB_PERIPH_I2C2
- RCC_APB_PERIPH_SPI1
- RCC_APB_PERIPH_SPI2
- RCC_APB_PERIPH_TIM1
- RCC_APB_PERIPH_TIM3
- RCC_APB_PERIPH_TIM4
- RCC_APB_PERIPH_TIM6
- RCC_APB_PERIPH_UART1
- RCC_APB_PERIPH_UART2
- RCC_APB_PERIPH_UART3
- RCC_APB_PERIPH_COMP
- RCC_APB_PERIPH_OPA
return none.
使用提示: 该函数在 n32g033_rcc.h 第 239 行声明;源码注释块中的 name 写作 RCC_EnableAPB1PeriphReset.,与函数名 RCC_EnableAPBPeriphReset 不一致,注释原文照抄未改。
void RCC_ConfigMcoClkPre(uint32_t MCO_PLL_prescaler)配置 MCO 的系统时钟与 HSI 时钟预分频。
name RCC_ConfigMcoClkPre.
fun Configures the MCO System and HSI clock prescaler.
param MCO_PLL_prescaler specifies the MCO PLL clock prescaler.
This parameter can be on of the following values:
- RCC_MCO_CLK_DIV2 MCOPRE[2:0] = 010, System and HSI Clock Divided By 2
- RCC_MCO_CLK_DIV3 MCOPRE[2:0] = 011, System and HSI Clock Divided By 3
- RCC_MCO_CLK_DIV4 MCOPRE[2:0] = 100, System and HSI Clock Divided By 4
- RCC_MCO_CLK_DIV5 MCOPRE[2:0] = 101, System and HSI Clock Divided By 5
- RCC_MCO_CLK_DIV6 MCOPRE[2:0] = 110, System and HSI Clock Divided By 6
- RCC_MCO_CLK_DIV7 MCOPRE[2:0] = 111, System and HSI Clock Divided By 7
return none.
void RCC_ConfigMco(uint32_t MCO_source)选择在 MCO 引脚上输出的时钟源。
name RCC_ConfigMco.
fun Selects the clock source to output on MCO pin.
param MCO_source(clock source to output):
- RCC_MCO_NOCLK No clock selected
- RCC_MCO_LSI LSI oscillator clock selected
- RCC_MCO_SYSCLK System clock selected
- RCC_MCO_HSI HSI oscillator clock selected
return none.
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG)检查指定的 RCC 标志是否置位。
name RCC_GetFlagStatus.
fun Checks whether the specified RCC flag is set or not.
param RCC_flag:
- RCC_CTRL_FLAG_HSIRDF HSI oscillator clock ready
- RCC_CTRL_FLAG_LSICALCF LSI Calibration finish
- RCC_CLKINT_FLAG_LSIRDF LSI oscillator clock ready
- RCC_CTRLSTS_FLAG_PINRSTF Pin reset
- RCC_CTRLSTS_FLAG_PORRSTF POR/PDR reset
- RCC_CTRLSTS_FLAG_SFTRSTF Software reset
- RCC_CTRLSTS_FLAG_IWDGRSTF Independent Watchdog reset
- RCC_CTRLSTS_FLAG_GLITCHF Glitch reset
- RCC_CTRLSTS_FLAG_EMCGBNRSTF EMCGBN reset
- RCC_CTRLSTS_FLAG_EMCGBRSTF EMCGB reset
- RCC_CTRLSTS_FLAG_LKUPRSTF M0 lock up reset
return FlagStatus:
- SET
- RESET
void RCC_ClearResetFlag(void)清除 RCC 复位标志。
name RCC_ClearResetFlag.
fun Clears the RCC reset flags.
param none
return none
note Clear the following flags:
- RCC_CTRLSTS_FLAG_PINRSTF Pin reset
- RCC_CTRLSTS_FLAG_PORRSTF POR/PDR reset
- RCC_CTRLSTS_FLAG_SFTRSTF Software reset
- RCC_CTRLSTS_FLAG_IWDGRSTF Independent Watchdog reset
- RCC_CTRLSTS_FLAG_GLITCHF Glitch reset
- RCC_CTRLSTS_FLAG_EMCGBNRSTF EMCGBN reset
- RCC_CTRLSTS_FLAG_EMCGBRSTF EMCGB reset
- RCC_CTRLSTS_FLAG_LKUPRSTF M0 lock up reset
INTStatus RCC_GetIntStatus(uint8_t interrupt_flag)检查指定的 RCC 中断是否发生。
name RCC_GetIntStatus.
fun Checks whether the specified RCC interrupt has occurred or not.
param interrupt_flag(RCC interrupt source to check):
- RCC_INT_LSIRDIF LSI ready interrupt
- RCC_INT_HSIRDIF HSI ready interrupt
return The new state of RccInt
- SET
- RESET
void RCC_ClrIntPendingBit(uint32_t interrupt_clear)清除 RCC 的中断挂起位。
name RCC_ClrIntPendingBit.
fun Clears the RCC's interrupt pending bits.
param RccInt specifies the interrupt pending bit to clear.
- RCC_CLR_LSIRDIF Clear LSI ready interrupt flag
- RCC_CLR_HSIRDIF Clear HSI ready interrupt flag
return none.
void RCC_EnableEMCReset(uint32_t EMC_type, FunctionalState Cmd)配置 EMC 错误发生时是否产生复位请求。
name RCC_EnableEMCReset.
fun Configure whether to generate a reset request when an EMC error occurs.
param EMC_type:
- RCC_EMC_GB
- RCC_EMC_GBN
param Cmd:
- ENABLE
- DISABLE
return none.
void RCC_EnableEMCDetect(uint32_t EMC_type, FunctionalState Cmd)配置是否使能 EMC 检测。
name RCC_EnableEMCDetect.
fun Configure whether to enable EMC detection.
param EMC_type:
- RCC_EMC_GB
- RCC_EMC_GBN
param Cmd:
- ENABLE
- DISABLE
return none.
void RCC_EnableEMCSwitch(uint32_t EMC_type, FunctionalState Cmd)配置是否使能 EMC 切换。
name RCC_EnableEMCSwitch.
fun Configure whether to enable EMC switch.
param EMC_type:
- RCC_EMC_GB
- RCC_EMC_GBN
param Cmd:
- ENABLE
- DISABLE
return none.
void RCC_ConfigEMCDetectLevel(uint32_t EMC_type, uint8_t level)配置 EMC 检测的电压阈值。
name RCC_ConfigEMCDetectLevel.
fun Configures the voltage threshold detected by the EMC.
param EMC_type:
- RCC_EMC_GB
- RCC_EMC_GBN
param level (The input parameters must be the following values):
- 0x0 ~ 0x3
return none
void RCC_EnableGlitchDetect(FunctionalState Cmd)配置是否使能 Glitch 检测。
name RCC_EnableGlitchDetect.
fun Configure whether to enable Glitch.
param Cmd:
- ENABLE
- DISABLE
return none.
note After enabling the GVDET bit by RCC_EnableGlitchDetect(), a delay of 10us or more is required to
enable the GVRST bit and GVSW bit by RCC_EnableGlitchReset() and RCC_EnableGlitchSwitch().
void RCC_EnableGlitchReset(FunctionalState Cmd)配置是否使能 Glitch 复位。
name RCC_EnableGlitchReset.
fun Configure whether to enable Glitch reset.
param Cmd:
- ENABLE
- DISABLE
return none.
void RCC_EnableGlitchSwitch(FunctionalState Cmd)配置是否使能 Glitch 切换。
name RCC_EnableGlitchSwitch.
fun Configure whether to enable Glitch switch.
param Cmd:
- ENABLE
- DISABLE
return none.
void RCC_ConfigGlitchDetectLevel(uint8_t level)配置 Glitch 检测的电压阈值。
name RCC_ConfigGlitchDetectLevel.
fun Configures the voltage threshold detected by the Glitch.
param level (The input parameters must be the following values):
- 0x0 ~ 0x1F
return none
void RCC_EnableM0LockupReset(FunctionalState Cmd)配置是否使能 M0 死锁复位。
name RCC_EnableM0LockupReset.
fun Configure whether to enable M0 lockup reset.
param Cmd:
- ENABLE
- DISABLE
return none.
void RCC_ConfigTimClk(uint32_t timer_clksrc)配置 TIM1/3/4 时钟源(TIMCLK)。
name RCC_ConfigTimClk.
fun Configures the TIM1/3/4 clock source(TIMCLK).
param timer_clksrc(TIM clock source):
- RCC_TIM_CLKSRC_HCLK
- RCC_TIM_CLKSRC_SYSCLK
return none
void RCC_ConfigTim6Clk(uint32_t timer_clksrc)配置 TIM6 时钟源(TIM6CLK)。
name RCC_ConfigTim6Clk.
fun Configures the TIM6 clock source(TIM6CLK).
param timer_clksrc(TIM6 clock source):
- RCC_TIM6_CLKSRC_SYSCLK
- RCC_TIM6_CLKSRC_LSI
return none
void RCC_ConfigUart3Clk(uint32_t uart3_clksrc)配置 UART3 时钟源(UART3CLK)。
name RCC_ConfigUart3Clk.
fun Configures the UART3 clock source(UART3CLK).
param uart3_clksrc(UART3 clock source):
- RCC_UART3_CLKSRC_PCLK
- RCC_UART3_CLKSRC_LSI
return none
void RCC_ConfigIOFilter(uint32_t ioflitclk_div)配置 GPIO 滤波速度。
name RCC_ConfigIOFilter.
fun Configures the Speed of GPIO fliter.
param ioflitclk_div value(IO Fliter clock is derived from the AHB clock (HCLK)):
-0 ~ 0xF
return none
void RCC_ConfigTIM4Filter(uint32_t tim4flitclk_div)配置 TIM4 滤波速度。
name RCC_ConfigTIM4Filter.
fun Configures the Speed of TIM4 fliter.
param tim4flitclk_div value(TIM4 Fliter clock is derived from the AHB clock (HCLK)):
-0 ~ 0x1F
return none
void RCC_ConfigTIM3Filter(uint32_t tim3flitclk_div)配置 TIM3 滤波速度。
name RCC_ConfigTIM3Filter.
fun Configures the Speed of TIM3 fliter.
param tim3flitclk_div value(TIM3 Fliter clock is derived from the AHB clock (HCLK)):
-0 ~ 0x1F
return none
void RCC_ConfigTIM1Filter(uint32_t tim1flitclk_div)配置 TIM1 滤波速度。
name RCC_ConfigTIM1Filter.
fun Configures the Speed of TIM1 fliter.
param tim1flitclk_div value(TIM1 Fliter clock is derived from the AHB clock (HCLK)):
-0 ~ 0x1F
return none
void RCC_ConfigLSICalibPeriod(uint32_t lsi_period)配置 LSI 校准周期。
name RCC_ConfigLSICalibPeriod.
fun Configure LSI Calibration Period.
param lsi_period:
- RCC_LSICAL_PERIOD_128 Count the HSI clock within 128 LSI cycles
- RCC_LSICAL_PERIOD_256 Count the HSI clock within 256 LSI cycles
- RCC_LSICAL_PERIOD_512 Count the HSI clock within 512 LSI cycles
- RCC_LSICAL_PERIOD_1024 Count the HSI clock within 1024 LSI cycles
return none
void RCC_EnableLSICalibration(FunctionalState Cmd)配置是否启动 LSI 校准计算。
name RCC_EnableLSICalibration.
fun Configure whether to start LSI Calibration calculation.
param Cmd:
- ENABLE
- DISABLE
return none.
uint32_t RCC_GetHSICalibPeriod(void)获取 HSI(64 MHz)在校准周期内捕获的 LSI 周期数。
name RCC_GetHSICalibPeriod
fun Gets the HSI(64MHz) captures the number of LSI cycles within the clock calibration period.
param none
return HSI captures value.
5.15.3 Demo 示例说明
本节说明 RCC 的 2 个示例:LSI_Calibration 用 HSI 测量 LSI 频率并按偏差调整 trim 值,RCC_ClockConfig 在 HSI、HSI/2 与 LSI 之间切换系统时钟并通过 MCO 与串口输出结果。
5.15.3.1 LSI_Calibration LSI 频率测量与 trim 校准
工程目录: projects/n32g033_EVAL/examples/RCC/LSI_Calibration/
配置引脚并把 LSI 输出到 MCO→等待 HSI 与 LSI 就绪→设定校准周期并启动校准计数→校准完成后读取计数结果→按测量频率算出 trim 并写回 LSI 校准寄存器
| 项目 | 源码解读 |
|---|---|
| 功能 | 先让 LSI 稳定并作为 MCO 输出,再用固定 64 MHz 的 HSI 在校准周期内计数,算出 LSI 实际频率并调整 trim 值。 |
| 源码组成 | src/main.c 含 main 与 GPIO_Configuration;inc/main.h 给出外设头文件与声明;readme.txt 给出配置与测试步骤;工程文件在 MDK-ARM/ 与 EWARM/。 |
| 关键配置 | 时钟:HSI 64 MHz、LSI 约 32 KHz; 校准周期: RCC_LSICAL_PERIOD_128;MCO:PA8 复用输出; trim 源: RCC_LSICAL_SRC_TRIM。 |
| 程序与数据路径 | main → GPIO_Configuration 打开 GPIO 时钟并把 PA8 设为复用 → RCC_ConfigMco 选择输出 LSI → 等待 HSIRDF、LSIRDF → RCC_ConfigLSICalibPeriod 设周期 → RCC_EnableLSICalibration 启动 → 等待 LSICALCF → 用 RCC_GetHSICalibPeriod 算出频率 → 由偏差算出 trim → RCC_SetLsiCalibValue 写回。 |
| 主要 API | RCC_ConfigMco、RCC_GetFlagStatus、RCC_ConfigLSICalibPeriod、RCC_EnableLSICalibration、RCC_GetHSICalibPeriod、RCC_ConfigLsiCalibSource、RCC_SetLsiCalibValue |
| 验证方法 | 编译下载后器件按测量频率校准 LSI; 用示波器抓 PA8 的 MCO 波形,观察频率随 trim 调整而变化。 |
| 使用提示 | 开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1,硬件基于评估板 N32G033K8Q7-1_STB V1.0; 读 LSI 校准计数结果前必须等 LSICALCF 置位,否则计数未完成。 |
核心代码解读与移植
示例先把 LSI 引到 MCO 便于观测,再等待两个振荡器就绪,启动一次 LSI 校准计数并按结果调整 trim。
数据路径: GPIO_Configuration 配 PA8 复用 → RCC_ConfigMco 输出 LSI → 等待 HSIRDF/LSIRDF → RCC_ConfigLSICalibPeriod → RCC_EnableLSICalibration → 等待 LSICALCF → RCC_GetHSICalibPeriod 算频率 → RCC_ConfigLsiCalibSource → RCC_SetLsiCalibValue
1. 先把 LSI 引到 MCO 引脚。 配置 PA8 为复用输出,再选择 MCO 时钟源为 LSI,便于用示波器观测。
/* MCO Configuration */
GPIO_Configuration();
RCC_ConfigMco(RCC_MCO_LSI);
若只需校准而不需观测,可省去 MCO 输出,校准逻辑本身不依赖它。
2. 等待两个振荡器就绪后再计数。 校准要求 HSI、LSI 都稳定,因此逐个等待对应的 ready 标志置位。
/* Wait HSI ready */
while (RCC_GetFlagStatus(RCC_CTRL_FLAG_HSIRDF) == RESET)
{}
/* Wait LSI ready */
while (RCC_GetFlagStatus(RCC_CLKINT_FLAG_LSIRDF) == RESET)
{}
把 HSI/LSI 的准备标志改成对应宏即可复用到其他校准项,等待循环不要加超时以外的副作用。
3. 设定校准周期并启动,等待完成标志。 一个周期内用 LSI 计满设定个数,同时用 HSI 计数,完成后 LSICALCF 置位。
RCC_EnableLSICalibration(ENABLE);
/* Wait HSI ready */
while (RCC_GetFlagStatus(RCC_CTRL_FLAG_LSICALCF) == RESET)
{}
校准周期可选 128、256、512、1024 个 LSI 周期,周期越长结果越平滑但耗时越久。
4. 按计数结果算频率并选择 trim 源。 用 64 MHz 乘周期数再除以 HSI 计数得到 LSI 频率,并把 trim 来源切到 LSITRIM 以便软件写值。
Lsi_Cal_Value = ((uint64_t)HSI_VALUE * 128 / RCC_GetHSICalibPeriod());
/* LSI trim value computation */
Lsi_Trim_Value1 = (RCC->LSCTRL & 0x01FF);
RCC_ConfigLsiCalibSource(RCC_LSICAL_SRC_TRIM);
换用其他校准周期时,公式里的 128 要与 RCC_ConfigLSICalibPeriod 的取值保持一致。
5. 把算出的 trim 写回 LSI 校准寄存器。 依据测量频率与 32 KHz 的偏差增减 trim,再写入生效。
/* LSI trim*/
RCC_SetLsiCalibValue(Lsi_Trim_Value1);
trim 有效范围为 0 到 0x1FF,越界时需在计算阶段做钳位,避免写入无效值。
对应源码: src/main.c、firmware/n32g033_std_periph_driver/inc/n32g033_rcc.h
5.15.3.2 RCC_ClockConfig 系统时钟切换与输出
工程目录: projects/n32g033_EVAL/examples/RCC/RCC_ClockConfig/
打印复位后的时钟信息→按宏选择把系统时钟切到 HSI 或 LSI→重新打印当前时钟频率→配置引脚并把系统时钟分频后输出到 MCO
| 项目 | 源码解读 |
|---|---|
| 功能 | 分别把系统时钟配成 HSI、HSI/2 或 LSI,打印当前 SYSCLK、HCLK、PCLK,并把系统时钟分频后从 PA8 的 MCO 输出。 |
| 源码组成 | src/main.c 含 PrintfClockInfo、SetSysClockToHSI、SetSysClock_LSI;inc/n32g033_it.h 定义系统时钟源选择宏;readme.txt 给出配置与测试步骤;工程文件在 MDK-ARM/ 与 EWARM/。 |
| 关键配置 | 时钟源选择宏:SYSCLK_SOURCE_SELECT,默认 SYSCLK_SOURCE_HSI_DIV2;MCO:PA8 复用输出,预分频 RCC_MCO_CLK_DIV4,源 RCC_MCO_SYSCLK;打印口:PA9,波特率 115200。 |
| 程序与数据路径 | main → PrintfClockInfo 打印复位后时钟 → 按 SYSCLK_SOURCE_SELECT 调用 SetSysClockToHSI 或 SetSysClock_LSI → 再 PrintfClockInfo → 打开 GPIO 时钟并把 PA8 设为复用 → RCC_ConfigMcoClkPre 设分频 → RCC_ConfigMco 输出 SYSCLK。 |
| 主要 API | RCC_GetClocksFreqValue、RCC_EnableHsi、RCC_WaitHsiStable、RCC_ConfigHclk、RCC_ConfigPclk、RCC_ConfigSysclkPres、RCC_ConfigSysclk、RCC_GetSysclkSrc、RCC_ConfigMcoClkPre、RCC_ConfigMco |
| 验证方法 | 编译下载复位运行后,串口分别打印 HSI、HSI/2、LSI 下的 SYSCLK、HCLK、PCLK; 用示波器查看 PA8 的 MCO 输出频率。 |
| 使用提示 | 开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1,硬件基于评估板 N32G033K8Q7-1_STB V1.0; 系统时钟切到 LSI 后,串口波特率需改为 1200 才能正常打印。 |
核心代码解读与移植
示例先打印复位后的时钟,再按宏切换系统时钟并复打印,最后把系统时钟分频后从 MCO 输出。
数据路径: PrintfClockInfo 取时钟频率并打印 → SetSysClockToHSI 或 SetSysClock_LSI 切换系统时钟 → PrintfClockInfo 复打印 → 配 PA8 复用 → RCC_ConfigMcoClkPre → RCC_ConfigMco 输出 SYSCLK
1. 用结构体读回并打印各时钟频率。 切换前后各调用一次,便于对比;因主频改变,重新初始化日志后打印才不会乱码。
void PrintfClockInfo(const char* msg)
{
log_init(); // should reinit after sysclk changed
log_info("\n--------------------------------\n");
log_info("%s:\n", msg);
RCC_GetClocksFreqValue(&RCC_ClockFreq);
log_info("SYSCLK: %d\n", RCC_ClockFreq.SysclkFreq);
log_info("HCLK: %d\n", RCC_ClockFreq.HclkFreq);
log_info("PCLK: %d\n", RCC_ClockFreq.PclkFreq);
}
RCC_ClocksType 的成员字段随驱动版本固定,打印前先重新初始化串口可避免波特率不匹配。
2. 切换系统时钟到 HSI。 先开 HSI 并等它稳定,再配置 Flash 等待周期与总线分频,最后选择 HSI 作为系统时钟并等待生效。
RCC_EnableHsi(ENABLE);
/* Wait till HSI is ready */
HSIStartUpStatus = RCC_WaitHsiStable();
if (HSIStartUpStatus == SUCCESS)
{
/* Flash 1 wait state */
FLASH_SetLatency(FLASH_LATENCY_1);
/* HCLK = SYSCLK */
RCC_ConfigHclk(RCC_SYSCLK_DIV1);
HSI 不能在使用它作为系统时钟时被关闭;切到更高主频前要同步调整 Flash 等待周期。
3. 切换系统时钟到 LSI。 LSI 就绪后把 AHB、APB 分频设为不分频,选择 LSI 为系统时钟并等待状态位切换。
/* Wait till LSI is ready */
if (RCC_GetFlagStatus(RCC_CLKINT_FLAG_LSIRDF) == SET)
{
/* HCLK = SYSCLK */
RCC_ConfigHclk(RCC_SYSCLK_DIV1);
/* PCLK = HCLK */
RCC_ConfigPclk(RCC_HCLK_DIV1);
LSI 作为系统时钟后主频很低,串口、定时等依赖主频的外设都要重新按新频率配置。
4. 配置 MCO 输出系统时钟。 先设 MCO 预分频,再选择输出源为 SYSCLK。
RCC_ConfigMcoClkPre(RCC_MCO_CLK_DIV4);
/*** Select the corresponding MCO clock source ***/
RCC_ConfigMco(RCC_MCO_SYSCLK);
MCO 输出引脚必须先配成对应复用功能,改用 HSI 或 LSI 作为输出源时只需改选择宏。
对应源码: src/main.c、inc/n32g033_it.h、firmware/n32g033_std_periph_driver/inc/n32g033_rcc.h
5.15.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| 系统时钟范围 | 用户手册 RCC 章写明系统时钟最大 64 MHz、AHB 最大 64 MHz、APB 最大 32 MHz; 修改分频系数时要保证 APB 频率不超过 32 MHz。 |
用户手册 |
| 时钟源切换顺序 | 用户手册 RCC 章写明系统复位后选择 HSI 作为系统时钟,且只有目标时钟源准备好后才能切换; 切换由 RCC_CFG.SCLKSW 控制、由 SCLKSTS 反映状态。 |
用户手册 |
| HSI 关闭条件 | 用户手册 RCC 章写明 HSI 直接或经 PLL 作为系统时钟时不能被关闭; 切到 LSI 并完成切换后,才可禁能 HSI 以降低功耗。 |
用户手册 |
| LSI 校准计数 | 用户手册 RCC 章写明校准计数在 LSICALLEN 设定的 LSI 周期内统计 HSI 周期数,结束后 LSICALCF 置位;公式为 LSI 频率 = 64000000 × N ÷ RCC_LSICAL。 |
用户手册 |
| MCO 输出配置 | 用户手册 RCC 章写明 MCO 引脚对应的 GPIO 必须配置为复用功能,输出源由 RCC_CFG.MCO[1:0] 选择;可输出 SYSCLK 分频值、HSI 分频值或 LSI。 |
用户手册 |
| Glitch 检测时序 | 用户手册 RCC 章写明使能 GVDET 位后需延时 10 µs 及以上,才能使能 GVRST 位与 GVSW 位; 时序不满足时检测与保护可能不生效。 |
用户手册 |
| TIM6/UART3 的 STOP 时钟源 | 用户手册 RCC 章写明 TIM6、UART3 若要在系统 STOP 状态工作,其时钟源必须配置为 LSI; 否则进入 STOP 后这两个外设停止工作。 |
用户手册 |
| 复位源识别 | 用户手册 RCC 章写明可通过 RCC_CTRLSTS 的复位标志识别复位源,寄存器的 RMRSTF 位写 1 可清除这些标志;读标志前应先确认是否需要保留上一次的复位源信息。 |
用户手册 |
勘误手册 V1.0.0(2025.9.25)针对 A 版芯片,未列出 RCC 相关条目。