您的位置 首页 嵌入式

MSP430学习之时钟

时钟初始化和GPIO概述:本实验的目的是了解用于执行对MSP430ValueLine设备的初始化过程的步骤。在这个练习中,您将编写初始化代码,并…

时钟初始化和GPIO

概述:

本试验的意图是了解用于履行对MSP430 Value Line设备的初始化进程的过程。在这个操练中,您将编写初始化代码,并运转该设备运用各种时钟资源。

1、写初始化代码

2、运转CPU的MCLK的来历方法:VLO 、32768晶体、DCO

3、主体程序部分

4、调查LED闪光灯速度

MSP430时钟:

1、在MSP430单片机中一共有三个或四个时钟源:

(1)LFXT1CLK,为低速/高速晶振源,一般接32.768kHz,也能够接(400kHz~16Mhz);

(2)XT2CLK,可选高频振荡器,外接规范高速晶振,一般是接8Mhz,也能够接(400kHz~16Mhz);

(3)DCOCLK,数控振荡器,为内部晶振,由RC震动回路构成;

(4)VLOCLK,内部低频振荡器,12kHz规范振荡器。

2、在MSP430单片机内部一共有三个时钟体系:

(1)ACLK,Auxiliary Clock,辅佐时钟,一般由LFXT1CLK或VLOCLK作为时钟源,能够经过软件操控更改时钟的分频系数;

(2)MCLK,Master Clock,体系主时钟单元,为体系内核供给时钟,它能够经过软件从四个时钟源挑选;

(3)SMCLK,Sub-Main Clock,体系子时钟,也是能够由软件挑选时钟源。

Basic Clock Module Registers(根底时钟寄存器)

DCO control register DCOCTL

Basic clock system control 1 BCSCTL1

Basic clock system control 2 BCSCTL2

Basic clock system control 3 BCSCTL3

SFR interrupt enable register 1 IE1

SFR interrupt flag register 1 IFG1

3、MSP430的时钟设置包含3个寄存器,DCOCTL、BCSCTL1、BCSCTL2、BCSCTL3

DCOCTL,DCO操控寄存器,地址为56H,初始值为60H

DCO2

DCO1

DCO0

MOD4

MOD3

MOD2

MOD1

MOD0

DCO0~DCO2: DCO Select Bit,界说了8种频率之一,而频率由注入直流发生器的电流界说。

MOD0~MOD4: Modulation Bit,频率的微调。

一般不需求DCO的场合坚持默许初始值就行了。

BCSCTL1,Basic Clock System Control 1,地址为57H,初始值为84H

XT2OFF

XTS

DIVA1

DIVA0

XT5V

RSEL2

RSEL1

RSEL0

RSEL0~RSEL2: 挑选某个内部电阻以决议标称频率.0最低,7最高。

XT5V: 1.

DIVA0~DIVA1:挑选ACLK的分频系数。DIVA=0,1,2,3,ACLK的分频系数别离是1,2,4,8;

XTS: 挑选LFXT1作业在低频晶体方式(XTS=0)仍是高频晶体方式(XTS=1)。

XT2OFF: 操控XT2振荡器的敞开(XT2OFF=0)与封闭(XT2OFF=1)。

正常情况下把XT2OFF复位就能够了.

BCSCTL2,Basic Clock System Control 2,地址为58H,初始值为00H

SEM1

SELM0

DIVM1

DIVM0

SELS

DIVS1

DIVS0

DCOR

DCOR: Enable External Resistor. 0,挑选内部电阻;1,挑选外部电阻

DIVS0~DIVS1: DIVS=0,1,2,3对应SMCLK的分频因子为1,2,4,8

SELS: 挑选SMCLK的时钟源, 0:DCOCLK; 1:XT2CLK/LFXTCLK.

DIVM0~1: 挑选MCLK的分频因子, DIVM=0,1,2,3对应分频因子为1,2,4,8.

SELM0~1: 挑选MCLK的时钟源, 0,1:DCOCLK, 2:XT2CLK, 3:LFXT1CLK

我用的时分一般都把SMCLK与MCLK的时钟源挑选为XT2。

其它:

1. LFXT1: 一次有用的PUC信号将使OSCOFF复位,答应LFXT1作业,假如LFXT1信号没有用作SMCLK或MCLK,可软件置OSCOFF封闭LFXT1.

2. XT2: XT2发生XT2CLK时钟信号,假如XT2CLK信号没有用作时钟MCLK和SMCLK,能够经过置XT2OFF封闭XT2,PUC信号后置XT2OFF,即XT2的封闭的。

3. DCO振荡器:振荡器失效时,DCO振荡器会主动被选做MCLK的时钟源。假如DCO信号没有用作SMCLK和MCLK时钟信号时,可置SCG0位封闭DCO直流发生器。

4. 在PUC信号后,由DCOCLK作MCLK的时钟信号,根据需求可将MCLK的时钟源别的设置为LFXT1或XT2,设置次序如下:

(1)清OSCOFF/XT2

(2)清OFIFG

(3)延时等候至少50uS

(4)再次查看OFIFG,假如仍置位,则重复(1)-(4)步,直到OFIFG=0中止。

(5)设置BCSCTL2的相应SELM。

实例剖析

1、CPU运转在VLO时钟下:

这是最慢的时钟,在约12千赫兹下运转。因而,咱们将经过可视化的LED闪耀的赤色慢慢地在约每3秒钟率。咱们能够让时钟体系默许这种状况,设置专门来操作VLO。咱们将不运用任何ALCK外设时钟在此试验室作业,但你应该认识到,ACLK来自VLO时钟。

#include <msp430g2231.h>

void main(void)

{

WDTCTL = WDTPW + WDTHOLD; // 封闭看门狗定时器

P1DIR = 0x40; // P1.6 装备输出

P1OUT = 0; // 封闭LED

BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO

IFG1 &= ~OFIFG; // 铲除OSCFault 标志

__bis_SR_register(SCG1 + SCG0); // 封闭 DCO

BCSCTL2 |= SELM_3 + DIVM_3; // MCLK = VLO/8

while(1)

{

P1OUT = 0x40; // 敞开LED

_delay_cycles(100);

P1OUT = 0; // 封闭 LED

_delay_cycles(5000);

}

}

2、CPU运转在晶振(32768Hz)时钟下:

晶体频率为32768赫兹,约3倍的VLO。假如咱们在前面的代码中运用晶振,指示灯应闪耀大约每秒一次。你知道为什么32768赫兹是一个规范?这是因为这个数字是2的15次方,因而很容易用简略的数字计数电路,以每秒一次取得率 ——手表和其他时刻时基。认识到ACLK来自外部晶振时钟。

#include

void main(void)

{

WDTCTL = WDTPW + WDTHOLD; // 封闭看门狗定时器

P1DIR = 0x41; // P1.0 和P1.6装备输出

P1OUT = 0x01; // 敞开P1.0

BCSCTL3 |= LFXT1S_0; // LFXT1 = 32768Hz 晶振

while(IFG1 & OFIFG)

{

IFG1 &= ~OFIFG; // 铲除 OSCFault 标志

_delay_cycles(100000); // 为可见的标志延时

}

P1OUT = 0; // 封闭P1

__bis_SR_register(SCG1 + SCG0); // 封闭 DCO

BCSCTL2 |= SELM_3 + DIVM_3; // MCLK = 32768/8

while(1)

{

P1OUT = 0x40; // 敞开 LED

_delay_cycles(100);

P1OUT = 0; / / 封闭LED

_delay_cycles(5000);

}

}

3、CPU运转在晶振(32768Hz)和DCO时钟下:

最慢的频率,咱们能够运转DCO约在1MHz(这也是默许速度)。因而,咱们将开端切换MCLK到DCO下。在大多数体系中,你会期望ACLK上运转的VLO或32768赫兹晶振。因为ACLK在咱们现在的代码是在晶体上运转,咱们会翻开DCO核算。

#include

void main(void)

{

WDTCTL = WDTPW + WDTHOLD; // 封闭看门狗定时器

if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)

{

while(1); // If cal const erased, 挂起

}

BCSCTL1 = CALBC1_1MHZ; // Set range

DCOCTL = CALDCO_1MHZ; //设置DCO方式

P1DIR = 0x41; // P1.0 和P1.6装备输出

P1OUT = 0x01; // P1.0 敞开

BCSCTL3 |= LFXT1S_0; // LFXT1 = 32768Hz

while(IFG1 & OFIFG)

{

IFG1 &= ~OFIFG; // 铲除OSCFault 标志

_delay_cycles(100000); // 为可见标志延时

}

P1OUT = 0; // P1.6 封闭

// __bis_SR_register(SCG1 + SCG0); // 封闭DCO

BCSCTL2 |= SELM_0 + DIVM_3; // MCLK = DCO

while(1)

{

P1OUT = 0x40; // P1.6 敞开

_delay_cycles(100);

P1OUT = 0; / / P1.6 封闭

_delay_cycles(5000);

}

}

4、CPU运转在DCO时钟下:

最慢的频率,咱们能够运转DCO约在1MHz(这也是默许速度)。因而,咱们将开端切换MCLK到DCO下。在大多数体系中,你会期望在VLO或者是晶振下运转ACLK。因为ACLK在咱们现在的代码是在VLO上运转,咱们会翻开DCO运转。

#include

void main(void)

{

WDTCTL = WDTPW + WDTHOLD; // 封闭看门狗定时器

if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)

{

while(1); // If cal const erased,挂起

}

BCSCTL1 = CALBC1_1MHZ; // Set range

DCOCTL = CALDCO_1MHZ; // 设置DCO方式

P1DIR = 0x40; // P1.6 装备输出

P1OUT = 0; // P1封闭

BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO

IFG1 &= ~OFIFG; // 铲除 OSCFault 标志

//__bis_SR_register(SCG1 + SCG0); // 封闭DCO

BCSCTL2 |= SELM_0 + DIVM_3; // MCLK = DCO/8

while(1)

{

P1OUT = 0x40; // P1.6 封闭

_delay_cycles(100);

P1OUT = 0; // P1.6 敞开

_delay_cycles(5000);

}

}

以下将会剖析上面4个比如的代码细微差别:

首要让咱们看一下msp430x20x2.h这个文件中的内容,因为头文件信息量很大这儿就只简略阐明和以上四个代码有关的部分,其他请咱们自行阅览。

一、WDTCTL = WDTPW + WDTHOLD; // 封闭看门狗定时器(例1、2、3、4)

头文件中的相关阐明如下:

/************************************************************

* WATCHDOG TIMER

************************************************************/

#define __MSP430_HAS_WDT__ /* Definition to show that Module is available */

SFR_16BIT(WDTCTL); /* Watchdog Timer Control */

/* The bit names have been prefixed with “WDT” */

#define WDTIS0 (0x0001)

#define WDTIS1 (0x0002)

#define WDTSSEL (0x0004)

#define WDTCNTCL (0x0008)

#define WDTTMSEL (0x0010)

#define WDTNMI (0x0020)

#define WDTNMIES (0x0040)

#define WDTHOLD (0x0080)

#define WDTPW (0x5A00)

这个指令设置暗码(WDTPW)和中止位定时器(WDTHOLD),一切的WatchDog装备都需求在WDTPW的辅佐下完结。

举例如下:

A、间隔时刻由Bit0-2位编码:

1、看门狗的时钟由FSMCLK(假设为1MHz)

#defineWDT_MDLY_32 (WDTPW+WDTTMSEL+WDTCNTCL) /* 32ms interval (default) */

#defineWDT_MDLY_8 (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS0) /* 8ms ” */

#defineWDT_MDLY_0_5 (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS1) /* 0.5ms ” */

#defineWDT_MDLY_0_064 (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS1+WDTIS0) /* 0.064ms ” */

2、看门狗的时钟由FACLK(假设为32KHz)

#defineWDT_ADLY_1000 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL) /* 1000ms ” */

#defineWDT_ADLY_250 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS0) /* 250ms ” */

#defineWDT_ADLY_16 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1) /* 16ms ” */

B、看门狗方式——在过期时刻后重启:

1、看门狗的时钟由FSMCLK(假设为1MHz)

#defineWDT_MRST_32 (WDTPW+WDTCNTCL) /* 32ms interval (default) */

#defineWDT_MRST_8 (WDTPW+WDTCNTCL+WDTIS0) /* 8ms ” */

#defineWDT_MRST_0_5 (WDTPW+WDTCNTCL+WDTIS1) /* 0.5ms ” */

#defineWDT_MRST_0_064 (WDTPW+WDTCNTCL+WDTIS1+WDTIS0) /* 0.064ms ” */

2、看门狗的时钟由FACLK(假设为32KHz)

#defineWDT_ARST_1000 (WDTPW+WDTCNTCL+WDTSSEL) /* 1000ms ” */

#defineWDT_ARST_250 (WDTPW+WDTCNTCL+WDTSSEL+WDTIS0) /* 250ms ” */

#defineWDT_ARST_16 (WDTPW+WDTCNTCL+WDTSSEL+WDTIS1) /* 16ms ” */

#defineWDT_ARST_1_9 (WDTPW+WDTCNTCL+WDTSSEL+WDTIS1+WDTIS0) /* 1.9ms ” */

二、P1DIR = 0x40; // P1.6 装备输出

P1OUT = 0; // P1封闭 (例1、2、3、4)

其间DIR 和P1OUT别离装备IO口的方向和输出值,这儿不在赘述,请参考手册。

三、BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO (例1和例4)

BCSCTL3 |= LFXT1S_0; // LFXT1 = 32768Hz (例2和例3)

/************************************************************

* Basic Clock Module

************************************************************/

#define__MSP430_HAS_BC2__

/* Definition to show that Module is available */

SFR_8BIT(DCOCTL); /* DCO Clock Frequency Control */

SFR_8BIT(BCSCTL1); /* Basic Clock System Control 1 */

SFR_8BIT(BCSCTL2); /* Basic Clock System Control 2 */

SFR_8BIT(BCSCTL3); /* Basic Clock System Control 3 */

#defineMOD0 (0x01) /* Modulation Bit 0 */

#defineMOD1 (0x02) /* Modulation Bit 1 */

#defineMOD2 (0x04) /* Modulation Bit 2 */

#defineMOD3 (0x08) /* Modulation Bit 3 */

#defineMOD4 (0x10) /* Modulation Bit 4 */

#defineDCO0 (0x20) /* DCO Select Bit 0 */

#defineDCO1 (0x40) /* DCO Select Bit 1 */

#defineDCO2 (0x80) /* DCO Select Bit 2 */

#defineLFXT1OF (0x01)

/* Low/high Frequency Oscillator Fault Flag */

#defineXT2OF (0x02)

/* High frequency oscillator 2 fault flag */

#defineXCAP0 (0x04) /* XIN/XOUT Cap 0 */

#defineXCAP1 (0x08) /* XIN/XOUT Cap 1 */

#defineLFXT1S0 (0x10) /* Mode 0 for LFXT1 (XTS = 0) */

#defineLFXT1S1 (0x20) /* Mode 1 for LFXT1 (XTS = 0) */

#defineXT2S0 (0x40) /* Mode 0 for XT2 */

#defineXT2S1 (0x80) /* Mode 1 for XT2 */

#defineXCAP_0 (0x00) /* XIN/XOUT Cap : 0 pF */

#defineXCAP_1 (0x04) /* XIN/XOUT Cap : 6 pF */

#defineXCAP_2 (0x08) /* XIN/XOUT Cap : 10 pF */

#defineXCAP_3 (0x0C) /* XIN/XOUT Cap : 12.5 pF */

#defineLFXT1S_0 (0x00)

/* Mode 0 for LFXT1 : Normal operation */

#defineLFXT1S_1 (0x10) /* Mode 1 for LFXT1 : Reserved */

#defineLFXT1S_2 (0x20) /* Mode 2 for LFXT1 : VLO */

#defineLFXT1S_3 (0x30)

/* Mode 3 for LFXT1 : Digital input signal */

#defineXT2S_0 (0x00) /* Mode 0 for XT2 : 0.4 – 1 MHz */

#defineXT2S_1 (0x40) /* Mode 1 for XT2 : 1 – 4 MHz */

#defineXT2S_2 (0x80) /* Mode 2 for XT2 : 2 – 16 MHz */

#defineXT2S_3 (0xC0)

/* Mode 3 for XT2 : Digital input signal */

四、__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中有如下界说:

#defineRSEL0 (0x01) /* Range Select Bit 0 */

#defineRSEL1 (0x02) /* Range Select Bit 1 */

#defineRSEL2 (0x04) /* Range Select Bit 2 */

#defineRSEL3 (0x08) /* Range Select Bit 3 */

#defineDIVA0 (0x10) /* ACLK Divider 0 */

#defineDIVA1 (0x20) /* ACLK Divider 1 */

#defineXTS (0x40)

/* LFXTCLK 0:Low Freq. / 1: High Freq. */

#defineXT2OFF (0x80) /* Enable XT2CLK */

#defineDIVA_0 (0x00) /* ACLK Divider 0: /1 */

#defineDIVA_1 (0x10) /* ACLK Divider 1: /2 */

#defineDIVA_2 (0x20) /* ACLK Divider 2: /4 */

#defineDIVA_3 (0x30) /* ACLK Divider 3: /8 */

#defineDIVS0 (0x02) /* SMCLK Divider 0 */

#defineDIVS1 (0x04) /* SMCLK Divider 1 */

#defineSELS (0x08)

/* SMCLK Source Select 0:DCOCLK / 1:XT2CLK/LFXTCLK */

#defineDIVM0 (0x10) /* MCLK Divider 0 */

#defineDIVM1 (0x20) /* MCLK Divider 1 */

#defineSELM0 (0x40) /* MCLK Source Select 0 */

#defineSELM1 (0x80) /* MCLK Source Select 1 */

#defineDIVS_0 (0x00) /* SMCLK Divider 0: /1 */

#defineDIVS_1 (0x02) /* SMCLK Divider 1: /2 */

#defineDIVS_2 (0x04) /* SMCLK Divider 2: /4 */

#defineDIVS_3 (0x06) /* SMCLK Divider 3: /8 */

#defineDIVM_0 (0x00) /* MCLK Divider 0: /1 */

#defineDIVM_1 (0x10) /* MCLK Divider 1: /2 */

#defineDIVM_2 (0x20) /* MCLK Divider 2: /4 */

#defineDIVM_3 (0x30) /* MCLK Divider 3: /8 */

#defineSELM_0 (0x00) /* MCLK Source Select 0: DCOCLK */

#defineSELM_1 (0x40) /* MCLK Source Select 1: DCOCLK */

#defineSELM_2 (0x80)

/* MCLK Source Select 2: XT2CLK/LFXTCLK */

#defineSELM_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

(外部引证处理的特定于设备的连接器指令文件)

#defineSFR_8BIT(address)extern volatile unsigned charaddress

#defineSFR_16BIT(address)extern volatile unsigned intaddress

七、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灯。不然,它会这么快,咱们的光将无法看到它。

装备:

BCSCTL1

BCSCTL2

BCSCTL3

DCOCTL

IFG1

VLO(12KHz)

SELM_3 + DIVM_3

LFXT1S_2

32768KHz

SELM_3 + DIVM_3

LFXT1S_0

While

晶振、DCO

SELM_0+ DIVM_3

LFXT1S_0

While

DCO

CALBC1_1MHZ

SELM_0+ DIVM_3

LFXT1S_2

CALDCO_1MHZ

成果:

ACLK

MCLK

LFXT1

VLO(12KHz)

VLO

VLO/8

VLO

32768Hz

32768Hz

32768Hz/8

32768Hz

晶振、DCO

32768Hz

DCO

32768Hz

DCO

VLO

DCO/8

VLO

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/326018.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部