本节我们讲述定时器的应用,在使用定时器前补充一点关于MSP430.H头文件自带的延时函数的知识,该头文件自带__delay_cycles(x);的延时函数,根据官方信息说延时时间是一个周期,内部可以放入常量和表达式,根据其特性我们可以运用其设计较为准确的US,MS级延时函数,操作方法为将以下函数段放入头文件之下宏定义即可在后续程序中调用。
#define CPU_F ((double)8000000)//CPU_F 为系统主时钟频率
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))//微秒
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))//毫秒
对应寄存器简述
在使用定时器之前我们首先要了解MSP430F5529片内片外的是时钟源,MSP430有4个时钟源,它们分别为TAxCLK,ACLK,SMCLK,INCLK(分别用TASSEL_0-TASSEL_3表示)。另外430的是时钟源支持二,四,八分频, 同时支持三种计数模式,分别为:
00 不分频 01 二分频 10 四分频 11八分频
01:从0计数至TAxCCR0 10:从0计数至0XFFFF 11:从TAxCCR0计数至0
寄存器其余位分别为为TACLR清零计数器,TAIE中断使能,TAIFG中断标志位。TA0CCRn为放置捕获数值和比较数值的寄存器。对应此寄存器对定时器进行基本的初始化配置为:
TA0CCTL0=CCIE;//CCR0中断使能
TA0CCR0=16;//中断计数值
TA0CTL=TASSEL_2+MC_1+ID_3+TACLR+TAIE;//SMCLK+增计数模式+不分频+清零计数器+使能中断
_BIS_SR(GIE);//将GIE位清零
以上函数为配置定时器A的代码,同理配置定时器B的代码也是以这种模式,同时TA0CTL内可以缩略为TASSEL_2+MC_1(选择时钟源和计数模式),其余配置在需要时再进行设置。
中断服务函数
对应定时器的操作最常用的即为定时器中断的使用,对应的也有定时器中断服务函数的书写,在MSP430中定时器中断服务函数和外部中断服务函数的书写方式近似:
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR(void)
{
//函数内容
}
在使用过程中,还可以在进入中断后加入“TA0CTL &= ~TAIFG;//清除标志位”语句清楚中断标志位
输出模式
输出模式由 OUTMOD 位定义,TA0CCTLx寄存器的共有7中输出模式,对于除模式 0 以外的所有模式,OUTn 信号随定时器时钟的上升沿而改变。 输出模式 2、3、6 和 7对输出模式 0 没有用,因为 EQUn=EQU0。
OUTMODx | 模式 | 描述 |
000 | OUTPUT | 输出信号OUTn 由OUT 位定义。OUTn 信号在OUT 更新时立即更新。 |
001 | SET | 当定时器计数到 TAxCCRn 值时设置输出。它保持设置直到定时器复位,或直到选择另一种输出模式并影响输出。 |
010 | Toggle/Reset | 当定时器计数到 TAxCCRn 值时输出切换。当定时器计数到 TAxCCR0 值时复位。 |
011 | Set/Reset | 当定时器计数到 TAxCCRn 值时设置输出。当定时器计数到 TAxCCRO 值时复位。 |
100 | Toggled | 当定时器计数到 TAxCCRn 值时,输出切换。输出周期是定时器周期的两倍。 |
101 | Reset | 当定时器计数到 TAxCCRn 值时,输出复位。它保持复位直到|选择了另一种输出模式并影响输出。 |
110 | Toggle/Set | 当定时器计数到 TAxCCRn 值时,输出被切换。当定时器计数到 TAxCCR0 值时设置。 |
111 | Reset/set | 当定时器计数到 TAxCCRn 值时输出复位。当定时器计数到 TAxCCRO 值时设置。 |
单定时器多通道
我们可以使用单个定时器产生多个通道的中断输出,例如:
#include <msp430.h>
void main(void)
{
WDTCTL = WDTPW |WDTHOLD; // Stop WDT
P1DIR =0x0C; // P1.0 output
P1SEL=0x0C;
TA0CCR0= 65534;
TA0CCR1 = 25000; //1sec (0.5+0.5)
TA0CCR2 = 64000; //
TA0CCTL1 = OUTMOD_7; // CCR0 interrupt enabled
TA0CCTL2 = OUTMOD_7; // CCR0 interrupt enabled
TA0CTL = TASSEL_2 + MC_3+ID_3+TAIE+TACLR; // SMCLK, countmode
_BIS_SR(LPM0_bits+GIE); // Enter LPM0 w/ interrupt
}
多定时器同时计数
以下为timer_A,timer_B同时工作的配置方式,通过同时对定时器A和定时器B的配置可以实现对两个定时器的同时计数:
TA0CCTL0=CCIE;
TA0CCR0 =1000-1;
TA0CTL = TASSEL_2 + MC_1; // SMCLK, contmode
TB0CCTL0 = CCIE; // CCR0 interrupt enabled
TB0CCR0 = 2000-1;
TB0CTL = TBSSEL_2 + MC_1; // SMCLK, contmode
同时对两个计数器分别写入对应的中断服务函数,通过其来实现不同的应用效果:
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0 (void)
{
x++;
if(x>1000)
{
P1OUT ^= 0x01;
x=0;
}
}
#pragma vector=TIMER0_B0_VECTOR
__interrupt void Timer_B0 (void)
{
y++;
if(y>1500)
{
P4OUT ^= 0x80;
y=0;
}
}
多源中断
中断服务函数的中断矢量(TIMER0_A1_VECTOR)以及本征函数(__even_in_range(TA0IV,14)) 对应TAxCCRx的不同中断标志位,通过对其进行判断可以设置不同中断的不同功能。
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIMER0_A1_ISR(void)
{
switch(__even_in_range(TA0IV,14))
// __even_in_range()本征函数,用于多源中断的查询。
{
case 0 : break; // No interrupt
case 2 : P1OUT ^= BIT0; break; // CCR1 used
case 4 : break; // CCR2 not used
case 6 : break; // reserved
case 8 : break; // reserved
case 10: break; // reserved
case 12: break; // reserved
case 14: P4OUT ^= BIT1;break; // TAIFG
default: break;
}
}
PWM波的输出
PWM作为定时器的一个使用方式在我们学习51单片机时就早有了解,那时我们便为自己成功实现电机调速等欣喜,在单片机微控制芯片的使用中免不了会遇到电机调速,调光,舵机转动等使用情况,这里我们便要使用到PWM波进行调控,即在一定周期内设定高低电平的时长,通过改变时长来实现调速的效果。接下来我们简单用timer_A实现简单的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,复位且高电平置位模式。
TA0CTL = TASSEL_2 + MC_1 +ID_1+TAIE;// SMCLK,向上计数模式,二分频 触发中断
_BIS_SR(LGIE);
}
#pragma vector= TIMER0_A1_VECTOR
__interrupt void timer(void)
{
TA0CTL &= ~TAIFG; //清楚标志位
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;
}
}
以上是我对MSP430定时器的粗浅认识,后续如有加深理解会继续优化,也欢迎大家批评指正。