MSP430的TimerA功能強大,可以用作定時器、PWM發生器和輸入捕獲器,這裏我們介紹TimerA用作定時器時該怎麼配置寄存器。
涉及寄存器
TACTL是TimerA的控制寄存器,我們需要使用TimerA的功能都必須對它進行配置。
TASSELx位於寄存器的第9、8位,用於選擇TimerA模塊的時鐘源。這裏我選擇ACLK(被配置爲4096Hz),即TASSEL[1:0]= 01.
IDx是對時鐘源進行分頻,這裏我1分頻(不分頻),ID[1:0]=00.
MCx是定時器模式選擇,這裏我選擇增模式(up mode),MC[1:0]=01.
增模式時序圖如下:
計數器TAR中的值從0開始遞增到與TACCR0值相等,然後復位,繼續遞增,如此循環往復。
TACLR是計數器TAR的清除位,置1則TAR復位爲0.
TAIE位很雞肋,是TimerA的溢出中斷使能位,其實就是在TAR中的值等於TACCR0的值時,產生一箇中斷,置位溢出中斷標誌位TAIFG。使用CCIE完全是同樣的效果。
TAR 定時器TimerA的16位計數器,每經過一個TimerA的時鐘週期,計數器自增1.我選的定時器時鐘爲4096Hz/1=4096Hz,也就是說1秒鐘,TAR可以從0增加到4096.
TACCTLx是一系列的寄存器,這裏定時器功能只需要使用TACCTL0中的一個位CCIE,使能輸出比較/輸入捕獲模塊0的中斷,其他位默認就行。至於CCIFG位,我完全不知道怎麼用,到了中斷函數裏邊就清零了,也許可以關中斷查詢一下吧*_*
還有一個寄存器需要用,TACCR0。這個寄存器用作TimerA整個模塊的週期寄存器,我們需要在這個16位寄存器中載入初值。這個初值就是TAR自增到與之相等時復位的值。譬如說,定時器的時鐘是4096Hz,我在TACCR0中寫了4096,這樣配置的話,不出意外1S進行一次中斷。
C程序代碼
#include <msp430x16x.h>
void Clock_init(void);
//void Clock_output(void); //just for debug
void Led_init(void);
void TimerA_init(void);
int main( void )
{
//Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
Clock_init();
//Clock_output(); //just for debug
Led_init();
TimerA_init();
_EINT(); //enable the general interrupt
LPM0; //enter LPM0 mode
while(1)
{
}
}
#pragma vector=TIMERA0_VECTOR
__interrupt void TIMERA0_ISR(void)
{
if(P4OUT & BIT7)
P4OUT &= ~BIT7;
else
P4OUT |= BIT7;
}
void TimerA_init(void)
{
TACTL |= TASSEL0 + TACLR; //select ACLK , clear TAR
TACCR0 = 4096;
TACTL |= MC0; //increase counter mode
CCTL0 |= CCIE; //enable interrupt of TACCR0
}
void Led_init(void)
{
P4SEL &= ~BIT7; //select IO function, P4.7
P4DIR |= BIT7; //set P4.7 as output
P4OUT &= ~BIT7; //output low level
}
void Clock_init(void)
{
unsigned int i;
//set ACLK = 4096Hz ; start XT2
BCSCTL1 &= ~XT2OFF; //XT2OFF = 0;
BCSCTL1 &= ~XTS; //XTS = 0XT1 low frequence 32.768KHz
BCSCTL1 |= DIVA1 + DIVA0; //DIVAx = 11, ACLK = fosc/8 = 32.768KHz/8 = 4096Hz
//set SMCLK = 1MHz
BCSCTL2 |= SELS; //set XT2 as the clock source of SMCLK
BCSCTL2 |= DIVS1 + DIVS0;//DIVSx = 11, SMCLK = fosc/8 = 8MHz/8 =1MHz
//set MCLK = 1MHz
BCSCTL2 |= SELM1; //SELMx = 10,select XT2CLK as the clock source of MCLK
BCSCTL2 &= ~SELM0;
BCSCTL2 |= DIVM1 + DIVM0; //DIVMx = 11, MCLK = fosc/8 = 8MHz / 8 = 1MHz
do
{
IFG1 &= ~OFIFG; //clear oscillator fault flag
for(i = 0xff; i > 0; i--); //delay some time ,wait for the oscillator works nomally
}while ((IFG1 & OFIFG) != 0); //do-while when oscillator fault occurs
}
void Clock_output(void)
{
//set P2.0 to output ACLK
P2DIR |= BIT0; //set P2.0 as output
P2SEL |= BIT0; //set multiplex function , ACLK output
P1DIR |= BIT4;
P1SEL|= BIT4;
//set P5.4 to output MCLK
P5DIR |= BIT4; //set P5.4 as output
P5SEL |= BIT4; //select multiplex function MCLK output
}
運行結果
這是我用示波器測量P4.7引腳得到的波形,大致就是1s變換一次電平了,我也可以看到LED燈亮和滅的時間大致是1s,達到了預期的效果。至於波形不太標準,是因爲電壓不夠穩定吧。