(三)定时器

一、MSP430单片机的定时器概述

MSP430共有4个16位定时器,主要包括定时器A的0、1、2以及定时器B,每个定时器输出通道个数不同。

时钟源包括ACLK、SMCLK和TACLK

二、定时器的工作模式

定时器主要包括4个工作模式:

① 停止模式

停止模式用于定时器暂停,并不发生复位,所有寄存器现行的内容在停止模式结束后都可用。当定时器暂停后重新计数时,计数器将从暂停时的值开始以暂停前的计数方向计数。例如,停止模式前,Timer_A定时器工作于增/减计数模式并且处于下降计数方向,停止模式后,Timer_A仍然工作于增/减计数模式下,从暂停前的状态开始继续沿着下降方向开始计数。若不想这样,则可通过TAxCTL中的TACLR控制位来清除定时器的计数及方向记忆特性。

② 增计数模式

比较寄存器TAxCCR0用作Timer_A增计数模式的周期寄存器。由于TAxCCR0为16位寄存器,所以在该模式下,定时器A连续计数值应小于0FFFFh。TAxCCR0的数值定义了定时的周期,计数器TAR可以增计数到TAxCCR0的值,当计数值与TAxCCR0的值相等(或定时器值大于TAxCCR0的值)时,定时器复位并从0开始重新计数。增计数模式下的计数过程如左图所示。
当定时器计数值计数到TAxCCR0时,置位CCR0中断标志位CCIFG。当定时器从TAxCCR0计数到0时,置位Timer_A中断标志位TAIFG。增计数模式下中断标志位设置过程如右图所示。

注意:该模式如果只用定时器的溢出中断,用CCR0中断和TAIV中断都差不多,只差了一个时钟周期。

③ 连续计数模式

在连续计数模式下,Timer_A定时器增计数到0FFFFh之后从0开始重新计数,如此往复。连续计数模式下的计数过程如左图所示。
当定时器计数值从0FFFFh计数到0时,置位Timer_A中断标志位,连续计数模式下的中断标志位设置过程如右图所示。
在这里插入图片描述

④ 增/减计数模式

需要对称波形的情况往往可以使用增/减计数模式。在该模式下,定时器先增计数到TAxCCR0的值,然后反方向减计数到0。计数周期仍由TAxCCR0定义,它是TAxCCR0值的2倍。增/减计数模式下的计数过程如左图所示。
在增/减计数模式下,TAxCCR0中断标志位CCIFG和Timer_A中断标志位TAIFG在一个周期内仅置位一次。当定时计数器增计数从TAxCCR0-1计数到TAxCCR0时,置位TAxCCR0中断标志位CCIFG,当定时计数器减计数从0001h到0000h时,置位Timer_A中断标志位TAIFG。增/减计数模式下中断标志位的设置过程如右图所示。

三、定时器的中断

每个16位定时器Timerx_A具有两个中断向量,分别如下:
捕获/比较寄存器TAxCCR0的中断向量CCIFG0
具有其余捕获/比较寄存器TAxCCRn的中断标志CCIFGn及溢出位TAIFG的中断向量TAIV

捕获模式下,当定时计数器TAR的值被捕获到TAxCCRn寄存器内时,置位相关的CCIFGn中断标志位。

比较模式下,当定时计数器TAR的值计数到TAxCCRn的值时,置位相关的CCIFGn中断标志位。
注意:捕获/比较只与CCIFGn有关,和定时计数溢出寄存器TAIFG无关

① TAxCCR0中断
TAxCCR0中断标志位CCIFG0在Timer_A中断中具有最高的中断优先级。
② TAIV中断
TAxIV中断主要包括TAxCCRn的中断标志CCIFGnTAIFG中断标志。

四、定时器A相关函数

(1)定时器A配置和控制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Timer_A_startCounter(uint16_t baseAddress, uint16_t timerMode)    
//定时器A开始计数

Timer_A_initUpMode(uint16_t baseAddress, Timer_A_initUpModeParam ∗param)
//配置定时器A为增计数模式

Timer_A_initUpDownMode(uint16_t baseAddress, Timer_A_initUpDownModeParam
∗param)
//配置定时器A为增/减计数模式

Timer_A_initContinuousMode(uint16_t baseAddress, Timer_A_initContinuousModeParam ∗param)
//配置定时器A为连续计数模式

Timer_A_initCaptureMode(uint16_t baseAddress, Timer_A_initCaptureModeParam ∗param)
//初始化为捕获模式。

Timer_A_initCompareMode(uint16_t baseAddress, Timer_A_initCompareModeParam ∗param)
//初始化为比较模式

Timer_A_clear(uint16_t baseAddress)
//复位/清除计时器时钟分频器,计数方向,计数值

Timer_A_stop(uint16_t baseAddress)
//停止计时器计时
(2)管理定时器A中断的相关函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Timer_A_enableInterrupt(uint16_t baseAddress)
//使能定时器中断

Timer_A_disableInterrupt(uint16_t baseAddress)
//禁用定时器中断

Timer_A_getInterruptStatus(uint16_t baseAddress)
//获取定时器中断状态

Timer_A_enableCaptureCompareInterrupt(uint16_t baseAddress, uint16_t
captureCompareRegister)
//启用捕获比较中断

Timer_A_disableCaptureCompareInterrupt(uint16_t baseAddress, uint16_t
captureCompareRegister)
//禁用捕获比较中断

Timer_A_getCaptureCompareInterruptStatus(uint16_t baseAddress, uint16_t
captureCompareRegister, uint16_t mask)
//返回捕获比较中断状态

Timer_A_clearCaptureCompareInterrupt(uint16_t baseAddress, uint16_t
captureCompareRegister)
//清除捕获比较中断标志

Timer_A_clearTimerInterrupt(uint16_t baseAddress)
//清除Timer TAIFG中断标志
(3)定时器A输出相关函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Timer_A_getSynchronizedCaptureCompareInput((uint16_t baseAddress, uint16_t
captureCompareRegister, uint16_t synchronized)
//获取同步的capturecompare输入

Timer_A_getOutputForOutputModeOutBitValue(uint16_t baseAddress, uint16_t
captureCompareRegister)
//为输出模式获取输出位

Timer_A_setOutputForOutputModeOutBitValue(uint16_t baseAddress, uint16_t
captureCompareRegister, uint8_t outputModeOutBitValue)
//为输出模式设置输出位

Timer_A_outputPWM(uint16_t baseAddress, Timer_A_outputPWMParam ∗param)
//计时器A运行在增计数模式产生PWM

Timer_A_getCaptureCompareCount(uint16_t baseAddress, uint16_t
captureCompareRegister)
//获取当前capturecompare计数值

Timer_A_setCompareValue(uint16_t baseAddress, uint16_t compareRegister, uint16_t
compareValue)
//设置捕获比较寄存器的值

Timer_A_getCounterValue(uint16_t baseAddress)
//读取当前计时器A计数值

五、相关实例

(1)定时器计数中断模式的初始化

中断频率 = 25MHZ/分频/htim.timerPeriod(CCR0寄存器的值)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void TIMA_2_Init(void)
{
Timer_A_initUpModeParam htim = {0};
htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;//SMCLK = 25MHZ
htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_64;
htim.timerPeriod = 240000 - 1;
htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE;
htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE;//使能CCR0中断
htim.timerClear = TIMER_A_DO_CLEAR; //把定时器的定时计数器,分频计数器的计数值清零
htim.startTimer = true; //初始化后立即启动定时器

/* 配置定时器A2为增计数模式 */
Timer_A_initUpMode(TIMER_A2_BASE, &htim);
}

(2)CCR0中断的代码

1
2
3
4
5
#pragma vector = TIMER0_A0_VECTOR
__interrupt void TIMA0_0_ISR (void)
{
// GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);
}

(3)TAIV中断的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIMA0_1_ISR (void)
{
switch(TA0IV)/* 中断向量寄存器 */
{
case TA0IV_TAIFG: /* 定时器溢出中断 */
{
//GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN7);
Timer_A_clearTimerInterrupt(TIMER_A0_BASE);//清除TAIFG中断标志
break;
}
case TA0IV_NONE: /* 无中断挂起 */
break;
case TA0IV_TACCR1:/* 捕获比较1 */
break;
case TA0IV_TACCR2:/* 捕获比较2 */
break;
case TA0IV_TA0CCR3:/* 捕获比较3 */
break;
case TA0IV_TA0CCR4:/* 捕获比较4 */
break;
case TA0IV_5: /* 捕获比较5 */
break;
case TA0IV_6: /* 捕获比较6 */
break;
default:
break;
}
}

TAxIFG要和你选的定时器对应

(4)PWM输出初始化配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
void TIMA_0_PWM_Init(void)
{
//复用P1.2、P1.3、P1.4、P1.5输出
GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5);

Timer_A_initUpModeParam htim = {0};
htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_4;
htim.timerPeriod = 625 - 1;//10KHZ
htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;
htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;
htim.timerClear = TIMER_A_DO_CLEAR;
htim.startTimer = true;
Timer_A_initUpMode(TIMER_A0_BASE, &htim);

/* 配置为 比较 模式 */
Timer_A_initCompareModeParam htim_PWM = {0};
htim_PWM.compareInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE;
htim_PWM.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;

htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;
htim_PWM.compareValue = (int)(625 * 0.2);//初始占空比
//Initialize compare mode to generate PWM1
Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);

htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2;
htim_PWM.compareValue = (int)(625 * 0.4);
//Initialize compare mode to generate PWM2
Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);

htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_3;
htim_PWM.compareValue = (int)(625 * 0.6);
//Initialize compare mode to generate PWM3
Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);

htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_4;
htim_PWM.compareValue = (int)(625 * 0.8);
//Initialize compare mode to generate PWM4
Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);

}

定时器可以同时配置PWM输出(比较模式)以及计数中断

(5)改变占空比

1
2
3
4
5
Timer_A_setCompareValue(
TIMER_A0_BASE,
TIMER_A_CAPTURECOMPARE_REGISTER_1,//通道
i*625/10//占空比
);

占空比与输出电压成正比