四、__bis_SR_register(SCG1 + SCG0); // 关闭 DCO
__bis_SR_register()是在intrinsics.h这个头文件中定义了,实现的功能是将SR中的位置零。 关于头文件中的代码作用 #ifdef __cplusplus extern "C" { #endif #ifdef __cplusplus } #endif /* extern "C" */ 一般用于将C++代码以标准C形式输出(即以C的形式被调用),这是因为C++虽然常被认为是C的超集,但是C++的编译器还是与C的编译器不同的。C中调用C++中的代码这样定义会是安全的。
五、BCSCTL2 |= SELM_3 + DIVM_3; // MCLK = VLO/8 BCSCTL2 |= SELM_3 + DIVM_3; // MCLK = 32768/8 BCSCTL2 |= SELM_0 + DIVM_3; // MCLK = DCO BCSCTL2 |= SELM_0 + DIVM_3; // MCLK = DCO/8 MSP430中有如下定义: #define RSEL0 (0x01) /* Range Select Bit 0 */ #define RSEL1 (0x02) /* Range Select Bit 1 */ #define RSEL2 (0x04) /* Range Select Bit 2 */ #define RSEL3 (0x08) /* Range Select Bit 3 */ #define DIVA0 (0x10) /* ACLK Divider 0 */ #define DIVA1 (0x20) /* ACLK Divider 1 */ #define XTS (0x40) /* LFXTCLK 0:Low Freq. / 1: High Freq. */ #define XT2OFF (0x80) /* Enable XT2CLK */
#define DIVA_0 (0x00) /* ACLK Divider 0: /1 */ #define DIVA_1 (0x10) /* ACLK Divider 1: /2 */ #define DIVA_2 (0x20) /* ACLK Divider 2: /4 */ #define DIVA_3 (0x30) /* ACLK Divider 3: /8 */
#define DIVS0 (0x02) /* SMCLK Divider 0 */ #define DIVS1 (0x04) /* SMCLK Divider 1 */ #define SELS (0x08) /* SMCLK Source Select 0:DCOCLK / 1:XT2CLK/LFXTCLK */ #define DIVM0 (0x10) /* MCLK Divider 0 */ #define DIVM1 (0x20) /* MCLK Divider 1 */ #define SELM0 (0x40) /* MCLK Source Select 0 */ #define SELM1 (0x80) /* MCLK Source Select 1 */
#define DIVS_0 (0x00) /* SMCLK Divider 0: /1 */ #define DIVS_1 (0x02) /* SMCLK Divider 1: /2 */ #define DIVS_2 (0x04) /* SMCLK Divider 2: /4 */ #define DIVS_3 (0x06) /* SMCLK Divider 3: /8 */
#define DIVM_0 (0x00) /* MCLK Divider 0: /1 */ #define DIVM_1 (0x10) /* MCLK Divider 1: /2 */ #define DIVM_2 (0x20) /* MCLK Divider 2: /4 */ #define DIVM_3 (0x30) /* MCLK Divider 3: /8 */
#define SELM_0 (0x00) /* MCLK Source Select 0: DCOCLK */ #define SELM_1 (0x40) /* MCLK Source Select 1: DCOCLK */ #define SELM_2 (0x80) /* MCLK Source Select 2: XT2CLK/LFXTCLK */ #define SELM_3 (0xC0) /* MCLK Source Select 3: LFXTCLK */
六、BCSCTL1 = CALBC1_1MHZ; //设置值 (例3、4) #ifndef __DisableCalData SFR_8BIT(CALDCO_16MHZ); /* DCOCTL Calibration Data for 16MHz */ SFR_8BIT(CALBC1_16MHZ); /* BCSCTL1 Calibration Data for 16MHz */ SFR_8BIT(CALDCO_12MHZ); /* DCOCTL Calibration Data for 12MHz */ SFR_8BIT(CALBC1_12MHZ); /* BCSCTL1 Calibration Data for 12MHz */ SFR_8BIT(CALDCO_8MHZ); /* DCOCTL Calibration Data for 8MHz */ SFR_8BIT(CALBC1_8MHZ); /* BCSCTL1 Calibration Data for 8MHz */ SFR_8BIT(CALDCO_1MHZ); /* DCOCTL Calibration Data for 1MHz */ SFR_8BIT(CALBC1_1MHZ); /* BCSCTL1 Calibration Data for 1MHz */ #endif /* #ifndef __DisableCalData */
关于SFR_8BIT的相关说明: External references resolved by a device-specific linker command file (外部引用解决的特定于设备的连接器命令文件) #define SFR_8BIT(address) extern volatile unsigned char address #define SFR_16BIT(address) extern volatile unsigned int address
七、if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF) { while(1); // If cal const erased,挂起 } (例3、例4) 请注意这里的陷阱。它可以清除内存段信息。
八、IFG1 &= ~OFIFG; // 清除OSCFault 标志 (例1、例4) 时钟系统将强制使用的MCLK作为其源的DCO在一个时钟故障的存在。因此,我们必须清除故障标志。 FG1中断标志寄存器是1。寄存器中的位域是唯一的振荡器故障中断标志 - OFIFG。
九、while(IFG1 & OFIFG) { IFG1 &= ~OFIFG; // 清除OSCFault 标志 _delay_cycles(100000); // 为可见标志延时 } (例2、例3) 在上面的代码我们把OSCFault标志继续做我们的任务,由于时钟系统将默认为VLO。现在,我们希望确保该标志保持清零,这意味着晶体是启动并运行着的。 如果该故障标志是明确的,我们就退出循环。我们需要等待清算后的标志,直到我们再次测试50微秒。该_delay_cycles(100000)。我们需要它是那么长的时间,所以我们可以看到在代码开头的LED灯。否则,它会这么快,我们的光将无法看到它。
首先申明一下我也是才刚刚开始接触MSP430的片子,算是和大家一起学习吧,很多地方也不是很清楚。总之希望大家好好体会一下MSP430的头文件(名为:msp430x20x2.h),如果文章中有错误的话希望大家发邮件给我。纯属菜鸟入门级别文档,只是简单的分析了一下MSP430的时钟配置问题,对于一个单片机系统而言时钟可谓是重中之重,可能刚入门多是采用51系列的片子(不包括C8051f系列)所以对时钟也就没有过多的接触,只是涉及速度以及延时程序的时候才会去关心。其实芯片越是高端越是对时钟有很高的要求,不管是PIC、AVR还是C8051F这些8位的片子,在32位的领域更是这样,像我所熟悉的Cortex-M3系列包括STM32f103、Stellaris、NXP都是这样,片子内部的时钟都是相当的复杂。 最后在来唠叨几句,记得以前玩51的时候那个头文件真是小儿科,只有寄存器的定义还有一些位操作。程序写起来相当的麻烦,很多东西都需要去记忆或者干脆去看文档,所以那个时候还特地写了一个驱动库(效仿STM32f103给STC12C5A60S2写的,取名为Easy Hw OS,其实还是很方便的直接调用函数就可以啦),看到430的头文件才豁然开朗,这样做好,虽然没有驱动库方便但是很灵活也不需要去记忆那些寄存器的,真的很不错。喜欢上了430为文以记之。
|