历史上的今天
今天是:2025年01月21日(星期二)
2020年01月21日 | MSP430晶振配置详解
2020-01-21 来源:eefocus
MSP430(F5529)相比MSP430(F149)来讲,功能更加强大。
UCS简介
MSP430F5XX/MSP430F6XX系列器件的UCS包含有五种时钟源,依次是:XT1CLK、VLOCLK、REFOCLK、DCOCLK和XT2CLK。这五种时钟的详细介绍请参考该系列芯片的指导手册,其中XT1CLK、VLOCLK、REFOCLK和XT2CLK跟MSP430F1XX系列没有太大区别,学习配置起来也比较简单。
UCS上电默认状态
PUC后,UCS模块的默认状态如下:
在CODE上查看代码片派生到我的代码片
(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即可,具体代码如下:
在CODE上查看代码片派生到我的代码片
#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的配置要分为以下几步: 在CODE上查看代码片派生到我的代码片 1.配置IO口5.4和5.5为XT1功能。 2.配置XCAP为XCAP_3,即12PF的电容。 3.清除XT1OFF标志位。 4.等待XT1起振。 具体的代码如下: 在CODE上查看代码片派生到我的代码片 #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的代码如下: 在CODE上查看代码片派生到我的代码片 #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,其中,倍频计算公式如下: 在CODE上查看代码片派生到我的代码片 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的频率调节范围大致如下: 在CODE上查看代码片派生到我的代码片 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官方例子中的代码了,官方代码中的相关部分如下: 在CODE上查看代码片派生到我的代码片 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的详细代码: 在CODE上查看代码片派生到我的代码片 #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); 
下一篇:关于MSP硬件I2C讲解
史海拾趣
|
昨天用填充零低格硬盘时选错了硬盘,10秒之后觉得不对强行关机,把低格后的硬盘接在另一台电脑上后,用WinHex查看mbr,不出所料,全部是0.从自己机器硬盘复制前446个字节后,后面64位分区表搞不定了。 我用数据修复软 ...… 查看全部问答> |
|
工作地点:北京市海淀区 专业要求:软件工程、计算机应用等相关专业 学历要求:本科以上 工作经验:不限 有效期至:2007年12月10日 工作职责: 负责医用光电设备应用软件的开发、修改及维护。 职位要求: 1、熟练使用VB、VC进行usb通讯及图 ...… 查看全部问答> |
|
刚才做实验发现一个大问题,使用ST的固件库 执行如下程序 while(1){ GPIO_SetBits(GPIOB,GPIO_Pin_11); GPIO_ResetBits(GPIOB,GPIO_Pin_11); }用示波器看完整的波形周期竟然 ...… 查看全部问答> |
|
美国,达拉斯-2009 年 5月14日,德州仪器公司(NYSE:TXN)宣布,为了扩展 MCU产品线,将收购Luminary Micro (全球领先的基于ARM Cortex-M3的32位MCU的供应商) 。Luminary Micro公司旗下的Stellari ...… 查看全部问答> |
|
FLASH是SST39VF400A,原理图用的和CCS文档中的提供的,DSP是TMS320C6701,程序跑起来,运行到写数据就死了,不知道怎么回事? 代码如下: void main() { int f; f = Check_SST_39VF400A(); &nbs ...… 查看全部问答> |




