TI杯 电赛总结 MSP430F5529LP 定时器计时 流水灯 寄存器操作
软件:CCS12.4.0
开发板:MSP-EXP430F5529LP
参考视频:传送门
概念解释
定时器计时的基本原理:计数器从装载值自增或自减至比较值或溢出值,自增自减的时间步长由时钟源与分频系数共同决定。时钟每产生一个脉冲,计数器就进行自增或自减计数,计数值为比较值或溢出时进入中断。
第一个寄存器TAxCTL(用于配置定时器的基本参数)
所有位复位值为0
Reserved:保留字
TASSEL:时钟源选择位
ACLK:32.768k Hz
SMCLK:1M Hz
ID:时钟分频系数位
MC:计数模式选择位
Stop:定时器停止工作
Up:计数器从TAxR(默认为0)开始一直自增至TAxCCR0,然后自动清0并产生中断
Continuous:计数器从TAxR(默认为0)开始一直自增至0xFFFF(65535),然后自动清0并产生溢出中断
TACLR:设置此位将清除TAR、时钟分频器逻辑(分频器设置保持不变)和计数方向。(官方解释)
TAIE:中断使能位,用于开启和关闭定时器的溢出中断请求
第二个寄存器TAxEX0
分频拓展,配合第一个寄存器中的ID位来用,用于分频
第三个寄存器TAxR
用于设置计数器开始计数时的装载值
第四个寄存器TAxCCRn
在比较模式下,用于设置定时器各通道(x = 0,1,2,3,4,5,6)的比较值,当计数器的值达到比较值时,对应通道会产生中断,不同定时器的通道数不同,具体需查阅手册。
第五个寄存器TAxCCTLn
用于使能定时器各通道(x = 0,1,2,3,4,5,6)的中断
代码
板载资源:LED(P1.0),TimerA0
所有方式的效果都是使LED的电平每0.5s反转一次,仅涉及到定时器相关的代码,LED需自己配置。
每个方式都大同小异,灵活运用,只要能满足最终的需求就好。
相关参数解释:

介绍两个中断函数:
中断函数的函数名可以任意起,不像32一样必须是固定的,但尽量标准易懂。
// 定时器比较通道0的中断函数(特殊)
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
//进入中断需执行的内容
}
// 定时器其它比较通道及溢出时的中断函数
#pragma vector = TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
{
switch (__even_in_range(TA0IV, 14))
{
case 0: break; //无中断
case 2: break; //CCR1中断
case 4: break; //CCR2中断
case 6: break; //CCR3中断
case 8: break; //CCR4中断
case 10: break; //CCR5中断
case 12: break; //CCR6中断
case 14: break; //溢出中断
default: break;
}
}
方式一
//SMCLK 不分频 目标值
void TimerA_Init(void)
{
//SMCLK,增计数模式,清除TAR
TA0CTL = TASSEL__SMCLK + MC__UP + TACLR;
//设置目标计数值
TA0CCR0 = 50000;
//使能CCR0中断
TA0CCTL0 = CCIE;
//开启全局中断
_EINT();
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
static uint8_t cnt_50ms;
cnt_50ms++;
if (cnt_50ms>=10)
{
P1OUT ^= BIT0; //电平反转
cnt_50ms = 0;
}
}
脉冲频率 = 1M Hz
每过1us,计数器加1,计数器值为50000时产生中断,时间为50ms(1us * 50000),即每50ms进入一次中断函数,中断内设置静态局部变量——cnt_50ms,此变量用于标志产生中断的次数,次数为10时时间为500ms,执行相应的语句,最后需将标志清0
前面提到TACLR,其作用为每次中断时,计数器自动清0,如果不设置此位,计数器将一直自增至65535,最终溢出产生中断,然后清0
方式二
//SMCLK 10分频 目标值
void TimerA_Init(void)
{
//SMCLK,增计数模式,清除TAR
TA0CTL = TASSEL__SMCLK + ID__2 + MC__UP + TACLR;
TA0EX0 = TAIDEX_4; //Timer A Input divider expansion : /5
//设置目标计数值
TA0CCR0 = 50000;
//使能CCR0中断
TA0CCTL0 = CCIE;
//开启全局中断
_EINT();
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
P1OUT ^= BIT0;
}
脉冲频率 = 1M / 2(ID__2) / 5(TAIDEX_4) = 100k Hz
每过10us,计数器加1,计数器值为50000时产生中断,时间恰好为500ms。
方式三
//ACLK 不分频 目标值
void TimerA_Init(void)
{
//选择ACLK,增计数模式,清除TAR
TA0CTL = TASSEL__ACLK + MC__UP + TACLR;
//设置目标计数值
TA0CCR0 = 16384;
//使能CCR0中断
TA0CCTL0 = CCIE;
//开启全局中断
_EINT();
}
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
P1OUT ^= BIT0;
}
脉冲频率 = 32768 Hz
每过1/32768s,计数器加1,计数器值为16384时产生中断,时间恰好为500ms。
方式四
//ACLK 不分频 目标值
void TimerA_Init(void)
{
//选择ACLK,增计数模式,清除TAR
TA0CTL = TASSEL__ACLK + MC_1 + TAIE + TACLR;
//设置目标计数值
TA0CCR0 = 16384;
//开启全局中断
_EINT();
}
#pragma vector = TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
{
switch (__even_in_range(TA0IV, 14))
{
case 0: break; //无中断
case 2: break; //CCR1中断
case 4: break; //CCR2中断
case 6: break; //CCR3中断
case 8: break; //CCR4中断
case 10: break; //CCR5中断
case 12: break; //CCR6中断
case 14: //溢出中断
P1OUT ^= BIT0;
break;
default: break;
}
}
脉冲频率 = 32768 Hz
每过1/32768s,计数器加1,计数器值为16384时计数器清0会产生一个溢出中断,此时时间恰好为500ms。
方式五
//ACLK 不分频 无目标值
void TimerA_Init(void)
{
//选择ACLK,连续计数模式,不清除TAR
TA0CTL = TASSEL__ACLK + MC__CONTINUOUS + TAIE;
//设置开始的计数值
TA0R = 65535 - 16384; // 16384/32768 = 0.5s
//开启全局中断
_EINT();
}
#pragma vector = TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
{
switch (__even_in_range(TA0IV, 14))
{
case 0: break; //无中断
case 2: break; //CCR1中断
case 4: break; //CCR2中断
case 6: break; //CCR3中断
case 8: break; //CCR4中断
case 10: break; //CCR5中断
case 12: break; //CCR6中断
case 14: //溢出中断
P1OUT ^= BIT0;
TA0R = 65535 - 16384;
break;
default: break;
}
}
脉冲频率 = 32768 Hz
计数器从49151(65535 – 16384)开始,每过1/32768s,计数器加1,计数器值为65535时计数器溢出产生中断,此时时间恰好为500ms。在CONTINUOUS计数模式下,需手动重装TA0R的值,否则计数器将一直自增至65535后才会清0。
中断函数中需要将计数器的值重装载为49151
方式六
//ACLK 不分频 目标值
void TimerA_Init(void)
{
//选择ACLK,连续计数模式,清除TAR
TA0CTL = TASSEL__ACLK + MC__CONTINUOUS + TACLR;
//设置目标计数值
TA0CCR1 = 16384;
//使能CCR1中断
TA0CCTL1 = CCIE;
//开启全局中断
_EINT();
}
#pragma vector = TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
{
switch (__even_in_range(TA0IV, 14))
{
case 0: //无中断
break;
case 2: //CCR1中断
P1OUT ^= BIT0;
TA0R = 0;
break;
case 4: //CCR2中断
break;
case 6: //CCR3中断
break;
case 8: //CCR4中断
break;
case 10: //CCR5中断
break;
case 12: //CCR6中断
break;
case 14: //溢出中断
break;
default:
break;
}
}
脉冲频率 = 32768 Hz
每过1/32768s,计数器加1,计数器值为16384时,通道1会产生一个比较中断,此时时间恰好为500ms。因为选择的定时器模式为CONTINUOUS计数,在中断函数中需手动清空TA0R,否则计数器将继续自增至0xFFFF后才会清0。
此方式类似于pwm,调节TA0CCR1的值可以改变占空比,不推荐这样模拟pwm,定时器有专门的pwm输出模式。
作者:学习不爱我_!