12.1 定时器A介绍
定时器是一个能对时钟脉冲进行计数的计数器,当时钟脉冲规则时,定时器可以进行严格的定时,当时钟脉冲不规则时,定时器为一个计数器。
定时器A是一个16位的定时/计数器,有三个捕获/比较寄存器。定时器A可以支持多个捕获/比较、PWM输出和间隔定时。定时器A还有充分的中断能力,中断可以产生于计数器的溢出状态以及每一个捕获/比较寄存器。
定时器A的特点包括:
·异步的16位定时器/计数器,有4种运行模式
·可选的和可设置的时钟源
·2个或3个可设置的捕获/比较寄存器
·可设置的输出,有PWM能力
·异步输入和输出锁存
·中断向量寄存器用于所有定时器A中断的快速解码
定时器A模块是由用户软件设置的,对定时器A的设置和操作在下述例程中进行讨论。
12.2 定时器A的例程
例12.1用PWM波来点亮与P1.2相连接的红色LED(取下跳线帽,用杜邦线连接红色LED和P1.2管脚)。选择P1.2的第二输出功能,即输出PWM波。选择ACLK为定时器的时钟源。按下按键S2(与P1.3相连)时产生I/O口中断,在中断服务程中让全局变量a加1,在while(1)主循环中,根据a的值切换TACCR1的值,从而改变了PWM波的占空比,则红色LED的亮度随之改变。
具体程序如下:
#include"msp430g2553.h"
int a=0;
void main()
{
WDTCTL=WDTPW+WDTHOLD; //关闭看门狗
BCSCTL3|=LFXT1S_2; //选择VLO低频时钟为ACLK的时钟源
P1DIR|=BIT2; //设置P1.2为输出方向
P1SEL2&=~BIT2;
P1SEL|=BIT2; //选择P1.2的第二输出功能,即输出PWM波
P1DIR&=~BIT3; //设置P1.3为输入方向
P1REN|=BIT3; //P1.3内部上/下拉使能
P1OUT|=BIT3; //P1.3被上拉,连接于P1.3的按键未按下时,P1.3的输入为高电平
P1IES|=BIT3; //设置P1.3下降沿产生中断
P1IE|=BIT3; //P1.3中断允许
_EINT(); //开启总中断
TACTL|= MC_1+TASSEL_1+ID_0;//设置Timer0_A增量计数至TACCR0,选择ACLK为定时器的时钟源,不分频
TACCTL1=OUTMOD_7; //PWM输出方式7:PWM复位、置位方式
TACCR0=328-1; //为TACCR0赋初值
TACCR1=0; //为TACCR1赋初值。
while(1)
{
switch(a) //用switch()语句来进行判断和切换
{
case 0: TACCR1=0; //TACCR1值的大小决定了PWM波的占空比,占空比越大,LED灯越亮。
break;
case 1: TACCR1=1;
break;
case 2: TACCR1=5;
break;
case 3: TACCR1=15;
break;
case 4: TACCR1=20;
break;
case 5: TACCR1=30;
break;
case 6: TACCR1=40;
break;
case 7: TACCR1=100;
break;
case 8: TACCR1=120;
break;
case 9: TACCR1=130;
break;
case 10:TACCR1=160;
break;
case 11:TACCR1=325;
break;
default:
break;
}
}
}
#pragma vector=PORT1_VECTOR
__interrupt void P1_ISR(void) //P1口中断程序
{
P1IFG=0; //中断标志清零
int i;
for(i=0;i<1000;i++); //延时后判、消抖
if(P1IN&BIT3)
return;
else
a++;
if(a==12)
a=0;
}
例12.2用PWM波来点亮与P2.1相连接的红色LED(取下跳线帽,用杜邦线连接红色LED和P2.1管脚),以及与P2.4相连接的绿色LED(取下跳线帽,用杜邦线连接绿色LED和 P2.4管脚)。设置管脚的第二功能,让P2.1和P2.4输出两路PWM波。设置Timer1_A,产生两个PWM波TA1.1和TA1.2。按下按键S2(与P1.3相连)时产生I/O口中断,在中断服务程中让全局变量a加1,在while(1)主循环中,根据a的值切换TA1CCR1和TA1CCR2的值,从而改变了PWM波的占空比,红色LED和绿色LED的亮度随之改变。
具体程序如下:
#include"msp430g2553.h"
int a=0;
void main()
{
WDTCTL=WDTPW+WDTHOLD; //关闭看门狗
P2DIR|=BIT4+BIT1;
P2SEL2&=~(BIT4+BIT1);
P2SEL|=BIT4+BIT1; //选择P2.1、P2.4的第二输出功能,即输出PWM波
//P2.1输出TA1.1,P2.4输出TA1.2
P1DIR&=~BIT3; //设置P1.3为输入方向
P1REN|=BIT3; //P1.3内部上/下拉使能
P1OUT|=BIT3; //P1.3被上拉,连接于P1.3的按键未按下时,P1.3的输入为高电平
P1IES|=BIT3; //设置P1.3下降沿中断
P1IE|=BIT3; //P1.3中断允许
_EINT();
TA1CTL|= MC_1+TASSEL_2+ID_0; //设置Timer1_A增量计数至TACCR0,选择SMCLK,不分频
TA1CCTL1=OUTMOD_7; //TA1.1,PWM输出方式7:PWM复位、置位方式
TA1CCR0=328-1; //为TA1CCR0赋初值
TA1CCR1=0; //为TA1CCR1赋初值;本句可以不要。
TA1CCTL2=OUTMOD_3; //TA1.2,PWM输出方式3:PWM置位、复位方式
TA1CCR2=0; //为TA1CCR2赋初值;本句可以不要。
while(1)
{
switch(a) //用switch()语句来进行判断和切换
{
case 0: TA1CCR1=0; //TACCR1值的大小决定了PWM波的占空比,占空比越大,LED灯越亮。
TA1CCR2=327;
break;
case 1: TA1CCR1=1;
TA1CCR2=280;
break;
case 2: TA1CCR1=5;
TA1CCR2=260;
break;
case 3: TA1CCR1=15;
TA1CCR2=220;
break;
case 4: TA1CCR1=20;
TA1CCR2=200;
break;
case 5: TA1CCR1=30;
TA1CCR2=150;
break;
case 6: TA1CCR1=40;
TA1CCR2=100;
break;
case 7: TA1CCR1=100;
TA1CCR2=80;
break;
case 8: TA1CCR1=120;
TA1CCR2=60;
break;
case 9: TA1CCR1=130;
TA1CCR2=30;
break;
case 10:TA1CCR1=160;
TA1CCR2=20;
break;
case 11:TA1CCR1=325;
TA1CCR2=0;
break;
default:
break;
}
}
}
#pragma vector=PORT1_VECTOR
__interrupt void P1_ISR(void) //P1口中断程序
{
P1IFG=0; //中断标志清零
int i;
for(i=0;i<1000;i++); //延时后判、消抖
if(P1IN&BIT3)
return;
else
a++;
if(a==12)
a=0;
}
例12.3本程序演示了定时器TIMER0_A在连续增量计数模式下,对TACCR0,TACCR1,TACCR2赋值,开中断,在中断程序中的判断和处理:分别点亮红LED(与P1.0相连)、绿LED(与P1.6相连),红绿LED同时熄灭,红绿LED同时点亮。并通过TACCR0,TACCR1,以及TACCR2的值来控制点亮的时间长短。
具体程序如下:
#include"MSP430G2553.H"
void main()
{
WDTCTL=WDTPW+WDTHOLD;
BCSCTL3|=LFXT1S_2; //选择 VLO 为低频时钟
P1DIR|=BIT6+BIT0;
P1OUT&=~(BIT6+BIT0);
TACTL|= MC_2+TASSEL_1; //设置TA连续增量计数至0xFFFF,选择ACLK,不分频
TACTL|=TAIE;
TACCTL0|=CCIE;
TACCTL1|=CCIE;
TACCTL2|=CCIE;
TACCR0=30000; //为TACCR0赋初值
TACCR1=10000; //为TACCR1赋初值
TACCR2=20000; //为TACCR2赋初值
_EINT();
LPM3; //低功耗至LPM3还可以运行。但选择LPM4时,系统不再运行,系统休眠的太深了。
}
//定时器A中断服务程序
#pragma vector=TIMER0_A1_VECTOR //G2553中有两个16位的定时器,分别为Timer0 A
__interrupt void Timer0_A1 (void) //和Timer1 A
{ //TIMER0_A1_VECTOR为CC1、CC2和TA0中断向量
switch(TAIV) //TIMER0_A0_VECTOR为CC0的中断向量
{
case 2:
P1OUT&=~(BIT6+BIT0);
P1OUT|=BIT0;//计数至TACCR1时,红色LED点亮
break;
case 4:
P1OUT&=~(BIT6+BIT0);
P1OUT|=BIT6;//计数至TACCR2时,绿色LED点亮
break;
case 10:
P1OUT&=~(BIT6+BIT0);
P1OUT|=BIT6+BIT0; //计数至0xFFFF时,红绿两个LED全点亮
break;
}
}
#pragma vector=TIMER0_A0_VECTOR //TIMER0_A0_VECTOR为CC0的中断向量
__interrupt void Timer0_A0 (void)
{
P1OUT&=~(BIT6+BIT0); //计数至TACCR0时,红绿两个LED全熄灭
}
通过上述的三个例程,可以大致知道有关定时器A的设置方法,定时器A进一步的设置和使用还需大家更深入的学习。在CCS中建立工程、把上述例程加入工程,调试、下载到开发板,运行后即可观察实验结果。在此基础上,还可以调整、改变对定时器A的设置,观察相应的运行结果。