专栏首页TencentOS-tinyMSP430F5529时钟系统深究

MSP430F5529时钟系统深究

1、为什么要进行时钟管理?

时钟系统是一个数字器件的命脉,对于普通的51单片机来说,它的时钟来源只有外部晶振,然后每12个振荡周期完成一个基本操作,所以也叫做12T单片机,但对于当前高级一点的单片机来说,比如MSP430F5529有5个时钟来源,经过UCS(Unified Clock System,通用时钟系统)模块之后,产生MCLK(Master Clock),SMCLK(Subsystem master clock ),ACLK(Auxiliary clock)三个时钟;对于更高端的单片机,比STM32F103ZET6里面有专门用来管理时钟的RCC单元(Reset Clock Control),也就是通常所说的时钟树,在时钟管理上更加强大!

  首先来看两个例子:

  1) MSP430F5529单片机的时钟设计:

  该单片机中通过UCS单元产生三路信号,MCLK供CPU使用,SMCLK供高速外设使用,ACLK供低速外设使用,这样设计后,每个外设都具有自己的时钟源,可以独立工作,不需要的时候可以空闲的时钟源关闭,进入低功耗模式,根据时钟不同程度上的关闭,分为7种低功耗模式;

  2) STM32F103ZET6单片机的时钟设计

  该单片机中通过RCC单元产生SYSCLK,HCLK,PCLK2,PCLK1四路时钟,独立工作,并且默认情况下所有外设时钟都处于关闭状态,即使要使用一个IO口输出,也需要先使能相应GPIO时钟,可见STM32的时钟管理单元更加精妙;

  通过这两个例子,可以看出时钟管理这个单元往往被开发者所忽略是因为一般情况下单片机设计者已经为我们设置好了最优的时钟状态,系统工作都采用默认时钟,我们利用这个默认设置可以完成大部分项目,但是在一些必须要求低功耗的场合,比如智能手环,智能仪表,性能需求不是很高,但是必须要求低功耗,那么如何实现低功耗呢有两种途径,一是关闭没有用到的外设的时钟,停止工作;二是降低系统CPU工作频率。这两种途径都是通过操作单片机的时钟管理单元实现的,所以掌握时钟的管理尤其重要!

2、器材资料准备

在这里我们深入探究一下MSP430F5529的UCS单元

实验平台:MSP430F55529launchpad开发板

实验仪器:示波器或者逻辑分析仪

参考资料:MSP430F55529launchpad开发板原理图《MSP-EXP430F5529LP_Schematic》以及MSP430F5529的官方参考手册《MSP430x5xx and MSP430x6xx Family User's Guide》

3、统一时钟系统(Unified Clock System,UCS) 

  1)功能简图

  2)由图中可以看到时钟来源一共有5个:

XT1CLK - 外部低频率或高频率振荡源,32.768Khz(LF模式)或4-32Mhz(HF模式); VLOCLK - 内部超低功耗振荡源,典型值10Khz; REFOCLK - 内部低频参考源,典型值32.768Khz; DCOCLK - 内部数字时钟振荡器,由FLL稳定后得到; XT2CLK - 外部高频振荡源4-32Mhz;   注:DCOCLK是通过内部FLL单元稳定而来,并不算是一个通过振荡产生时钟的源,所以在图中未标注;

  3)这5个时钟源经过UCS单元后,产生3个时钟信号,这三个时钟的时钟源可由软件控制从XT1,REFO,VLO,DCO,DCOCLK,XT2中选择,其中DCOCLKDIV经由DCO1/2/4/8/16/32分频得到;另外ACLK也可以被再次1/2/4/8/16/32分频;

MCLK -- CPU使用; SMCLK -- 高速外设使用; ACLK -- 低速外设使用;   4)单独的MOSOSC模块,产生5Mhz的MDOCLK时钟信号,只为FLASH控制模块和ADC12模块提供时钟,该模块不使用时自动关闭,使用时无需使能即可响应请求,为外设提供时钟;

  5)具体的时钟框图如下(图片来源于官方参考手册):

4、实验验证

了解了UCS单元的基本功能后,接下来开始实验:

首先查看开发板原理图,搞清楚硬件连接,可以看到,单片机在XIN(P5.4)和XOUT(P5.5)引脚接了一个32.768K的手表晶振,在XT2IN(P5.2)和XT2OUT(P5.3)处接了一个4M的有源晶振;

1)复位后的时钟情况

  系统上电复位后,XT1在LF低频模式,作为XT1CLK的时钟来源,XT1CLK又被选中作为ACLK的时钟源;当XT1无效时,低频模式自动切换为REFO,其它情况切换为DCO;

  FLL使能,FLL的参考时钟源FLLREFCLK选中XT1CLK,当XT1无效时,低频模式自动切换为REFO,经过锁频环FLL稳定倍频,分频,稳定频率之后,产生DCOCLK和DCOCLKDIV;

  这个时候要注意最关键的,如果连接XT1和XT2的引脚不进行PXSEL的设置,那么这两个时钟源都是无效的,而内部时钟REFOCLK,VLOCLK,DCOCLK默认都是可用的;并且在单片机复位之后,XT2OFFG,XT1HFOFFG清零,没有故障失效,XT1LFOFFG,DCOCLK置位,产生故障失效,而且在刚打开时钟的时候,这些故障位都会置位,一旦被置位,即使晶振恢复到正常状态也将一直保持置位,直到手动用软件将故障失效标志位清零,清零之后,若晶振故障失效情况仍然存在,晶振故障失效标志位将自动再次被置位;

  所以,单片机默认情况下虽然全被配置为XT1CLK,但是因为XT1引脚未配置,并且故障位置位,所以自动切换使用REFO,即:

ACLK=REFOCLK = 32.768Khz;

  FLLREFCLK = REFOCLK = 32.768K;

  MCLK = SMCLK = DCOCLKDIV =1.048576MHZ;

  DCOCLK = 2.097152Mhz;

接下来将时钟信号输出到示波器上验证一下,MCLK输出复用P7.7脚,SMCLK输出复用P2.2脚,ACLK复用P1.0脚,实验板上只引出P1.0和P2.2,所以我们只测试ACLK和SMCLK,可以看到ACLK = 32.86khz,SMCLK = MCLK = 1.05Mhz,LED闪烁频率大约为1hz;

 #include <msp430.h>
  int main(void)
  {
    volatile unsigned int i;    //循环变量
    WDTCTL = WDTPW | WDTHOLD;    // stop watchdog timer
    P4DIR |= (BIT1+BIT7);       //P4.7观察现象,P4.1用于示波器观测
    P4OUT |= (BIT1+BIT7);       //输出高电平,点亮LED
    P1DIR |= BIT0;
    P1SEL |= BIT0;              //P1.0输出ACLK
    P2DIR |= BIT2;
    P2SEL |= BIT2;              //P2.2输出SMCLK
    while(1)
    {
        P4OUT ^= (BIT1+BIT7);   //LED状态取反
         for(i = 50000;i>0;i--); //delay
    }
 }

2)配置内部时钟源

  编程思路:内部钟源默认都可用,所以直接修改UCSCTL4寄存器配置即可;

1、修改时钟源,将ACLK配置为VLOCLK内部超低功耗振荡器,可以看到,ACLK = VCOCLK = 9.21Khz

加入这行代码:

UCSCTL4 |= SELA_1;          //配置ACLK = VCOCLK

2、修改时钟源,配置ACLK为REFOCLK,内置调整低频参考振荡器,可以看到,ACLK = REFOCLK = 32.86Khz

UCSCTL4 |= SELA_2;          //配置ACLK = REFOCLK

3、修改时钟源,配置ACLK为DCOCLK,可以看到,ACLK = DCOCLK = 2.11Mhz

UCSCTL4 |= SELA_3;          //配置ACLK = DCOCLK

4、修改时钟源,配置ACLK为DCOCLKDIV,可以看到,ACLK = DCOCLKDIV = 1.06Mhz

UCSCTL4 |= SELA_4;          //配置ACLK = DCOCLKDIV

3)配置外部时钟源

编程思路:

配置XT1/XT2连接晶振的引脚(PXSEL) 清除XT1,XT2,DCO失效标志位 修改UCSCTL4寄存器,选择时钟源 1、修改时钟源,配置ACLK = 32.768Khz,MCLK = SMCLK = DCOCLKDIV=1.05M;

#include <msp430.h>

int main(void)
{
    volatile unsigned int i;    //循环变量
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    P4DIR |= (BIT1+BIT7);       //P4.7观察现象,P4.1用于示波器观测
    P4OUT |= (BIT1+BIT7);       //输出高电平,点亮LED
    P1DIR |= BIT0;
    P1SEL |= BIT0;              //P1.0输出ACLK
    P2DIR |= BIT2;
    P2SEL |= BIT2;              //P2.2输出SMCLK

    P5SEL   |= BIT4+BIT5;       //P5.4和P5.5选择XT1晶振功能
    UCSCTL3 |= SELREF_0;        //设置FLL参考时钟源为XT1
    do
    {
       UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
                                //清除XT2,XT1,DCO故障失效标志位
       SFRIFG1 &= ~OFIFG;       //清除晶振故障失效中断标志位
    }while(SFRIFG1&OFIFG);      //晶振故障失效中断标志位
    UCSCTL6 &= ~XT1DRIVE_0;     //减少XT1驱动能力
    UCSCTL4 |= SELA_0;          //ACLK = XT1CLK

    while(1)
    {
        P4OUT ^= (BIT1+BIT7);   //LED状态取反
        for(i = 50000;i>0;i--); //delay
    }
}

2、修改时钟源,配置ACLK = MCLK = SMCLK = XT2CLK =4Mhz

#include <msp430.h>

int main(void)
{
    volatile unsigned int i;    //循环变量
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    P4DIR |= (BIT1+BIT7);       //P4.7观察现象,P4.1用于示波器观测
    P4OUT |= (BIT1+BIT7);       //输出高电平,点亮LED
    P1DIR |= BIT0;
    P1SEL |= BIT0;              //P1.0输出ACLK
    P2DIR |= BIT2;
    P2SEL |= BIT2;              //P2.2输出SMCLK

    P5SEL   |= BIT2+BIT3;       //P5.2和P5.3选择XT2晶振功能
    UCSCTL3 |= SELREF_5;        //设置FLL参考时钟源为XT2CLK
    UCSCTL4 |= SELA_5;          //必须要设置这一句配置ACLK = XT2CLK
    do
    {
       UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
                                //清除XT2,XT1,DCO故障失效标志位
       SFRIFG1 &= ~OFIFG;       //清除晶振故障失效中断标志位
    }while(SFRIFG1&OFIFG);      //晶振故障失效中断标志位
    UCSCTL6 &= ~XT2DRIVE_0;     //XT2 = 4M,减少XT2驱动能力
    UCSCTL4 |= SELS_5 + SELM_5; //配置MCLK = SMCLK = XT2CLK

    while(1)
    {
        P4OUT ^= (BIT1+BIT7);   //LED状态取反
        for(i = 50000;i>0;i--); //delay
    }
}

示波器观测结果,可以看到LED闪烁频率也比之前加快4倍:

3、修改时钟源,配置ACLK = 32.768Khz,MCLK = SMCLK = XT1CLK * (499+1) =16Mhz

#include <msp430.h>

int main(void)
{
    volatile unsigned int i;    //循环变量
    WDTCTL = WDTPW | WDTHOLD;   // stop watchdog timer
    P4DIR |= (BIT1+BIT7);       //P4.7观察现象,P4.1用于示波器观测
    P4OUT |= (BIT1+BIT7);       //输出高电平,点亮LED
    P1DIR |= BIT0;
    P1SEL |= BIT0;              //P1.0输出ACLK
    P2DIR |= BIT2;
    P2SEL |= BIT2;              //P2.2输出SMCLK

    P5SEL   |= BIT4+BIT5;       //P5.4和P5.5选择XT1晶振功能
    UCSCTL3 |= SELREF_0;        //设置FLL参考时钟源为XT1
    UCSCTL4 |= SELA_0;          //ACLK = XT1CLK
    UCSCTL0 = 0;                //设置DCO=MOD=0  
    do
    {
       UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
                                //清除XT2,XT1,DCO故障失效标志位
       SFRIFG1 &= ~OFIFG;       //清除晶振故障失效中断标志位
    }while(SFRIFG1&OFIFG);      //晶振故障失效中断标志位
    UCSCTL6 &= ~XT1DRIVE_0;     //减少XT1驱动能力
    __bis_SR_register(SCG0);    //禁止FLL
    UCSCTL1 = DCORSEL_4;        //选择DCO频率范围
    UCSCTL2 |= 499;             //设置频率16Mhz
    __bic_SR_register(SCG0);    //启用FLL
    for(i = 50000;i>0;i--);     //delay,等待FLL稳定

    while(1)
    {
        P4OUT ^= (BIT1+BIT7);   //LED状态取反
        for(i = 50000;i>0;i--); //delay
    }
}

示波器测试结果

本文分享自微信公众号 - Mculover666(Mculover666),作者:Mculover666

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-06-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 盘点嵌入式那些常见的GUI:emWin、TouchGFX、MiniGUI、Qt等

    现在,MCU资源增多,处理能力也强了,同时市场需求也增多了,GUI功能也越来越丰富了。

    Mculover666
  • 【编译器玄学研究报告】第二期——break

    编译器玄学报告第一期出来后,并没有任何人理睬我在文章一开头留下的问题,相反大部分人都是来围观“闰年更新”的

    Mculover666
  • 第6期 | MultiTimer,一款可无限扩展的软件定时器

    本专栏由Mculover666创建,主要内容为寻找嵌入式领域内的优质开源项目,一是帮助开发者使用开源项目实现更多的功能,二是通过这些开源项目,学习大佬的代码及背...

    Mculover666
  • nRF52832——设置内部低频时钟源的方法

    32.768k低频时钟坑的地方太多,很容易受到其他信号的影响,52832 协议栈的低频时钟源自32.768k,时钟源用外部晶体时遇到很多奇葩的问题,经过定位及与...

    Winter_world
  • JavaScript学习笔记

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    村雨遥
  • 混合云管理平台与现代企业不可不说关系

    混合云管理是现代IT运营领域中的一个热点话题。继续阅读本文以了解它是什么,它的工作原理以及它能够为用户的基础设施做些什么。 目前,最大的IT热点之一就是混合云。...

    静一
  • 虚拟币投资者de自我思考

    很多人都说投资虚拟币是投机的行为,这样的评价我是不接受也不认可的,我个人觉得但凡是真金白银投入的事物都可以说是投资,而非一些人口中的投机。

    链圈小姐姐
  • placement new

    JIFF
  • 自定义圆环进度条

    六月的雨
  • 使用Pyspark进行特征工程时的那些坑

    以脚本spark_clean_online_action.py、数据集new_sxf_time_count_1781115582.csv为例: 集群节点包括21...

    Bo_hemian

扫码关注云+社区

领取腾讯云代金券