敏矽微电子Cortex-M0学习笔记03——时钟系统设计例程

电子说

1.3w人已加入

描述

1.1. ME32F030R8T6的时钟树

时钟是MCU运行的基础,时钟信号推动单片机内各个部分执行相应的指令。时钟系统就是CPU的脉搏,决定cpu速率,像人的心跳一样 只有有了心跳,人才能做其他的事情,而MCU有了时钟,才能够运行执行指令,才能够做准确、稳定的进行一系列的操作 (例如:串口通信、PWM信号、ADC采样等等),因此时钟的重要性不言而喻。

ME32F030系列 具有非常灵活的时钟控制系统。用户可根据不同应用需求来配置时钟,从而取得最高的性能及优化的能耗管理。下图为 ME32F030R8T6 的时钟系统概要图:

时钟树

从图中可以看出,MCU的时钟源有内部高速的IRC_OSC 和 低速的 WDT_OSC 时钟可供选择。

IRC_OSC:它属于高速时钟,可以由内部晶体振荡器控制寄存器(IRCCTRL)配置为 40/48MHz的主频, 缺省值是40MHz 频率,由工厂出厂预设并由引导程序写入。一般作为系统主时钟的时钟源。

WDT_OSC:它属于低速时钟,由看门狗振荡器控制寄存器控制。振荡器包含模拟和数字两部分。振荡器的模拟部分用于产生模拟时钟(Fclkana)。在振荡器数字部分,模拟时钟(Fclkana)输出一个32KHz 频率时钟。然后再被DIVSEL 控制的分频器分频输出到 WDT_CLK,作为看门狗时钟源。

看门狗振荡器输出频率可用下列公式推算:

WDT_CLK = Fclkana/(4 ×DIVSEL) = 8K Hz ~ 250 Hz (标称值)

1.2. ME32F030R8T6时钟源的应用控制

介绍完系统的时钟源,接下来说说时钟源主要运用到了哪些方面。

ME32F030R8T6的外设非常多,但我们实际使用的时候只会用到有限的几个外设,使用任何外设都需要时钟才能启动,但并不是所有的外设都需要系统时钟那么高的频率,为了兼容不同速度的设备,有些高速,有些低速,如果都用高速时钟,势必造成浪费。并且,同一个电路,时钟越快功耗越快,同时抗电磁干扰能力也就越弱,所以较为复杂的MCU都是采用多时钟源的方法来解决这些问题。

WDT_CLK:由看门狗振荡器控制寄存器来选择输入时钟,作为看门狗的工作时钟。

时钟树

MAIN_CLK:由MAINCLK_SEL选择输入时钟源,上电默认选择IRC_OSC_CLK作为时钟源,也可以通过置位来选择WDT_OSC_CLK。

时钟树

SYSTEM_CLK:由MAINCLK通过AHB 接口时钟分频器寄存器(SYSAHBCLKDIV)分频而来,默认不分频。SYSTEM_CLK时钟供内核、外设和存储器使用。其中外设通过 AHB 接口时钟控制寄存器(SYSAHBCLKCTRL)来控制外设的时钟使能,上电默认外设的时钟都是打开的。

时钟树

UART:UART0/1有自己独立的时钟分频器从MAIN_CLK分频后取得UART时钟。

时钟树

CLK_OUT:MCU的内部晶振器(IRC_OSC_CLK)、看门狗振荡器(WDT_OSC_CLK),主时钟(MAIN_CLK),系统时钟(SYSTEM_CLK)都可以通过CLK_OUT作为输出时钟。

使用前需要通过 CLKOUT 输出时钟源选择寄存器 (CLKOUTCLKSEL)来确定想要输出的时钟源,再经过 CLKOUT 输出时钟分频器寄存器 (CLKOUTDIV)分频后输出,该寄存器初始值默认为0,即不输出时钟。需要输出的话,设置好分频系数(1-255)便可以输出了。

时钟树

时钟树

2、ME32F030R8T6的时钟系统函数简介

为了便于开发者快速上手,敏矽微电子为开发者提供了丰富的库函数和开发例程。

借助于库函数,可以不用像普通单片机那样去配置繁多的寄存器,从而加快开发进程。

借助于例程中,可以更深入理解寄存器配置及功能实现。

本例中,我们就借助于敏矽微电子提供的例程来简单介绍它的时钟系统的跨函数。在sys.c文件中,包含了切换系统时钟,配置时钟主频等函数,供开发者直接使用。

1.3. 主频配置函数

①、配置IRC_CLK为40M主频

 

void SYS_IRCTrimto40M(void){volatile uint32_t i=0xFFFF;if (DIA->IRCTRIM!=0xFFFFFFFF)

{

SYSCON->IRCCTRL=DIA->IRCTRIM;  while(i--==0);

FMC->FLASH_RDCYC =1;

SYSCON->SYSAHBCLKDIV =1;

SystemCoreClockUpdate ();

}return ;

}

 

②、配置IRC_CLK为48M主频

 

void SYS_IRCTrimto48M(void){volatile uint32_t i=0xFFFF;if (DIA->IRCTRIM48!=0xFFFFFFFF)

{

SYSCON->IRCCTRL=DIA->IRCTRIM48;while(i--==0);

FMC->FLASH_RDCYC =1;


SYSCON->SYSAHBCLKDIV =1; //core clock to 48M

SystemCoreClockUpdate ();

}

return ;

}

 

1.4. 时钟源选择函数

③、选择MAIN_CLK的时钟源,可以选择IRC_CLK 或者 WATCHDOG_CLK。

 

void SYS_SelectMainClkSrc(uint8_t src)


{

 //switch main clk source

 SYSCON->MAINCLKUEN_b.ENA= 1; //disable main clk update

 //switch main clk source to Specifyed source

 if (src==IRC_CLK)
 
 SYSCON->MAINCLKSEL_b.SEL=0;else if (src==WATCHDOG_CLK)

  SYSCON->MAINCLKSEL_b.SEL=2;

 
  SYSCON->MAINCLKUEN_b.ENA=0; //enable main clk update

 SystemCoreClockUpdate ();

 return;

}

 

④、设置AHB 接口时钟分频器的分频系数,在这里请注意,函数如果检查到当前时钟为IR_CLK且分频系数小于2,这样系统时钟SYSTEM_CLK的主频肯定大于30M, 而FLASH的擦写速度最高支持到30MHz。此时CPU时钟超过Flash的最大读取速度,这就需要插入延迟时钟,延迟时钟由 RDCYC 寄存器控制。

 

void SYS_SetAHBClkDivider (uint8_t div)

{

 //setup flash access speed if SystemCoreClock is going tomore than 30MHz 

 if ((SYSCON->MAINCLKSEL_b.SEL==0)  (div<2))  

 FMC->FLASH_RDCYC = 1;                
  
  SYSCON->SYSAHBCLKDIV_b.DIV = div;  //setup ahb clock divider

 SystemCoreClockUpdate ();   //update MainClock and SystemCoreClock

 return;
}

 

//⑤、设置WDT_CLK的时钟源,可以选择IRC_CLK 或者 WATCHDOG_CLK。

 

    void SYS_SelectWDTClkSrc(uint8_t src){if (src==IRC_CLK)



    SYSCON->WDTOSCCTRL_b.WDTCLKSRC = 0;

    else if (src==WATCHDOG_CLK)

    SYSCON->WDTOSCCTRL_b.WDTCLKSRC = 1;

 return;

}

 

//⑥、设置CLK_OUT的时钟源,可以选择IRC_CLK 、SYS_CLK、 WATCHDOG_CLK、MAIN_CLK中的一个。

 

void SYS_SelectClkOutSrc(uint8_t src)

{switch (src)


{

case IRC_CLK:

src=0;break;case SYS_CLK:

src=1;break;case WATCHDOG_CLK:

src=2;break;case MAIN_CLK:

src=3;break;

 default:return;

    }

    //switch clock

    SYSCON->CLKOUTUEN_b.ENA = 1;

    SYSCON->CLKOUTCLKSEL_b.SEL = src; //select clk out source

    SYSCON->CLKOUTUEN_b.ENA = 0;

     return;

}

 

//⑦、设置CLK_OUT时钟的输出分频系数。

 

void SYS_SetClkOutDivider(uint8_t div)

{

SYSCON->CLKOUTDIV_b.DIV = div;

return;}

 

3、ME32F030R8T6时钟系统例程

上面介绍了sys.c中关于系统时钟的部分函数,下面我们来编写一个关于时钟配置的例程。使大家能够对时钟配置有一个简单的了解。

本例实现的功能是:将AHB 接口时钟进行2分频,IRC时钟切换到48M主频,最后将系统时钟进行分频输出。

 

int main(void)

{

 SYS_SetAHBClkDivider (2);     // AHB 接口时钟进行2分频

 SYS_IRCTrimto48M(); // IRC时钟切换到48M主频

 SYS_SelectClkOutSrc(SYS_CLK); // 选择SYS_CLK作为OUT_CLK输出时钟 

 SYS_SetClkOutDivider(10); // 对OUT_CLK时钟进行10分频

 SYS_EnableClkOut(); // 使能OUT_CLK输出端口

}

 

来源:敏矽MCU

  审核编辑:汤梓红
 
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分