前言
本应用入门指南主要介绍两部分内容:
1、基于雅特力提供的V2.x.x的板级支持包来进行时钟源码的配置及修改
2、如何使用配套的时钟配置工具来进行时钟路径及参数的设定,生成相应的时钟流程代码并使用。
支持型号:AT32F402系列/AT32F405系列
备注:本文档仅供有需求的小伙伴参考,如需更多资料,可访问雅特力官网获取。
时钟是芯片正确高效运行的基础,正确的时钟配置是芯片能正确运行的必要条件,其重要性不言而喻。AT32各系列产品的时钟配置部分可能存在细微的差异和需要注意的事项,本文档就着重针对各系列的情况来详细介绍如何结合雅特力提供的V2.x.x的板级支持包(BSP)来配置时钟。
以下介绍时钟配置的方法主要分两种:
- 1)以手动编写代码调用BSP中提供的驱动函数接口来进行时钟配置。
2、 2)采用时钟工具来配置并生成相应的源码文件。 2 时钟树
在进行时钟配置之前,应充分了解对应芯片的时钟树结构,这样在进行时钟配置时才会游刃有余。对于系统时钟频率及路径的配置我们需要关注时钟源、倍频及系统时钟部分。类似如下图:
可由图中得到以下几个关键信息:
1) 1) SCLKSEL:系统时钟可以由HEXT、PLLCLK、HICK三大时钟源提供。
2) 2) HEXT:HEXT是外部高速时钟,其可以外接范围是4~25 MHz的晶振或时钟源。
3) 3)HICK:HICK RC是内部高速振荡器,频率为48 MHz。HICK时钟由内部振荡器给出,但在初始情况下由HICKDIV控制并默认6分频后为8 MHz,亦可配置为不分频,保持48 MHz的频率。
4) 4) PLLCLK:PLL时钟 = PLL输入时钟 / PLL_MS * PLL_NS / PLL_FP。
5) 5) PLL输入时钟:PLL的输入时钟由PLLRCS决定,有两个来源:HICK 8 MHz和HEXT。
3 3.代码配置解析以下将以库函数接口为核心来对时钟配置流程和方法进行说明。
3.1 函数接口
各系列产品对应提供的BSP中对硬件的时钟设置部分已封装好接口函数以供调用,以下罗列出时钟配置常用的函数接口,各函数的具体参数及返回值类型等请参考at32f402_405_crm.c/.h文件。
- /* 时钟和复位管理模块的复位函数,将时钟配置部分恢复到默认值 */
- void crm_reset(void);
复制代码- /* 外部高速时钟的旁路使能函数 */
- void crm_hext_bypass(confirm_state new_state);
复制代码- /* 各状态标志的获取函数,如PLL/HEXT/HICK等时钟源的稳定标志等 */
- flag_status crm_flag_get(uint32_t flag);
复制代码- /* 等待外部高速时钟稳定 */
- error_status crm_hext_stable_wait(void);
复制代码- /* 时钟源使能函数,如PLL/HEXT/HICK等时钟源的使能 */
- void crm_clock_source_enable(crm_clock_source_type source, confirm_state new_state);
复制代码- /* PLL配置函数,配置内容包括:PLL时钟源、各PLL倍频系数等 */
- void crm_pll_config(crm_pll_clock_source_type clock_source, uint16_t pll_ns, uint16_t pll_ms, crm_pll_fp_type pll_fp);
复制代码- /* PLLU后分频系数配置 */
- void crm_pllu_div_set(crm_pll_fu_type pll_fu);
复制代码- /* PLLU输出使能 */
- void crm_pllu_output_set(confirm_state new_state);
复制代码- /* 系统时钟切换函数 */
- void crm_sysclk_switch(crm_sclk_type value);
复制代码- /* 当前系统时钟切换状态获取函数 */
- crm_sclk_type crm_sysclk_switch_status_get(void);
复制代码- /* 自动顺滑使能函数,当PLL倍频频率大于108 MHz时,切换系统时钟到PLL前需开启 */
- void crm_auto_step_mode_enable(confirm_state new_state);
复制代码- /* 内部高速时钟6分频配置函数,主要用于hick 48 MHz接入系统时钟 */
- void crm_hick_divider_select(crm_hick_div_6_type value);
复制代码- /* 内部高速时钟用做系统时钟时的频率路径选择函数,可设置固定路径(8 MHz),6分频路径路径(8 MHz或48 MHz由6分频配置函数决定) */
- void crm_hick_sclk_frequency_select(crm_hick_sclk_frequency_type value);
复制代码- /* 系统时钟到AHB时钟的分频设置函数 */
- void crm_ahb_div_set(crm_ahb_div_type value);
复制代码- /* AHB时钟到APB1时钟的分频设置函数 */
- void crm_apb1_div_set(crm_apb1_div_type value);
复制代码- /* AHB时钟到APB2时钟的分频设置函数 */
- void crm_apb2_div_set(crm_apb2_div_type value);
复制代码- /* HEXT时钟到系统时钟的分频设置函数 */
- void crm_hext_sclk_div_set(crm_hext_sclk_div_type value);
复制代码- /* HICK时钟到系统时钟的分频设置函数 */
- void crm_hick_sclk_div_set(crm_hick_sclk_div_type value);
复制代码 3.2 时钟配置流程按常规应用来讲解时钟配置流程. 3.2.1 复位(CRM Reset)
首先按规范流程应复位CRM配置参数,其主要是将系统时钟切换到HICK,其余的系统时钟配置寄存器写入默认值,待后续进行新配置参数的写入。函数调用的代码实现如下:
- crm_reset(); /* CRM 复位 */
复制代码 3.2.2 Flash等待周期(Set Flash Wait Cycle)AT32F402/405片上采用的是嵌入式Flash,当运行在不同的主频下时需对应设定Flash等待周期。flash等待周期与运行主频关系如下:
| SystemClock Frequency | FlashWait Cycle | | 0<sysclk <=32 MHz | FLASH_WAIT_CYCLE_0 | | 32<sysclk <=64 MHz | FLASH_WAIT_CYCLE_1 | | 64<sysclk <=96 MHz | FLASH_WAIT_CYCLE_2 | | 96<sysclk <=128 MHz | FLASH_WAIT_CYCLE_3 | | 128<sysclk <=160 MHz | FLASH_WAIT_CYCLE_4 | | 160<sysclk <=192 MHz | FLASH_WAIT_CYCLE_5 | | 192<sysclk <=216 MHz | FLASH_WAIT_CYCLE_6 | | |
| 函数调用的代码实现如下:
- flash_psr_set(FLASH_WAIT_CYCLE_0); /* 设置flash等待周期0 cycle */
复制代码 3.2.3 时钟源配置(Clock Source Configuration)与系统时钟相关的高速时钟源主要包括HEXT和HICK,PLL也是使用以上时钟源来进行倍频。需要在配置使能PLL前将所使用的PLL参考时钟源开启并等待其稳定。
u HHEXT
外部高速时钟如采用外接有源时钟的方式时,可开启旁路模式来进行使用,采用晶振时,不能开启旁路模式,旁路模式应在外部高速时钟源使能前进行设定,其默认情况为关闭。旁路模式使能代码实现如下:
- crm_hext_bypass(TRUE); /* HEXT时钟旁路模式开启 */
复制代码使能HEXT时钟源并等待HEXT时钟稳定,代码实现如下: - crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE); /* 开启HEXT时钟源 */
- while(crm_hext_stable_wait() == ERROR) /* 等待HEXT时钟稳定 */
- {
- }
复制代码u HICK
内部高速时钟是由芯片内部振荡器提供,使能HICK时钟源并等待HICK时钟稳定,代码实现如下: - crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE); /* 开启HICK时钟源 */
- while(crm_flag_get(CRM_HICK_STABLE_FLAG) != SET) /* 等待HICK稳定标志置起 */
- {
- }
复制代码 3.2.4 PLL配置(PLL Configuration)PLL配置主要包括:PLL时钟源、PLL倍频系数、PLL倍频频率范围等的设置。倍频时钟公式为:PLLCLK = (PLL输入时钟 * PLL_NS) / (PLL_MS * PLL_FP)。
u PLL时钟源
PLL时钟源细分有如下来源:1、HICK(8 MHz),2、HEXT。PLL时钟源应在PLL配置使能前开启并等待稳定。以上PLL时钟源在crm_pll_config函数中对应的参数定义如下:
- CRM_PLL_SOURCE_HICK
- CRM_PLL_SOURCE_HEXT
复制代码u PLL倍频系数 PLL_MS:PLL预分频系数,范围值1~15。其功能是对PLL输入时钟进行预分频。 PLL_NS:PLL倍频参数,范围值31~500。其功能是对PLL_MS进行预分频处理后的时钟进行倍频。 PLL_FP:PLLP后分频系数,范围(1、2、4、6、8、10、12、14、16、18、20、22、24、26、28、30)。其功能是对PLL_NS倍频后的时钟进行后除频,除频后的时钟才是PLLP时钟,PLLP时钟可选作为系统时钟。 PLL_FU:PLLU后分频系数,范围(11、12、13、14、16、18、20)。其功能是对PLL_NS倍频后的时钟进行后除频,除频后的时钟才是PLLU时钟, PLLU时钟可选作为USB外设的时钟源。 注:PLLU分频系数需要在PLL使能之前进行配置,在PLL使能后配置无效。 以上参数在搭配使用时有如下限制条件,详情可参考RM的时钟源章节: - 2 MHz <= PLL输入时钟 / PLL_MS <= 16 MHz
- 500 MHz <= PLL输入时钟 * PLL_NS / PLL_MS <= 1000 MHz
复制代码当PLL参数设置完成后,即可开启PLL并等待PLL稳定。示例:外部时钟晶振8 MHz,采用HEXT 时钟作为PLL时钟源,PLLCLK倍频到216 MHz的代码实现如下:
- crm_pll_config(CRM_PLL_SOURCE_HEXT, 108, 1, CRM_PLL_FP_4); /* 配置PLL参数 */
- crm_pllu_div_set(CRM_PLL_FU_18); /* 配置PLLU分频参数 */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE); /* 开启PLL时钟源 */
- while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET) /* 等待PLL稳定标志置起 */
- {
- }
- crm_pllu_output_set(TRUE); /* 开启PLLU输出 */
- while(crm_flag_get(CRM_PLLU_STABLE_FLAG) != SET) /* 等待PLLU稳定标志置起 */
- {
- }
复制代码 3.2.5 总线分频(Set Bus Frequency Division)总线分频包含SCLK到AHBCLK分频、AHBCLK到APB1CLK分频、AHBCLK到APB2CLK分频。AHB总线1分频、APB1/APB2总线1分频的代码实现如下:
- crm_ahb_div_set(CRM_AHB_DIV_1); /* SCLK 1分频作为AHB总线时钟 */
- crm_apb2_div_set(CRM_APB2_DIV_1); /* AHBCLK 1分频作为APB2总线时钟,最大频率216MHz*/
- crm_apb1_div_set(CRM_APB1_DIV_1); /* AHBCLK 1分频作为APB1总线时钟,最大频率120MHz*/
复制代码注:APB2CLK的最大频率为216MHz,APB1CLK的最大频率为120MHz。 3.2.6 切换系统时钟(Switch System Clock)系统时钟来源主要有三个:HICK、HEXT、PLLCLK。在切换系统时钟到如上时钟源时应提前确保对应时钟源已稳定。
u HICK系统时钟
内部高速时钟在系统复位重新运行时默认作为系统时钟,后期代码进行设定时,可有两种频率值来进行设定(8 MHz和48 MHz)。如图1所述HICK默认情况下用的是8 MHz,可配置为48 MHz。
HICK 8 MHz用作系统时钟的代码实现如下:
- crm_hick_sclk_div_set(CRM_HICK_SCLK_DIV_1); /* 设置HICK到系统时钟分频 */
- crm_sysclk_switch(CRM_SCLK_HICK); /* 切换系统时钟到HICK */
- while(crm_sysclk_switch_status_get() != CRM_SCLK_HICK) /* 等待系统时钟状态为HICK */
- {
- }
复制代码HICK 48 MHz用作系统时钟的代码实现如下: - crm_hick_sclk_frequency_select (CRM_HICK_SCLK_48MHZ); /* HICK选择hick48MHz */
- crm_hick_sclk_div_set(CRM_HICK_SCLK_DIV_1); /* 设置HICK到系统时钟分频 */
- crm_sysclk_switch(CRM_SCLK_HICK); /* 切换系统时钟到HICK */
- while(crm_sysclk_switch_status_get() != CRM_SCLK_HICK) /* 等待系统时钟状态为HICK */
- {
- }
复制代码u HEXT系统时钟
外部高速时钟用作系统时钟时,其系统时钟频率以实际使用的外部时钟频率为准,范围为4~25 MHz。HEXT用作系统时钟的代码实现如下: - crm_hext_sclk_div_set(CRM_HEXT_SCLK_DIV_1); /* 设置HEXT到系统时钟分频 */
- crm_sysclk_switch(CRM_SCLK_HEXT); /* 切换系统时钟到HEXT */
- while(crm_sysclk_switch_status_get() != CRM_SCLK_HEXT) /* 等待系统时钟状态为HEXT */
- {
- }
复制代码u PLLCLK系统时钟
PLLCLK用作系统时钟时,频率值以实际的PLL倍频结果为准。其最高频率应满足芯片规格为基础。PLLCLK用作系统时钟的代码实现如下: - crm_sysclk_switch(CRM_SCLK_PLL); /* 切换系统时钟到PLL */
- while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL) /* 等待系统时钟状态为PLL */
- {
- }
复制代码 3.2.7 更新核心频率(Update Core Frequency)
提供的BSP中,其代码框架内保留了一个表示系统核心频率的参数值system_core_clock,其保存的是CPU核心的运行频率值,应该在每次系统时钟配置完成后来进行更新。为的是在整个代码框架下,各外设驱动的频率配置能很快获取到当前核心运行频率值并使用。代码实现如下:
- system_core_clock_update(); /* 更新系统核心频率值system_core_clock */
复制代码 3.3 时钟配置示例以下将以完整的时钟配置流程来进行说明,示例:由8 MHz外部时钟晶振作为时钟源,经PLL倍频后,216 MHz用做系统时钟,AHB不分频,APB2采用1分频,APB1采用2分频。函数system_clock_config代码实现如下:
- void system_clock_config(void)
- {
- crm_reset(); /* CRM 复位 */
- flash_psr_set(FLASH_WAIT_CYCLE_6); /* 设置flash 等待周期6 cycle */
- crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE); /* PWC外设时钟使能 */
- pwc_ldo_output_voltage_set(PWC_LDO_OUTPUT_1V3); /* 设置ldo输出电压为1.3V */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE); /* 使能HEXT时钟源 */
- while(crm_hext_stable_wait() == ERROR) /* 等待HEXT时钟稳定 */
- {
- }
- crm_pll_config(CRM_PLL_SOURCE_HEXT, 108, 1, CRM_PLL_FP_4); /* 配置PLL,PLL时钟源选择HEXT,倍频参数PLL_MS = 1,PLL_NS = 108,PLL_FP = 4分频,公式:PLLCLK = 8 / 1 * 108 / 4 = 216 MHz */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE); /* 使能PLL */
- while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET) /* 等待PLL稳定 */
- {
- }
- crm_ahb_div_set(CRM_AHB_DIV_1); /* SCLK 1分频作为AHB总线时钟 */
- crm_apb2_div_set(CRM_APB2_DIV_1); /* AHBCLK 1分频作为APB2总线时钟 */
- crm_apb1_div_set(CRM_APB1_DIV_2); /* AHBCLK 2分频作为APB1总线时钟 */
- crm_auto_step_mode_enable(TRUE); /* 因PLLCLK 216 MHz 大于108 MHz,开启时钟切换顺滑模式 */
- crm_sysclk_switch(CRM_SCLK_PLL); /* 切换系统时钟到PLL */
- while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL) /* 等待系统时钟切换状态为PLL */
- {
- }
- crm_auto_step_mode_enable(FALSE); /* 切换完成,关闭时钟切换顺滑模式 */
- system_core_clock_update(); /* 更新系统核心频率值 */
- }
复制代码 4 4.时钟工具时钟配置工具是雅特力科技为方便对AT32系列MCU进行时钟配置而开发的一个图形化配置工具,其主旨是使用户清晰了解时钟路径和配置出期望的时钟频率并生成源码文件。
4.1 4.1环境要求n 软件要求
需要Windows7及以上操作系统支持。
4.2 4.2安装n 软件安装
本软件不需要安装,只需直接运行可执行程序AT32_New_Clock_Configuration.exe。
4.3 功能介绍本章节将介绍此工具的基本操作,其主要的启动界面和配置界面如下所示
4.4 4.4 菜单栏菜单栏内容如图所示:
n “项目”(Project)菜单:
新建:
| 新建时钟配置项目
| 打开:
| 打开已存在的配置项目
| 保存:
| 保存已打开的配置项目
| n “语言”(Language)菜单:
English:
| 选择English作为显示语言
| 简体中文:
| 选择简体中文作为显示语言
| n “生成代码”(General code)菜单:
当在对应型号的操作配置界面将所期望的时钟路径和时钟频率配置完成之后,可点击“生成代码”菜单来选择源码文件的存储路径并生成相应的源码文件。
n “帮助”(Help)菜单:
新版本下载:
| 联网进行新版本下载
| 版本:
| 查看当前版本
| 4.5 4.5 新建配置项目双击打开时钟配置工具,可看到图示的启动界面,可点击“项目”菜单-->“新建”,进行配置项目的新建,在新建配置项目的过程中需要对芯片的系列所属进行选择,操作方法如下图所示
MCU系列的选择,可点击下拉框来进行选择,当选择好MCU后点击“确定”可进入到时钟配置界面。 4.6 4.6 配置界面的使用配置界面主要用来进行时钟路径及参数的配置,以下的介绍将以AT32F425系列作为示例来展开进行,其余系列的配置方法与此类似。
整个配置界面主要可以分为四个大块,如下图所示
1. 1.标题部分:用于展示当前配置项目所选择的MCU系列。
2. 2.配置部分:用于对时钟路径和时钟参数进行选择和配置,以达到期望的应用需求。
3. 3.输出部分:用于时钟输出(CLKOUT)的配置。
4. 4.在SCLK栏也可在选中PLL为系统时钟时作为输入框,可输入期望的系统时钟频率来反向自动配置出倍频参数。
5. 5. 结果部分:用于显示当前外设所使用的时钟频率及总线上的外设。
6. 6. 时钟源配置部分:用于对拥有独立时钟源的外设进行时钟源的设置。
接下来就着重介绍一下配置部分的使用。配置部分的流程界面是对应着MCU时钟树来进行的,各系列MCU的此部分可能存在着差异,但使用方式大同小异。时钟路径的配置可按流程对各开关进行点选来进行选择,配置部分如下图所示,将逐个流程点的功能及其注意事项进行介绍。
1. ertc使能:ertc时钟代码配置的使能下拉框。 2. ertcsel:点选框,ertc时钟源选择。当ertc使能开启后,此点选框可配置。 3. lext bypass:外部低速时钟的旁路使能。 4. hext:此为输入框,8 MHz为所采用外部时钟源的默认频率,用户可根据实际使用的外部时钟源频率进行修改。(注:此8 MHz被修改为其他频率值时,对应的BSP中demo目录下的inc/at32f402_405_conf.h文件内的HEXT_VALUE宏定义也应该一致修改,也可以采用工具生成的at32f402_405_conf.h文件来进行使用)。 5. hext bypass:高速外部时钟的旁路使能。 6. pllrcs:点选框,可配置PLL时钟源为HEXT或HICK。 7. pll_ms:输入框,PLL预分频系数,范围值1~15。其功能是对PLL输入时钟进行预分频。 8. pll_ns:输入框,PLL倍频参数,范围值31~500。其功能是对PLL_MS进行预分频处理后的时钟进行倍频。 9. pll_fp:下拉框,PLLP后分频系数,范围(1、2、4、6、8、10、12、14、16、18、20、22、24、26、28、30)。其功能是对PLL_NS倍频后的时钟进行后除频,除频后的时钟才是PLLP时钟。 10. sclk select:点选框,可配置HEXT、PLL或HICK作为系统时钟。 11. hextdiv:下拉框,可配置当HEXT选为系统时钟时的分频系数。 12. hickdiv:下拉框,可配置当HICK选为系统时钟时的分频系数。 13. sclk频率:当采用正向配置时,此作为系统时钟频率的配置结果显示,当将其用作输入框时,输入期望的频率后点击回车键,会根据此输入值反向计算一组合适的或最接近期望值的PLL配置参数。 14. hick to sclk:点选框,当sclk select选择HICK作为系统时钟时,可配置HICK的8 MHz或48MHz到系统时钟(注:当选择48 MHz HICK到系统时钟后,CLKOUT输出HICK时的频率也为48 MHz)。 15. pll_fu:下拉框。当PLL时钟被选作为USB的时钟来源时,PLLU后分频系数,范围(11、12、13、14、16、18、20)。其功能是对PLL_NS倍频后的时钟进行后除频,除频后的时钟才是PLLU时钟。。 16. USB使能:USB时钟代码配置的使能下拉框。 17. USB时钟频率的显示。此显示栏会实时计算USB时钟的频率并显示,如果配置出来的USB时钟不等于48 MHz时,显示出来的USB时钟频率会标注为红色,而实际应用中没有用到USB时选择disable则不会显示。(注:此部分只针对USB时钟频率的配置,USB外设时钟使能需自行额外打开)
4.7 生成代码当时钟配置完成后,可点击生成代码,然后选择代码生成的路径并确认,最后会在所选目录下生成两个文件夹inc和src,源文件存放在src文件夹下,头文件存放在inc文件夹下。这些文件可结合到BSP_V2.x.x内的工程来进行使用。可以采用新生成的时钟代码文件(at32f4xx_clock.c/ at32f4xx_clock.h/ at32f4xx_conf.h)将原BSP demo中的对应文件替换,在main函数中进行system_clock_config函数调用即可。 5 5.注意事项5.1 外部时钟源(HEXT)修改因本文档所示例的demo和配置工具都默认采用的8 MHz外部时钟频率,当实际硬件使用的外部时钟源是非8 MHz频率时需注意以下几点。
u 代码修改
1、 1.以实际的外部时钟频率按文中时钟配置流程章节所描述的时钟配置流程及方法来编写相应的代码,配置出期望的时钟配置及时钟路径。
2、 2.修改对应demo工程中at32f4xx_conf.h文件的HEXT_VALUE值,以实际使用的外部时钟源频率值来进行修改。如实际外部高速时钟使用12.288 MHz的晶振或时钟源时,at32f4xx_conf.h文件应修改如下:
- #if !defined HEXT_VALUE
- #define HEXT_VALUE ((uint32_t)12288000)
- #endif
复制代码u 工具修改 1、 在时钟配置工具中的HEXT输入框内填入外部时钟源实际频率值并按“Enter”键确认。 2、 配置好所需的时钟路径及时钟频率,生成代码。采用新生成的时钟代码文件(at32f4xx_clock.c/ at32f4xx_clock.h/at32f4xx_conf.h)将原BSP demo中的对应文件替换或取其中函数内容进行替换,在main函数中进行system_clock_config函数调用即可。
55.2 工具使用在使用本时钟配置工具时需注意:
1. 1. 此工具生成的时钟配置源码文件需结合雅特力科技提供的BSP_V2.x.x进行使用。
2. 2. 不同系列所生成的时钟配置源码文件不能型号混用,只能在相对应的工程项目中进行调用。
3. 3. 配置工具中各输入框参数修改后,请以“Enter”键结束。
6 6. 案例 系统时钟切换6.6.1 功能简介在系统运行过程中来进行系统时钟切换。
6.2 6.2 资源准备1) 1) 硬件环境: 对应产品型号的AT-START BOARD
2) 2) 软件环境 project\at_start_f405\examples\crm\sysclk_switch
6.3 6.3 软件设计1) 配置流程 n 初始化按键。 n 配置clkout时钟输出pll 4分频。 n 编写从hick经pll倍频64 MHz到系统时钟的配置代码。 n 编写从hext经pll倍频96 MHz到系统时钟的配置代码。 2) 代码介绍 main函数代码描述
- int main(void)
- {
- system_clock_config(); /* 系统时钟配置,默认216 MHz */
- at32_board_init(); /* 初始化按键和led */
- clkout_config(); /* clkout配置输出sysclk 4分频 */
- while(1)
- {
- if(at32_button_press() == USER_BUTTON) /* 检测是否按键按下 */
- {
- switch_system_clock(); /* 64与96 MHz系统时钟交替切换 */
- at32_led_toggle(LED4); /* 切换一次,led4 toggle一次 */
- }
- at32_led_toggle(LED2); /* led2 作为运行状态指示灯 */
- delay_ms(100); /* 延时100 ms */
- }
- }
复制代码
hick经pll倍频64 MHz到系统时钟的代码描述 - static void sclk_64m_hick_config(void)
- {
- crm_reset(); /* CRM 复位 */
- flash_psr_set(FLASH_WAIT_CYCLE_1); /* 设置flash 等待周期1 cycle */
- crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE); /* PWC外设时钟使能 */
- pwc_ldo_output_voltage_set(PWC_LDO_OUTPUT_1V0); /* 主频64MHz,LDO可设置1.0V */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE); /* 使能HICK时钟源 */
- while(crm_flag_get(CRM_HICK_STABLE_FLAG) != SET) /* 等待HICK稳定标志置起 */
- {
- }
- crm_pll_config(CRM_PLL_SOURCE_HICK, 64, 1, CRM_PLL_FP_8); /* 配置PLL,PLL时钟源选择HICK,倍频参数PLL_MS = 1,PLL_NS = 64,PLL_FP = 8分频,公式:PLLCLK = 8 / 1 * 64 / 8 = 64 MHz */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE); /* 使能PLL */
- while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET) /* 等待PLL稳定 */
- {
- }
- crm_ahb_div_set(CRM_AHB_DIV_1); /* SCLK 1分频作为AHB总线时钟 */
- crm_apb2_div_set(CRM_APB2_DIV_1); /* AHBCLK 1分频作为APB2总线时钟 */
- crm_apb1_div_set(CRM_APB1_DIV_1); /* AHBCLK 1分频作为APB1总线时钟 */
- //crm_auto_step_mode_enable(TRUE); /* 开启时钟切换顺滑模式,因PLLCLK 64 MHz 小于108 MHz可不开启 */
- crm_sysclk_switch(CRM_SCLK_PLL); /* 切换系统时钟到PLL */
- while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL) /* 等待系统时钟切换状态为PLL */
- {
- }
- //crm_auto_step_mode_enable(FALSE); /* 关闭时钟切换顺滑模式 */
- system_core_clock_update(); /* 更新系统核心频率值 */
- delay_init(); /* 因系统时钟频率切换,重新初始化delay */
- clkout_config(); /* 因crm复位,重新配置clkout */
- }
复制代码hext经pll倍频96 MHz到系统时钟的代码描述 - static void sclk_96m_hext_config(void)
- {
- crm_reset(); /* CRM 复位 */
- flash_psr_set(FLASH_WAIT_CYCLE_2); /* 设置flash 等待周期2 cycle */
- crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE); /* PWC外设时钟使能 */
- pwc_ldo_output_voltage_set(PWC_LDO_OUTPUT_1V0); /* 主频96MHz,LDO可设置1.0V */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE); /* 使能HEXT时钟源 */
- while(crm_hext_stable_wait() == ERROR) /* 等待HEXT时钟稳定 */
- {
- }
- crm_pll_config(CRM_PLL_SOURCE_HEXT, 96, 1, CRM_PLL_FP_8); /* 配置PLL,PLL时钟源选择HEXT,倍频参数PLL_MS = 1,PLL_NS = 96,PLL_FP = 8分频,公式:PLLCLK = 8 / 1 * 96 / 8 = 96 MHz */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE); /* 使能PLL */
- while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET) /* 等待PLL稳定 */
- {
- }
- crm_ahb_div_set(CRM_AHB_DIV_1); /* SCLK 1分频作为AHB总线时钟 */
- crm_apb2_div_set(CRM_APB2_DIV_1); /* AHBCLK 1分频作为APB2总线时钟 */
- crm_apb1_div_set(CRM_APB1_DIV_1); /* AHBCLK 1分频作为APB1总线时钟 */
- //crm_auto_step_mode_enable(TRUE); /* 开启时钟切换顺滑模式,因PLLCLK 96 MHz 小于108 MHz可不开启 */
- crm_sysclk_switch(CRM_SCLK_PLL); /* 切换系统时钟到PLL */
- while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL) /* 等待系统时钟切换状态为PLL */
- {
- }
- //crm_auto_step_mode_enable(FALSE); /* 关闭时钟切换顺滑模式 */
- system_core_clock_update(); /* 更新系统核心频率值 */
- delay_init(); /* 因系统时钟频率切换,重新初始化delay */
- clkout_config(); /* 因crm复位,重新配置clkout */
- }
复制代码 6.4 实验效果n 上电运行led2以间隔100ms时间进行闪烁,clkout(PA8)输出24 MHz。
n 每次USER按键按下,系统时钟在64 MHz与96 MHz之间进行交替切换,clkout输出对应的4分频频率,led4 toggle一次。
7 案例 时钟失效检测7.1 功能简介在当HEXT 时钟直接或间接作为系统时钟时,当HEXT 时钟出现故障,且时钟失效模块侦测到失效后,时钟失效事件将产生NMI 中断,在此中断中可完成系统的营救操作。 7.2 资源准备1) 硬件环境: 对应产品型号的AT-START BOARD 2) 软件环境 project\at_start_f405\examples\crm\clock_failure_detection 7.3 软件设计1) 配置流程 n 配置clkout时钟输出sysclk 4分频。 n 开启时钟失效检测,并完善void NMI_Handler(void)函数。 n 编写从hick经pll倍频216 MHz到系统时钟的配置代码。 2) 代码介绍
main函数代码描述 - int main(void)
- {
- system_clock_config(); /* 配置系统时钟 */
- at32_board_init(); /* 初始化led和delay函数 */
- clkout_config(); /* 配置clkout输出pll 4分频 */
- crm_clock_failure_detection_enable(TRUE); /* 开启时钟失效检测 */
- while(1)
- {
- at32_led_toggle(LED2); /* led2作为运行状态指示灯 */
- delay_ms(200); /* 延时200 ms */
- }
- }
复制代码hick经pll倍频216MHz到系统时钟的代码描述
- static void sclk_216m_hick_config(void)
- {
- crm_reset(); /* CRM 复位 */
- flash_psr_set(FLASH_WAIT_CYCLE_6); /* 设置flash 等待周期6 cycle */
- crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE); /* PWC外设时钟使能 */
- pwc_ldo_output_voltage_set(PWC_LDO_OUTPUT_1V3); /* 主频216MHz,LDO需设置1.3V */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE); /* 使能HICK时钟源 */
- while(crm_flag_get(CRM_HICK_STABLE_FLAG) != SET) /* 等待HICK稳定标志置起 */
- {
- }
- crm_pll_config(CRM_PLL_SOURCE_HICK, 108, 1, CRM_PLL_FP_4); /* 配置PLL,PLL时钟源选择HICK,倍频参数PLL_MS = 1,PLL_NS = 108,PLL_FP = 4分频,公式:PLLCLK = 8 / 1 * 108 / 4 = 216 MHz */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE); /* 使能PLL */
- while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET) /* 等待PLL稳定 */
- {
- }
- crm_ahb_div_set(CRM_AHB_DIV_1); /* SCLK 1分频作为AHB总线时钟 */
- crm_apb2_div_set(CRM_APB2_DIV_1); /* AHBCLK 1分频作为APB2总线时钟 */
- crm_apb1_div_set(CRM_APB1_DIV_2); /* AHBCLK 2分频作为APB1总线时钟 */
- crm_auto_step_mode_enable(TRUE); /* 开启时钟切换顺滑模式 */
- crm_sysclk_switch(CRM_SCLK_PLL); /* 切换系统时钟到PLL */
- while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL) /* 等待系统时钟切换状态为PLL */
- {
- }
- crm_auto_step_mode_enable(FALSE); /* 关闭时钟切换顺滑模式 */
- system_core_clock_update(); /* 更新系统核心频率值 */
- delay_init(); /* 因系统时钟频率切换,重新初始化delay */
- clkout_config(); /* 因crm复位,重新配置clkout */
- }
复制代码NMI中断实现 - void NMI_Handler(void)
- {
- clock_failure_detection_handler();
- }
- void clock_failure_detection_handler(void)
- {
- if(crm_flag_get(CRM_CLOCK_FAILURE_INT_FLAG) != RESET) /* 判断时钟失效标志 */
- {
- crm_clock_failure_detection_enable(FALSE); /* 关闭时钟失效检测 */
- sclk_216m_hick_config(); /* 系统时钟拯救,由hick倍频到216MHz */
- crm_flag_clear(CRM_CLOCK_FAILURE_INT_FLAG); /* 清除时钟失效标志 */
- }
- }
复制代码
7.4 实验效果n 在运行过程中将晶振拔掉或晶振脚接地,产生时钟失效。通常来说hext比hick更稳定,可观测clkout(PA8)的输出,可发现时钟拯救回来后hick作为源时的频率上存在细微波动。 8 案例 PLL参数计算8.1 功能简介在进行系统时钟配置过程时,可调用库函数根据PLL输入时钟源和目标时钟频率自动计算一组合理的PLL参数以供配置,减少人为计算的烦恼。 8.2 资源准备1) 硬件环境: 对应产品型号的AT-START BOARD 2) 软件环境 project\at_start_f405\examples\crm\pll_parameter_calculate 8.3 软件设计1) 配置流程 n 以crm_pll_parameter_calculate函数自动计算PLL参数方式配置系统时钟。 n 配置clkout时钟输出sysclk 4分频。 n 判断计算结果,能以目标时钟准确计算一组PLL参数时LED4闪烁,如果不能LED2闪烁。 2) 代码介绍
main函数代码描述 - int main(void)
- {
- system_clock_config_216mhz(); /* 以自动计算的方式进行时钟配置 */
- at32_board_init(); /* 初始化led和delay函数 */
- clkout_config(); /* 配置clkout输出sysclk 4分频 */
- while(1)
- {
- if(calculate_status == ERROR) /* 判断计算状态 */
- {
- at32_led_toggle(LED2); /* led2闪烁 */
- }
- else
- {
- at32_led_toggle(LED4); /* led4闪烁 */
- }
- delay_ms(500); /* 延时500 ms */
- }
- }
复制代码自动以目标时钟计算PLL参数并配置系统时钟的代码描述
- void system_clock_config_216mhz(void)
- {
- uint16_t pll_ns, pll_ms, pll_fp;
- crm_reset(); /* CRM 复位 */
- flash_psr_set(FLASH_WAIT_CYCLE_6); /* 设置flash 等待周期6 cycle */
- crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE); /* PWC外设时钟使能 */
- pwc_ldo_output_voltage_set(PWC_LDO_OUTPUT_1V3); /* 主频216MHz,LDO需设置1.3V */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE); /* 使能HEXT时钟源 */
- while(crm_hext_stable_wait() == ERROR) /* 等待HEXT稳定 */
- {
- }
- calculate_status = crm_pll_parameter_calculate(CRM_PLL_SOURCE_HEXT, 216000000, &pll_ms, &pll_ns, &pll_fp); /* 以目标时钟216 MHz计算一组PLL参数 */
- crm_pll_config(CRM_PLL_SOURCE_HEXT, pll_ns, pll_ms, (crm_pll_fp_type)pll_fp); /* 配置PLL */
- crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE); /* 使能PLL */
- while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET) /* 等待PLL稳定 */
- {
- }
- crm_ahb_div_set(CRM_AHB_DIV_1); /* SCLK 1分频作为AHB总线时钟 */
- crm_apb2_div_set(CRM_APB2_DIV_1); /* AHBCLK 1分频作为APB2总线时钟 */
- crm_apb1_div_set(CRM_APB1_DIV_2); /* AHBCLK 2分频作为APB1总线时钟 */
- crm_auto_step_mode_enable(TRUE); /* 开启时钟切换顺滑模式 */
- crm_sysclk_switch(CRM_SCLK_PLL); /* 切换系统时钟到PLL */
- while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL) /* 等待系统时钟切换状态为PLL */
- {
- }
- crm_auto_step_mode_enable(FALSE); /* 关闭时钟切换顺滑模式 */
- system_core_clock_update(); /* 更新系统核心频率值 */
- }
复制代码 8.4 实验效果
n 系统会自动计算一组以目标时钟为结果的PLL参数并配置,如果计算参数所算结果与目标时钟相等则LED4闪烁,如果所算结果与目标时钟接近则LED2闪烁。
|