目录
MSP430F5529的定时器有定时器A与定时器B,定时器B比定时器A强大一点。这里先只简单介绍定时器A,主要是教你使用库函数,详细资料请看用户手册,其他博客,视频教程。
定时器A可以硬件输出PWM,脉冲捕获,定时中断。本文只讲定时中断部分
定时器 A 是一个十六位的定时/计数器,MSP430F5529 中包含有 3 个定时器 A 的子模块 和 7 个捕捉/比较模块。定时器 A 支持多重捕获/比较,PWM 输出和内部定时。定时器还有 扩展中断功能,中断可以由定时器溢出产生或由捕获/比较寄存器产生。定时器 A 的特性包括:
四种运行模式的异步 16 位定时/计数器
可选择配置的时钟源
可配置的 PWM 输出
异步输入和输出锁存
对所有 TA 中断快速响应的中断向量寄存器
MSP430F5529定时器时钟 TACLK 可以选择 ACLK,SMCLK 或者来自外部的 TAxCLK。SMCLK系统默认 1048576Hz,ACLK系统默认为32768Hz。

看手册,我们知道有四中工作模式,第一个是停止状态,不计数,所以不讲。

此模式下,从0开始计数,可通过TAxCCR0的数值定义定时的周期。TAxCCR0数值小于0FFFFh。
一般用于软件PWM,定时中断。这个用到应该是最多的。
从0开始计数,直至计数到0FFFFh之后从0开始重新计数。与增计数模式不同的是,不能被提前结束,必须是从0计数到0FFFFh。定时周期只能由时钟源频率决定。
一般用于捕获脉冲。

从0开始计数,增加到TAxCCR0,再从TAxCCR0减少到0。

Timer_A有两个中断向量,CCIFG0中断和TAIV中断。后面会有介绍
- TIMERx_A0_VECTOR // CCR0 的中断向量
- TIMERx_A1_VECTOR // TAIV 的中断向量
void Timer_A_startCounter (uint16_t baseAddress, uint16_t timerMode);
指定定时器A中的3个子定时器,并且以指定方式开始计数。
baseAddress
- TIMER_A0_BASE
- TIMER_A1_BASE
- TIMER_A2_BASE
timerMode
- TIMER_A_STOP_MODE
- TIMER_A_UP_MODE //增计数模式
- TIMER_A_CONTINUOUS_MODE //连续计数模式
- TIMER_A_UPDOWN_MODE //增减计数模式
void Timer_A_initContinuousMode (uint16_t baseAddress,Timer_A_initContinuousModeParam ∗param)
配置指定的3个子定时器为增计数模式
baseAddress与上面一样
Param的值为如下
- (1)clockSource:选择时钟源
- TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK [Default]
- TIMER_A_CLOCKSOURCE_ACLK
- TIMER_A_CLOCKSOURCE_SMCLK
- TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLK
-
- (2)clockSourceDivider:选择时钟分频次数
- TIMER_A_CLOCKSOURCE_DIVIDER_1 [Default]
- TIMER_A_CLOCKSOURCE_DIVIDER_2
- TIMER_A_CLOCKSOURCE_DIVIDER_3
- TIMER_A_CLOCKSOURCE_DIVIDER_4
- TIMER_A_CLOCKSOURCE_DIVIDER_5
- TIMER_A_CLOCKSOURCE_DIVIDER_6
- TIMER_A_CLOCKSOURCE_DIVIDER_7
- TIMER_A_CLOCKSOURCE_DIVIDER_8
- TIMER_A_CLOCKSOURCE_DIVIDER_10
- TIMER_A_CLOCKSOURCE_DIVIDER_12
- TIMER_A_CLOCKSOURCE_DIVIDER_14
- TIMER_A_CLOCKSOURCE_DIVIDER_16
- TIMER_A_CLOCKSOURCE_DIVIDER_20
- TIMER_A_CLOCKSOURCE_DIVIDER_24
- TIMER_A_CLOCKSOURCE_DIVIDER_28
- TIMER_A_CLOCKSOURCE_DIVIDER_32
- TIMER_A_CLOCKSOURCE_DIVIDER_40
- TIMER_A_CLOCKSOURCE_DIVIDER_64
- TIMER_A_CLOCKSOURCE_DIVIDER_48
- TIMER_A_CLOCKSOURCE_DIVIDER_56
-
-
- (3)timerPeriod:指定的Timer_A时间段。这是写入的值进入CCR0。限制为16位[uint16_t]
-
- (4)timerInterruptEnable_TAIE:使能还是失能定时器中断
- TIMER_A_TAIE_INTERRUPT_ENABLE //使能定时器中断
- TIMER_A_TAIE_INTERRUPT_DISABLE //失能定时器中断
-
- (5)captureCompareInterruptEnable_CCR0_CCIE:选择中断响应
- TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE //CCR0中断
- TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE //TAIE中断
-
- (6)timerClear:选择是否把定时器的定时计数器,分频计数器的计数值清零
- TIMER_A_DO_CLEAR //清除
- TIMER_A_SKIP_CLEAR //不清除
-
- (7)startTimer:选择初始化之后是否立即启动定时器
- true //初始化后立即启动定时器
- false //初始化后不启动定时器
-
当定时器计数到CCR0的值的时候,置为标志位CCIFG。当定时器的值从CCR0计数到0的瞬间,置为TAIFG。

我们定时0.5s
首先我们选择SMCLK作为主时钟,32分频之后就是32750HZ,计数16375次数(写入值要-1)。
然后打开中断,最后两个设置与我一致即可,不用变化。
- void Timer_A_Init(void)
- {
- Timer_A_initUpModeParam htim = {0};
- htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //时钟源选为SMCLK = 1048576 HZ
- htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_32; //32分频 32768
- htim.timerPeriod = 16384 - 1; //计数值设为16374(32768/2=16374),定时0.5s
- htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE; //使能TALE中断
- htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;
- htim.timerClear = TIMER_A_DO_CLEAR; //把定时器的定时计数器,分频计数器的计数值清零
- htim.startTimer = true; //初始化后立即启动定时器
-
- //配置定时器A为增计数模式
- Timer_A_initUpMode(TIMER_A0_BASE, &htim);
- }
void Timer_A_initContinuousMode (uint16_t baseAddress,Timer_A_initContinuousModeParam ∗ param )
配置定时器A为连续计数模式
baseAddress与上面一样
与Timer_A_initUpModeParam相比,Timer_A_initContinuousModeParam 少了(3)timerPeriod,因为连续计数模式是从0到0FFFFh的,所以不需要配置周期。
也少了(5)captureCompareInterruptEnable_CCR0_CCIE,因为当定时值从FFFFh到0的瞬间,回设置TAIFG的标志位。所以他没有CCIFG0中断。

- Timer_A_initContinuousModeParam htim = {0};
- htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
- htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1;
- htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE;
- htim.timerClear = TIMER_A_DO_CLEAR;
- htim.startTimer = true;
- Timer_A_initContinuousMode(TIMER_A2_BASE, &htim);
- void Timer_A_initUpDownMode (uint16_t baseAddress,Timer_A_initUpDownModeParam ∗ param )
配置定时器A为增/减计数模式
baseAddress与上面一样
与Timer_A_initUpModeParam相比,Timer_A_initUpDownModeParam 一摸一样。
- Timer_A_initUpDownModeParam htim = {0};
- htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //时钟源选为SMCLK = 1.048MHz
- htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_32; //64分频 32750
- htim.timerPeriod = 16374 - 1; //计数值设为16374 - 1
- htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE; //使能TALE中断
- htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;
- htim.timerClear = TIMER_A_DO_CLEAR; //把定时器的定时计数器,分频计数器的计数值清零
- htim.startTimer = true; //初始化后立即启动定时器
-
- //配置定时器A为增计数模式
- Timer_A_initUpDownMode(TIMER_A0_BASE, &htim);
因为增计数模式最简单,且使用方便,所以我以下都使用增计数模式。连续计数模式是在后续捕获实验中讲解。增减模式这个我也想不到有啥应用场景,知道的可以在评论区评论。
实验为软件模拟实现PWM。周期为1S,占空比为50%
因为TALE的中断向量被公用,所以需要使用Switch语句,
- #include "driverlib.h"
-
- #define MCLK_IN_HZ 25000000
-
- #define delay_us(x) __delay_cycles((MCLK_IN_HZ/1000000*(x)))
- #define delay_ms(x) __delay_cycles((MCLK_IN_HZ/1000*(x)))
-
-
-
- void Timer_A_Init(void)
- {
- Timer_A_initUpModeParam htim = {0};
- htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //时钟源选为SMCLK = 1048576 HZ
- htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_32; //32分频 32768
- htim.timerPeriod = 16384 - 1; //计数值设为16374(32768/2=16374),定时0.5s
- htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE; //使能TALE中断
- htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;
- htim.timerClear = TIMER_A_DO_CLEAR; //把定时器的定时计数器,分频计数器的计数值清零
- htim.startTimer = true; //初始化后立即启动定时器
-
- //配置定时器A为增计数模式
- Timer_A_initUpMode(TIMER_A0_BASE, &htim);
- }
-
-
- void main (void)
- {
- //Stop WDT
- WDT_A_hold(WDT_A_BASE);
- //P4.1为输出
- GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN1);
- Timer_A_Init();
- //interrupts enabled
- __bis_SR_register(GIE);
- while(1)
- {
-
- }
- }
-
- #pragma vector=TIMER0_A1_VECTOR
- __interrupt
- void TIMER0_A1_ISR (void)
- {
- switch(TA0IV)
- {
- case TA0IV_NONE:
- break;
- case TA0IV_TACCR1:
- break;
- case TA0IV_TACCR2:
- break;
- case TA0IV_TACCR3:
- break;
- case TA0IV_TACCR4:
- break;
- case TA0IV_5:
- break;
- case TA0IV_6:
- break;
- case TA0IV_TAIFG:
- GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN1);
- break;
- default:
- break;
- }
- }
-
-
看注释掉的部分,就是要改的地方。
- #include "driverlib.h"
-
- #define MCLK_IN_HZ 25000000
-
- #define delay_us(x) __delay_cycles((MCLK_IN_HZ/1000000*(x)))
- #define delay_ms(x) __delay_cycles((MCLK_IN_HZ/1000*(x)))
-
-
-
- void Timer_A_Init(void)
- {
- Timer_A_initUpModeParam htim = {0};
- htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //时钟源选为SMCLK = 1048576 HZ
- htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_32; //32分频 32768
- htim.timerPeriod = 16384 - 1; //计数值设为16375(32768/2=16375),定时0.5s
- // htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE; //使能TALE中断
- // htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;
- htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE; //失能TALE中断
- htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE;
- htim.timerClear = TIMER_A_DO_CLEAR; //把定时器的定时计数器,分频计数器的计数值清零
- htim.startTimer = true; //初始化后立即启动定时器
-
- //配置定时器A为增计数模式
- Timer_A_initUpMode(TIMER_A0_BASE, &htim);
- }
-
-
- void main (void)
- {
- //Stop WDT
- WDT_A_hold(WDT_A_BASE);
- //P4.1为输出
- GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN1);
- Timer_A_Init();
- //interrupts enabled
- __bis_SR_register(GIE);
- while(1)
- {
-
- }
- }
-
- //#pragma vector=TIMER0_A1_VECTOR
- //__interrupt
- //void TIMER0_A1_ISR (void)
- //{
- // switch(TA0IV)
- // {
- // case TA0IV_NONE:
- // break;
- // case TA0IV_TACCR1:
- // break;
- // case TA0IV_TACCR2:
- // break;
- // case TA0IV_TACCR3:
- // break;
- // case TA0IV_TACCR4:
- // break;
- // case TA0IV_5:
- // break;
- // case TA0IV_6:
- // break;
- // case TA0IV_TAIFG:
- // GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN1);
- // break;
- // default:
- // break;
- // }
- //}
-
- #pragma vector=TIMER0_A0_VECTOR
- __interrupt
- void TIMER0_A0_ISR (void)
- {
- GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN1);
- }
