這裏使用TimerA的PWM功能,配置TACCTL1輸出3路佔空比相同的PWM方波。TimerA模塊由計數器TAR,3個輸入捕獲/輸出比較器(Capature/compare Model)組成。其中CCM0的寄存器CCR0,是定時器的週期寄存器,所以CCM0很特殊,不適合做PWM輸出和輸入捕獲。這裏使用CCM1來輸出三路波形相同的PWM方波。
涉及寄存器
TACCTL1用來配置輸出PWM方波,只需要關掉輸入捕獲,然後選擇PWM輸出模式即可。CM[1:0]=00(默認), OUTMOD[2:0]=111;
然後配置寄存器TACCR1,裝載在TACCR1中的值發揮的作用由OUTMOD的選擇決定。
PWM輸出模式介紹如下:
OUTMODE[2:0]三位是決定了TAR計數器計數到與TACCR0和TACCR1時,輸出電平的翻轉變化。當OUTMOD[2:0]=111時,TAR計數到TACCR1是輸出電平置0,直到TAR計數到TACCR0時置1,然後循環往復,輸出佔空比爲 (TACCR0 - TACCR1)/TACCR0*100%的PWM方波。
要想輸出PWM波,當然是需要配置定時器的,只是不使能中斷,以定時器時鐘爲基準輸出PWM波。
C程序代碼
#include <msp430x16x.h>
void Clock_init(void);
//void Clock_output(void); //just for debug
void TimerA_init(void);
void Gpio_init(void);
int main( void )
{
//Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
Clock_init();
//Clock_output(); //just for debug
TimerA_init();
Gpio_init();
_EINT(); //enable the general interrupt
LPM0; //enter LPM0 mode
while(1)
{
}
}
void TimerA_init(void)
{
TACTL |= TASSEL0 + TACLR; //select ACLK , clear TAR
TACCR0 = 1024; //ft =ACLK/4096
TACTL |= MC0; //increase counter model
//set the compare mode, generate the PWM
TACCTL1 |= OUTMOD2 + OUTMOD1 + OUTMOD0; //OUTMOD7 reset/set, no capture
TACCR1 = 512;
}
void Gpio_init(void)
{
P1SEL |= BIT2; //set P1.2 multiplex function, TA1 output, PWM channel 1
P1DIR |= BIT2; //set P1.2 asoutput
P1SEL |= BIT6; //set P1.6 multiplex function, TA1 output, PWM channel 2
P1DIR |= BIT6;
P2SEL |= BIT3; //set P2.3 multiplex function, TA1 output, PWM channel 3
P2DIR |= BIT3;
}
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 XT2as 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
}
運行結果
我配置的ACLK=4096Hz,TimerA時鐘源選擇ACLK,1分頻,TimerA時鐘爲4096Hz。TACCR0=1024,那麼PWM週期就是1/4s=250ms. TACCR1=512,那麼佔空比就是(1024-512)/1024 = 50%.與測試結果相符。