历史上的今天
返回首页

历史上的今天

今天是:2024年10月10日(星期四)

正在发生

2019年10月10日 | MSP430(F5529)学习笔记——UCS配置详解

2019-10-10 来源:eefocus

MSP430(F5529)相比MSP430(F149)来讲,功能更加强大。


UCS简介

MSP430F5XX/MSP430F6XX系列器件的UCS包含有五种时钟源,依次是:XT1CLK、VLOCLK、REFOCLK、DCOCLK和XT2CLK。这五种时钟的详细介绍请参考该系列芯片的指导手册,其中XT1CLK、VLOCLK、REFOCLK和XT2CLK跟MSP430F1XX系列没有太大区别,学习配置起来也比较简单。


UCS上电默认状态


PUC后,UCS模块的默认状态如下:


(1)XT1处于LF模式作为XT1CLK时钟源。ACLK选通为XT1CLK。

(2)MCLK选通为DCOCLKDIV

(3)SMCLK选通为DCOCLKDIV

(4)FLL使能,且将XT1CLK作为FLL参考时钟。

(5)XIN和XOUT脚设置为通用IO,XIN和XOUT配置为XT1功能前,XT1保持禁用。

(6)如果可用的话,XT2IN和XT2OUT被设置为通用IO且保持禁止状态。


清楚UCS上电默认状态是非常重要的,这对于理解后面的配置逻辑来说非常重要。


UCS时钟源切换


由于REFOCLK、VLOCLK、DCOCLK(这里暂时这么认为)默认状态下是可用的,所以,切换的时候只需要通过UCSCTL4来配置ACLK、SMCLK和MCLK的时钟源即可,而XT1CLK和XT2CLK需要根据硬件的具体配置情况确定,所以,这两者的配置比起前三者来讲,就有些不同了。下面,我们做三个实验:


(1)将MCLK和SMCLK配置REFOCLK、VLOCLK

REFOCLK和VLOCLK是芯片默认提供的,只要芯片正常工作,这两个时钟就会正常工作,因此,该时钟配置非常简单,只需要修改UCSCTL4,将SELS和SELM配置为对应的选项VLOCLK或者REFOCLK即可,具体代码如下:

#include

 

 

void main(void) {

  WDTCTL = WDTPW+WDTHOLD;

  

  P1SEL |= BIT0;

  P1DIR |= BIT0;//测量ACLK用

  P2SEL |= BIT2;

  P2DIR |= BIT2;//测量SMCLK用

  P7SEL |= BIT7;

  P7DIR |= BIT7;//测量MCLK用

 

 

  //UCSCTL4 = UCSCTL4&(~(SELS_7|SELM_7))|SELS_1|SELM_1; //将SMCLK和MCLK配置为VLOCLK

  UCSCTL4 = UCSCTL4&(~(SELS_7|SELM_7))|SELS_2|SELM_2; //将SMCLK和MCLK配置为REFOCLK

 

 

  while(1);

}


上面的代码就实现了将SMCLK和MCLK切换为VLOCLK和REFOCLK,ACLK的操作也是同样的,不作过多解释。

(2)将MCLK和SMCLK配置XT1CLK

我手头上的开发板XT1外接的是32.768K的手表时钟晶振,XT1CLK的配置要分为以下几步:


1.配置IO口5.4和5.5为XT1功能。

2.配置XCAP为XCAP_3,即12PF的电容。

3.清除XT1OFF标志位。

4.等待XT1起振。


具体的代码如下:

#include

 

void main(void) {

  WDTCTL = WDTPW+WDTHOLD;

  

  P1SEL |= BIT0;

  P1DIR |= BIT0;//测量ACLK用

  P2SEL |= BIT2;

  P2DIR |= BIT2;//测量SMCLK用

  P7SEL |= BIT7;

  P7DIR |= BIT7;//测量MCLK用

 

  P5SEL |= BIT4|BIT5; //将IO配置为XT1功能

  UCSCTL6 |= XCAP_3;  //配置电容为12pF

  UCSCTL6 &= ~XT1OFF; //使能XT1

 

  while (SFRIFG1 & OFIFG){

    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);         // 清除三类时钟标志位

                              // 这里需要清除三种标志位,因为任何一种

                              // 标志位都会将OFIFG置位

    SFRIFG1 &= ~OFIFG;                                  // 清除时钟错误标志位

  }

  UCSCTL4 = UCSCTL4&(~(SELS_7|SELM_7))|SELS_0|SELM_0;     //将SMCLK和MCLK时钟源配置为XT1

  while(1);

}


(3)将SMCLK和MCLK配置XT2

将SMCLK和MCLK配置为XT2跟配置为XT1的过程基本相同,唯一不同的是,在配置SMCLK和MCLK为XT2之前,需要将ACLK和REFCLK的时钟源,因为ACLK和REFCLK的默认时钟源是XT1,而我们这里并没有配置启动XT1CLK,所以会产生XT1时钟错误,即XT1LFFG,因此,我们先将ACLK和REFCLK配置为芯片自带的时钟(REFOCLK或VLOCLK)或者即将启动的时钟(XT2),此外,XT2配置时不需要配置电容,故将SMCLK和MCLK配置为XT2的代码如下:

#include

 

void main(void) {

  WDTCTL = WDTPW+WDTHOLD;

  

  P1SEL |= BIT0;

  P1DIR |= BIT0;//测量ACLK用

  P2SEL |= BIT2;

  P2DIR |= BIT2;//测量SMCLK用

  P7SEL |= BIT7;

  P7DIR |= BIT7;//测量MCLK用

 

  P5SEL |= BIT2|BIT3; //将IO配置为XT2功能

  UCSCTL6 &= ~XT2OFF; //使能XT2

 

  UCSCTL4 = UCSCTL4&(~(SELA_7))|SELA_1; //先将ACLK配置为VLOCLK

  UCSCTL3 |= SELREF_2;                  //将REFCLK配置为REFCLK

 

  while (SFRIFG1 & OFIFG){

    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);         // 清除三类时钟标志位

                              // 这里需要清除三种标志位,因为任何一种

                              // 标志位都会将OFIFG置位

    SFRIFG1 &= ~OFIFG;                                  // 清除时钟错误标志位

  }

  UCSCTL4 = UCSCTL4&(~(SELS_7|SELM_7))|SELS_5|SELM_5;     //将SMCLK和MCLK时钟源配置为XT2

  while(1);

}

做完前面三个实验,我们就能掌握MSP430F5XX系列时钟切换的基本操作了,讲的并不详细,有其他疑问请仔细阅读芯片手册或者留言讨论。


DCO模块详解

DCO模块在MSP430F5XX系列芯片中非常重要,因为从MSP430F4XX开始,MSP430引用了FLL模块,FLL即锁相环,可以通过倍频的方式提高系统时钟频率,进而提高系统的运行速度。

DCO模块运行需要参考时钟REFCLK,REFCLK可以来自REFOCLK、XT1CLK和XT2CLK,通过UCSCTL3的SELREF选择,默认使用的XT1CLK,但如果XT1CLK不可用则使用REFOCLK。

DCO模块有两个输出时钟信号,级DCOCLK和DCOCLKDIV,其中,倍频计算公式如下:

DCOCLK = D*(N+1)*(REFCLK/n)

DCOCLKDIV = (N+1)*(REFCLK/n)


其中:

n即REFCLK输入时钟分频,可以通过UCSCTL3中的FLLCLKDIV设定,默认为0,也就是不分频;

D可以通过UCSCTL2中的FLLD来设定,默认为1,也就是2分频;

N可以通过UCSCTL2中的FLLN来设定,默认值为32。

所以,系统上电后如果不做任何设置,DCOCLK的实际值为2097152,DCOCLKDIV的实际值为1048576。

另外,配置芯片工作频率还需要配置DCORSEL和DCOx,DCORSEL和DCOx的具体作用如下:

DCORSEL位于UCSCTL1控制寄存器中的4到6位,共3位,将DCO分为8个频率段。

DCOx位于UCSCTL0中的8到12位,共5位,将DCORSEL选择的频率段分为32个频率阶,每阶比前一阶高出约8%,该寄存器系统可以自动调整,通常配置为0。

DCORSEL和DCOx值的具体作用可以参考MSP430F5529的数据手册,阅读该手册相关部分可以找到如下表格:

可以见,DCORESL的频率调节范围大致如下:


DCORSEL = 0的调节范围约为0.20~0.70MHZ;

DCORSEL= 1的调节范围约为0.36~1.47MHZ;

DCORSEL = 2的调节范围约为0.75~3.17MHZ;

DCORSEL = 3的调节范围约为1.51~6.07MHZ;

DCORSEL = 4的调节范围约为3.2~12.3MHZ;

DCORSEL = 5的调节范围约为6.0~23.7MHZ;

DCORSEL = 6的调节范围约为10.7~39.7MHZ;

DCORSEL = 7的调节范围约为19.6~60MHZ。


理解了上面这些,可以理解TI官方例子中的代码了,官方代码中的相关部分如下:

if (fsystem <= 630)            //           fsystem < 0.63MHz

  UCSCTL1 = DCORSEL_0;

else if (fsystem <  1250)      // 0.63MHz < fsystem < 1.25MHz

  UCSCTL1 = DCORSEL_1;

else if (fsystem <  2500)      // 1.25MHz < fsystem <  2.5MHz

  UCSCTL1 = DCORSEL_2;

else if (fsystem <  5000)      // 2.5MHz  < fsystem <    5MHz

  UCSCTL1 = DCORSEL_3;

else if (fsystem <  10000)     // 5MHz    < fsystem <   10MHz

  UCSCTL1 = DCORSEL_4;

else if (fsystem <  20000)     // 10MHz   < fsystem <   20MHz

  UCSCTL1 = DCORSEL_5;

else if (fsystem <  40000)     // 20MHz   < fsystem <   40MHz

  UCSCTL1 = DCORSEL_6;

else

  UCSCTL1 = DCORSEL_7;


都在前面讲到的范围内,由于前面的范围有重叠部分,例子代码中的值是TI的工程师根据上面这些参数选取的比较合理的值。

到这里,我相信大家配合芯片手册和本文,都能明白DCO配置相关部分的原理了,下面是将DCO参考时钟选为XT1,并将DCOCLK倍频到25M的详细代码:

#include

 

void delay(){

  volatile unsigned int i;

  for(i = 0; i != 5000; ++i){

    _NOP();

  }

}

 

void SetVcoreUp (unsigned int level)

{

  // Open PMM registers for write

  PMMCTL0_H = PMMPW_H;

  // Set SVS/SVM high side new level

  SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;

  // Set SVM low side to new level

  SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;

  // Wait till SVM is settled

  while ((PMMIFG & SVSMLDLYIFG) == 0);

  // Clear already set flags

  PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);

  // Set VCore to new level

  PMMCTL0_L = PMMCOREV0 * level;

  // Wait till new level reached

  if ((PMMIFG & SVMLIFG))

    while ((PMMIFG & SVMLVLRIFG) == 0);

  // Set SVS/SVM low side to new level

  SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;

  // Lock PMM registers for write access

  PMMCTL0_H = 0x00;

}

 

void main(void) {

  WDTCTL = WDTPW+WDTHOLD;

  P1SEL &= ~BIT1;

  P1DIR |= BIT1;

  

  P1SEL |= BIT0; //ACLK

  P1DIR |= BIT0;

  P2SEL |= BIT2; //SMCLK

  P2DIR |= BIT2;

  P7SEL |= BIT7; //MCLK

  P7DIR |= BIT7;

 

  P5SEL |= BIT4|BIT5;

  UCSCTL6 |= XCAP_3;

  UCSCTL6 &= ~XT1OFF;

 

  SetVcoreUp(1); //一次提高Vcore电压等级,具体请参考手册

  SetVcoreUp(2);

  SetVcoreUp(3);

 

  __bis_SR_register(SCG0);

  UCSCTL0 = 0;

  UCSCTL1 = DCORSEL_6;

  UCSCTL2 = FLLD_1 | 380;

  __bic_SR_register(SCG0);

  __delay_cycles(782000);

 

  /*

   * 默认状态下:ACLK=FLLREFCLK=XT1 SMCLK=MCLK=DCOCLKDIV XT2关闭

   * 为了不产生XT1LFOFFG,将ACLK和FLLREFCLK设置为REFOCLK

   * 并打开XT2OFF,否则XT2将处于无法使用状态

   * */

  //UCSCTL6 &= ~(XT2DRIVE0|XT2DRIVE1|XT2OFF);

 

  while (SFRIFG1 & OFIFG) {                               // Check OFIFG fault flag

    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);         // Clear OSC flaut Flags

    SFRIFG1 &= ~OFIFG;                                  // Clear OFIFG fault flag

  }

 

  UCSCTL4 = UCSCTL4&(~(SELS_7|SELM_7))|SELS_3|SELM_3;

 

  while(1){

    P1OUT ^= BIT1;

    delay();

  }

}


好了,经过上面的四个实验,我们都能正确使用MSP430F5XX的UCS了,如果有什么疑问,欢迎留言讨论。


推荐阅读

史海拾趣

问答坊 | AI 解惑

意外的惊喜!考研+就业!

考研就业专刊 考研流程+考研经验+人才招聘会+薪资洽谈+面试攻略+健康贴士+时间表…… 妹妹大餐都在这里面! 尤其适合自动化相关专业,特别版!一路陪伴从准备到结束!!! 为了节省大家的芯币 本人最新编辑了一下 把所有的东西打 ...…

查看全部问答>

request_dma()函数中第一个参数是怎么得到?

int request_dma(unsigned int dmanr, const char * device_id) 参数dmanr是从0~3、5~7里面的随便挑一个就行了么? 还是需要怎么做来得到啊…

查看全部问答>

大家给我出出主意

几个问题 1.嵌入式的前景不错嘛?酬薪怎样? 2.嵌入式工程师没有35岁瓶颈吗? 3.我是个学生,想问下培训费用大概多少钱? 4.对于现在的情况,大学生是不是很需要培训,培训的目的和作用是什么? 我是个新手,希望大家好好指导我下。谢谢。大二 ...…

查看全部问答>

ARM7中断疑惑?请哪个大虾帮忙看看。小弟不胜感激!

在ARM7下写了一个定时器中断程序。下面代码是进入IRQ中断后然后为了可重入中断,就切换到系统模式下。但是在切换的时候出现问题?如何直接MSR CPSR_C,#SYS32_MODE(1)就出现SIGBUS错误。切换代码改成MSR CPSR_C,#(SYS32_MODE|NO_INT)(2)就行了 ...…

查看全部问答>

Tornado2.2(arm)的USB2.0问题

我的Tornado2.2里为什么没有EHCI和EHCI Init组件 但是别人好像有这个组件啊,是不是序列号的问题? 而且,我在pudn上下了安装,貌似就是t22-cp1-arm.tar那个东西,但是里面还是没有啊?请问高手怎么回事情啊? http://www.pudn.com/downloads148 ...…

查看全部问答>

uCOS-II内部机制

附件中的文件非常简洁的讲述了uCOS-II的内部机制,是不错的学习OS的资料…

查看全部问答>

EZ430——Rf2500学习小感

最近刚刚入手430,原来只接触过51,不过由于430的程序大都用C写得,所以学习起来还是比较方便的。前几天一直在学习uart的输出,具体做了一个有关uart的小程序,刚开始有例程可以看,不过不知道问什么,所有的例程都无法用串口助手加以显示输出,当 ...…

查看全部问答>

中断嵌套学习一些心得

中断嵌套,优先级430总中断的控制位是状态寄存器内的GIE位(该位在SR寄存器内),该位在复位状态下,所有的可屏蔽中断都不会发生响应。可屏蔽中断又分为单中断源和多中断源的。单中断源的一般响应了中断服务程序中断标志位就自动清零,而多中断源的 ...…

查看全部问答>

求助:可以给单片机外接晶体振荡器求出该晶振频率吗?

已知一个石英晶体的谐振频率为5MHz左右(大概偏差几十Hz),想要较为准确测试出其谐振频率,可以把它作为一个晶振,接到单片机的两个晶振输入端,然后算出这个石英晶体的谐振频率么?如果可以的话,具体怎么接怎么求算?精度如何?对应的程序怎么写 ...…

查看全部问答>

CCS controlSUITE是干什么用的?

(DSP)管网上说这个是C2000系列的例程,帮助,等文件软件,反正就是学习C2000安装这个肯定有用,不知道学习C5000,安装这个有没有用???…

查看全部问答>