定时器常见的代码解析(CCS)
MSP430F5529中有着A,B,D三种定时器,与平时接触的8位单片机不同,在定时器A能够支持PWM输出、中断捕获比较等功能
上图就为定时器的时钟选择,有三种时钟源选择,分别为SMLCK,ACLK,INCLK,如果需要获得较高频率的定时时间,一般选择主时钟SMCLK较好。
TASSELx为该时钟选择哪个时钟源,并且在ID选择多少分频,随后选择MC哪种定时器的模式开始计数。而其CCRx则可以理解为该定时时间所存储的实际时间数。
以下为所示的代码。使用了定时器TA,并且使用了定时器模式3,定时器中断来完成PWM自加。
#include <msp430f5529.h>
int i = 0,d=0;
void main(void)
{ WDTCTL = WDTPW|WDTHOLD;
P1DIR |= BIT2;//设置P1.2为输出模式
P1SEL |= BIT2;//设置其IO口为特殊IO口
TA0CCR0 = 16; // 设置好PWM的总周期
TA0CCR1 = 0; // PWM的工作周期
TA0CCTL1 = OUTMOD_3; // TA0CCR1为模式3,为复位且高电平置位模式。输出为TAxR(计数寄存器)=TAxCCRn时,输出置位,输出为TAxR = TAxCCR0时,输出复位
TA0CTL = TASSEL_2 + MC_1 +ID_1+TAIE;// 时钟源选择了SMCLK,并且模式1为MC_1为向上计数模式。Timer A control set to SMCLK, 1MHz and count up mode MC_1 ID_1为二分频 TAIE为触发中断 d选择SMCLK 为1Mhz 如果频率想低点可以选择频率较低的是时钟,辅助时钟ACLK
_bis_SR_register(LPM0_bits + GIE); // 开启低功耗模式0
}
#pragma vector= TIMER0_A1_VECTOR
__interrupt void timer(void)
{
TA0CTL &= ~TAIFG; //先将全部的IFG先置零,让标志位回0
if(d==0)
{
if(i<16 )
TA0CCR1=++i;//让其定时每到一个中断就自加1,以此类推使得PWM逐步上升。
else
d=1;
}
else if(d==1)
{
if(i>1)
TA0CCR1=--i;
else
d=0;
}
}
TA定时器相关寄存器介绍
TA0CTL寄存器
BITS | Field | Description |
---|---|---|
9-8 | TASSEL | Timer_A0时钟源选择:00b =TAxCLK,01b=ACLK,10b=SMCLK,11b=INCLK |
7-6 | ID | 时钟分频,00=不分频,01=二分频,10b=四分频,11b=八分频 |
5-4 | MC | 计数模式选择,01b=计数至TAxCCR0,10b=计数至0xFFFF,11b = 计数到TAxCCR0再减回到0 |
2 | TACLR | 清零计数器 |
1 | TAIE | TA中断使能 |
0 | TAIFG | TA中断标志位 |
注意在TA定时器上,还有着捕获比较寄存器,TAxCCTLx(x=1,2…,6).
TA0CCTLn
BITS | Field | Description |
---|---|---|
15-14 | CM | 捕获模式选择 |
13-12 | CCIS | 选择TAxCCR0输入的通道 |
8 | CAP | 选择捕获或者比较模式 (0:捕获,1:比较) |
7-5 | OUTMOD | 输出模式 |
4 | CCIE | 捕获比较中断的使能 |
2 | OUT | 要看OUTMOD是否选择模式0,才能进行对这个位操作 |
0 | CCIFG | 捕获比较中断标志位 |
该寄存器实质上是用来设置TA定时器的一些捕获和比较的常用,可以用来实时监测定时器的值,或者
和ADC12一起使用。详情使用可以看上面的例子。
TA0CCRn
该定时器为存放定时器相关的值。
BITS | Field | Description |
---|---|---|
15-0 | TAxCCR0 | 用来存放相关捕获和比较的值以供用户使用 |
TAxIE
该寄存器为中断矢量寄存器,用操作捕获以及比较的值的一个中断寄存器。各个对应的值如下图代码所示
中断服务函数的中断矢量(TIMER0_A1_VECTOR)以及本征函数(__even_in_range(TA0IV,14))的运用
BITS | Field | Description |
---|---|---|
15-0 | TAIV | 对应TAxCCRx的不同中断标志位 |
相关代码如下:
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
{
switch(__even_in_range(TA0IV,14))//中断查询
{
//注意优先级,标号最低的优先级最高
//可以加相关的中断操作,相当于查询中断并且操作
case 0:break;//No interrupt
case 2:break;//TAxCCR1 CCIFG
case 4:break;//TAxCCR2 CCIFG
case 6:break;//TAxCCR3 CCIFG
case 8:break;//TAxCCR4 CCIFG
case 10:break;//TAxCCR5 CCIFG
case 12:break;//TAxCCR6 CCIFG
case 14:break;//TAxCTL TAIFG
default :break;
}
}
至此,简单的定时器TA已经可以实现绝大多数的功能了,在实际运用中,如电赛中,应该要更好的设置
其模式以及初值,以达到适合的频率周期。