MSP430 定时器AWord格式.docx
《MSP430 定时器AWord格式.docx》由会员分享,可在线阅读,更多相关《MSP430 定时器AWord格式.docx(17页珍藏版)》请在冰豆网上搜索。
14
13
12
11
10
9
8
-
TASSEL1
TASSEL0
7
6
5
4
3
2
1
ID1
ID0
MC1
MC0
TACLR
TAIE
TAIFG
TA0CTL(也可以写TACTL)负责设置TimerA的时钟来源、分频系数、计数模式、复位信号以及相关的中断允许和中断标志位:
9~8-TASSEL:
用来设置TimerA的时钟来源
0:
TACLK?
1:
ACLK?
2:
SMCLK?
3:
INCLK
7~6-ID:
用来设置输入时钟信号经过多少分频驱动TAR?
分频系数=2ID?
5~4-MC:
用来设置TimerA的计数模式
停止模式?
增模式?
连续模式?
增减模式
TACLR:
TimerA清零位,该位置位会复位TAR,时钟分频和计数方向,完成后TACLR自动清零
TAIE:
TimerA中断允许位,用来允许TAIFG中断请求
中断禁止1:
中断允许
TAIFG:
TimerA中断标志位?
无中断挂起?
有中断挂起
2、TA0R:
TimerA寄存器
TA0R?
X
TA0R(也可以写TAR)是一个用来存放当前计数值的一个16位的寄存器,类似于51的TH0和TL0的合体。
3、TA0CCRx:
TimerA捕获比较寄存器x
TA0CCRx?
TA0CCRx(也可以写TACCRx)是一个用来存放定时计数器捕获值的16位寄存器,在MSP430G2553中x可以是0、1、2,对应相应的TA0CCTLx。
另外TA0CCR0还可以用来设置TimerA计数模式中增模式和增减模式的峰值,详细后面将会讲。
4、TA0CCTLx:
TimerA捕获比较控制寄存器x
TimerA比较控制寄存器x
CM1
CM0
CCIS1
CCIS0
SCS
SCCI
CAP
OUTMODE2
OUTMODE1
OUTMOD0
CCIE
CCI
OUT
COV
CCIFG
TA0CCTLx(也可以写TACCTLx),在MSP430G2553中x可以是0、1、2(其他型号单片机可能有更多的支持,详细看相关数据手册),对应相应的TA0CCRx,TA0CCTLx定义了很多TimerA捕获比较控制控制相关的位,让我们来一一学习:
15~14-CM:
捕获模式控制寄存器
不捕获?
1上升沿捕获?
下降沿捕获?
上升和下降沿都捕获
13~12-CCIS:
捕获比较选择,该位选择TA0CCRx的输入信号,
11-SCS:
同步捕获源,该位用于将捕获通信和时钟同步?
异步捕获?
同步捕获
10-SCCI:
同步的捕获/比较输入,所选择的CCI输入信号由EQUx信号锁存,并可通过该位读取
8-CAP:
比较/捕获模式选择?
比较模式?
捕获模式
7~5-OUTMODE:
输出模式位,由于在模式2、3、6、7下EAQUx=EQU0,因此这些模式对TA0CCRx无效
OUT位的值?
置位?
翻转/复位?
置位/复位
4:
翻转?
5:
复位?
6:
翻转/置位?
7:
复位/置位
4-CCIE:
捕获比较中断允许位,该位允许相应的CCIFG标志请求
中断禁止?
3-CCI:
捕获比较输入,所选择的输入信号可以通过该位读取
2-OUT:
输出状态位,对于输出模式0,该位直接接控制输出状态
输出低电平?
输出高电平
1-COV:
捕获溢出位,该位表示一个捕获溢出发生。
COV必须由软件复位
没有捕获溢出发生?
有捕获溢出发生
0-CCIFG:
捕获比较中断标志位?
没有中断挂起?
三、Timer的四种计数模式
下面让我们来看一下TimerA的4种计数模式,这也是后面TimerA计数和捕获/比较的基础:
1、MC=0:
Stop(停止模式),这个模式下TimerA停止计数;
2、MC=1:
Up(增模式),在这个模式下,TimerA的TAR会自动从0开始一直计数至TA0CCR0,并不断重复计数,注意,此时的TA0CCR0比较特殊,将不作为捕获/比较的作用,和TA0CCR1、TA0CCR2起不同作用。
如果在设置增模式时TAR值比TACCR0大,那么TAR会立刻重新从0开始计数,其波形如图所示:
在增模式下,TACCR0?
CCIFG中断标志将在TAR计数至TACCR0时被置1。
TAIFG中断标志将在TAR从TACCR0跳至0时被置1,下图描述了这两个标志位的置位时序:
对于如何理解TAIFG和CCIFG何时置位问题,这里Cloud的解读是,TAIFG是在TAR归零的时候置1的,而CCIFG是在TAR计数至TA0CCR0时置1的。
另外,当TA0CCR0在TimerA运行过程中发生改变时(Timer工作在增模式下),如果新的TA0CCR0的值比当前TAR计数的值要大,则TAR继续向上计数至新的TA0CCR0,反之,TAR将立即归零;
3、MC=2:
Continuous(连续模式),在这个模式下,TimerA的TAR会自动从0开始计数至0xFFFF然后归零,并不断重复计数。
此时的TA0CCR0将和TA0CCR1、TA0CCR2一样起到捕获/比较的作用。
连续模式下的TAR计数波形如下图所示:
在连续模式下,TAIFG中断标志将在TAR从0xFFFF溢出至0的时候置1,如下图(由于这里没有专门用到TA0CCR0所以就不关心CCIFG,这里同样符合我们前面对中断标志置位问题的分析):
官方手册还对连续模式的应用作了介绍:
连续模式可以用于产生独立的时间间隔和输出频率。
当每个时间间隔完成时就产生一个中断。
下一个时间间隔的值在进入中断服务子程序时写入TA0CCRx。
下图显示了2个独立的而时间间隔t0和t1写入捕获/比较寄存器。
在该应用中,时间间隔由硬件而不是软件控制,与中断响应没有冲突:
这里,稍微解释一下上面的图,锯齿波是TAR产生的,从0增至0xFFFF单调循环。
TACCR0a和TACCR1a分别是两个捕获/比较寄存器的值(初始值),为了产生t0和t1两个时间间隔,我们可以让中断响应我们的CCIFGx中断响应(因为CCIFGx是和TA0CCRx相关联的)。
这里例子的做法是在每次由于CCIFGx中断响应的时候,相应的将TACCRx加上tx(比如TACCR0a?
+?
t0得到TACCR0b),然后TAR继续计数(不管是否退出中断),然后计数到下一个周期的时候自然又产生的TA0CCRx的CCIFGx中断,由此我们得到了连续时间间隔;
4、MC=3:
Up/Down(增减模式),在这个模式下,TimerA的TAR会自动从0开始计数至TA0CCR0然后从TA0CCR0-1自动减至0,并不断重复计数(可以看出,此时TA0CCR0又作为了周期寄存器来使用而不是捕获/比较寄存器)。
其周期是TA0CCR0值的2倍。
下面的图描述了这一过程:
该模式下,计数方向是固定的,即让定时器停止后再重新启动定时器,它就沿着停止时的计数方向和数值开始计数。
如果不希望这样,可以将TA0CLR置位来清除方向(同时也会清除TAR的值和定时器的时钟分频)。
在增减模式,在TA0CCR0中,CCIFG中断标志和TAIFG中断标志在一个周期中只能置位一次,由1/2定时器周期隔开。
当定时器计数到由TA0CCR0—1变到TA0CCR0时,CCIFG置位;
而定时器完成减计数从0x0001到0x0000时,TAIFG置位(依然和我们前面的分析一致),下图描述了这个过程:
当定时器运行时,改变TA0CCR0的值,如果正处于减计数的情况,定时器会继续减到0,新的周期在减到0后开始。
如果正处于增计数状态,新周期大于等于原来的二周期,或比当前计数值要大,定时器会增计数到新的周期。
反之,定时器立刻开始减计数,但是,在定时器开始减计数之前会多计一个数。
同样的,官方数据手册也给出了一个增减模式的使用例子:
增减模式支持在输出信号之间有死时间的应用。
例如,避免出现过载情况,2个输出驱动一个H桥不能同时为高电平。
下图显示了这个过程:
这里的Output?
Mode?
6、2在后面将会讲到其输出波形特性,现在大家只要知道这些波形都是可以通过我们的IO口输出来的(想起IO那篇IO具有第二功能的特性了么?
)。
其中Tdead?
=?
ttimer?
*?
(TACCR1?
-?
TACCR2)
Tdead—同时输出时必须没有反应的时间段
Ttimer—定时器时钟周期
TACCRx—捕获比较寄存器x的内容
TACCRx寄存器并不是缓冲,写入时立即更新,因此,任何所要求的死去时间不会自动保留。
由于上面的例子使用了TimerA的比较捕获模块,这里我们还没有讲到,大家如果暂时理解不了这个例子可以跳过它继续往后面学习,等到学习完比较捕获模块再回过头来看这个例子。
五、Timer的捕获比较/模块
前面我们已经讲完了定时器的4种计数模式以及每种技术模式中TAR的计数特点和相关中断标志位的置位时序,另外还初步学习了相关的应用。
下面我们来一起学习下一个重要内容,捕获/比较模块:
TimerA中有3个相同的捕获比较模块TA0CCRx,其中的任何一个模块可以用于定时器数据的捕获或时间间隔。
①捕获模块:
(以下内容可以配合定时器内部结构图来学习分析)
当CAP=1时,选择捕获模式。
捕获模式用于记录时间事件,比如速度估计或时间测量。
捕获输入CCIXA和CCIXB连接外部的引脚或内部的信号,这通过CCIS来选择。
CM选择捕获输入信号触发沿:
上升沿、下降沿或者两者都捕获。
捕获事件发生于所选择的的输入信号的触发沿。
如果发生了捕获事件:
定时器TAR的值复制到TA0CCRx寄存器中
中断标志位CCIFG置位
内部信号可以在任一时间通过CCI位来读取捕获信号可能会和定时器时钟不同步,并导致竞争条件(这是数电用语)的发生。
将SCS置1可以在下个定时器时钟使捕获同步,下图描述了这个过程:
如果一个第二次捕获动作在第一次捕获的值被读取之前发生,捕获比较寄存器就会产生一个溢出逻辑,COV此时将置1,COV必须由软件清除,下图描述了捕获循环:
通过软件初始化捕获
捕获可以由软件初始化。
CM可以配置捕获的触发沿。
CCIS1=1和CCIS0可以捕获电压在Vcc和GND之间的信号。
②比较模块:
CAP=0时选择比较模式。
比较模式用于选择PWM输出信号或在特定的时间间隔中断。
当TAR计数到TACCRx的值时:
中断标志CCIFG置位
内部信号EQUx=1
EQUx根据输出模式来影响输出信号
输入信号CCI锁存到SCCI
每个捕获比较模块(分别用各自的TA0CCRx来配置)包含一个输出单元。
输出单元用于产生如PWM这样的信号。
每个输出单元可以根据EQU0和EQUx产生8中模式的信号。
输出模式:
输出模式由OUTMOD来确定,如下表。
对于所有模式来说(模式0除外),OUTx信号随着定时器时钟的上升沿而改变。
输出模式2、3、6、7对输出单元0无效,因为在这些模式下,EQUx=EQU0:
OUTMODx
模式
说明
二进制
十进制
000
输出
输出信号OUTx由OUTx位定义。
当OUTx位更新时,OUTx信号立刻更新
001
置位
当计时器计数到TA0CCRx值时,输出置位,并保持置位直到定时器复位或选择了另一个输出模式
010
翻转/复位
当定时器计数到TA0CCRx值时,输出翻转。
当定时器计数到TA0CCR0值时,输出复位
011
当定时器计数到TA0CCRx值时,输出置位。
100
翻转
输出信号的周期是定时器的2倍
101
复位
当定时器计数到TA0CCRx值时,输出复位,并保持复位直到选择了另一个输出模式
110
翻转/置位
当定时器计数到TA0CCR0值时,输出置位
111
当定时器计数到TA0CCRx值时,输出复位。
看了上面的表,是不是有些云里雾里的赶脚?
没事,下面,我们将以定时器计数的三种模式(这里因为停止模式没有意义所以不举例)下看一下OUTMOD不同而导致输出不同的输出波形(以使用TA0CCR0和TA0CCR1为例):
1、增模式下:
大家可以看到,上面的时序图中有两种线,一种虚线,一种实线,分别来表示输出在不同初始状态下的时序变化。
有些时序前面有虚线后面没有了说明后面的实线和虚线重合了。
下面图也都是类似的,后面就不再赘述。
2、连续模式下:
3、增减模式下:
如果你要在不同输出模式之间进行切换,OUTMODx的第一个位必须在过渡时保持置位(切换至模式0除外),否则会由于或非门解码输出模式0而导致出现脉冲干扰。
输出模式切换之间的安全切换的方法之一是用输出模式7作为过渡状态。
六、Timer的中断
终于要说到中断了,16位Timer0A有两个中断向量:
①TA0CCR0?
CCIFG的TACCR0中断向量
②所有其他CCIFG和TAIFG的TAIV中断向量
在捕获模式下,当一个定时器的值捕获到相应的TACCRx寄存器时,CCIFG标志置位。
在比较模式下,如果TAR计数到相应的TACCRx值时,CCIFG标志置位。
软件可以清除或置位任何一个CCIFG标志。
当相应的CCIE和GIE置位时,CCIFG标志就会产生一个中断。
TACCR0中断:
TACCR0?
CCIFG标志拥有定时器A的最高中断优先级,并有一个专用的中断向量,如图所示。
当进入TACCR0中断后,TACCR0?
CCIFG标志自动复位。
TAIV,中断向量发生器:
TACCR1的CCIFG、TACCR2的CCIFG和TAIFG标志共用一个中断向量。
中断向量寄存器TAIV用于确定他们中的那个要求响应中断。
最高优先级的中断在TAIV寄存器中产生一个数字,这个数字是规定的数字,可以在程序中识别并自动进入相应的子程序。
定时器A中断不会影响TAIV的值。
对TAIV的读写会自动复位最高优先级的挂起中断标志。
如果另一个中断标志置位,该中断将在结束原先的中断响应后立即发生。
例如,当中断服务子程序访问TAIV时,如果TACCR1和TACCR2的CCIFG标志置位,TACCR1的CCIFG自动复位。
在中断服务子程序的RETI命令执行后,TACCR2的CCIFG标志会产生另一次中断。
在实际使用中,如果是TAIV中断中断向量,我们需要在中断服务函数中用选择分支语句对中断进行分别处理。
下表表示了TAIV的详细中断源:
TAIV值
中断源
中断标志
中断优先级
0x00
无中断
0x02
捕获/比较1
TACCR1?
最高
0x04
捕获/比较2
TACCR2?
0x06
0x08
0x0A
定时器溢出
0x0C
0x0E
最低
七、编程实例
经过上面的理论学习,我们基本上掌握了TimerA的所有的知识点,现在我们开始在IAR中进行实际编程。
1、编写一个最基本的定时器定时溢出中断的程序:
这是我们写的第一个定时器相关的程序,我们需要让定时器隔一段时间就产生一次溢出中断,这和我们学习51单片机时的定时器工作方式差不多。
我们假设500ms定时一次,同时让P1口的电平翻转一次(也就是1秒为周期)。
让我们配置一下TA0CTL寄存器。
首先分析一下应该让定时器工作在什么模式下。
我们已经知道定时器计数模式可以是增模式、连续模式、增减模式。
这里,我们可以使用增模式,因为在增模式下,我们可以通过控制TA0CCR0的值来直接控制我们定时器的定时时间。
所以我们配置MC=1。
然后我们选择一下定时器的时钟源,由TASSEL决定。
我们这里可以直接使用SMCLK,即TASSEL=2。
SMCLK由DCO产生,所以我们还要配置DCO的时钟频率。
当然,配置时钟的问题我们已经在上一篇中详细介绍了,这里就不再赘述。
我们还可以对输出的时钟信号进行分频,由ID控制。
我们可以进行8分频即ID=3。
我们这里用到Timer0A的溢出归零中断,所以需要开启TA0IFG中断,则使TAIE=1。
另外我们要让TACLR=1,这样可以在配置完成定时器时同时将Timer0A复位,TAR清零。
然后我们配置TA0CCR0寄存器,通过控制它来控制定时时长。
定时器定时时长为TA0CCR0个定时器A的时钟周期,由此我们可以计算:
TA0CCR0=500ms÷
(1÷
(1MHz÷
8))=62500=0xF424
另外我们还要开启总中断:
__enable_interrupt();
//注意前面是两个下划线
网上对开启总中断往往使用的是:
_EINT();
但其实_EINT()调用了__enable_interrupt(),由于我们所包含的头文件为“io430.h”,它会根据编译器自动包含“io430g2553.h”这个头文件,而在这个文件里面没有对_EINT()进行定义,所以不能使用_EINT()。
如果想要使用_EINT()可以将“io430.h”改为“msp430g2553.h”。
然后我们学习一下MSP430单片机在IAR集成开发环境中书写中断的方法:
#pragma?
vector?
【中断向量】
__interrupt?
void?
【中断服务函数名】
(void)
{
&
~TAIFG;
//清空TAIFG中断标志
//在这里书写中断服务函数代码
}
上面的函数体是一个模板,【中断向量】表示中断服务函数的中断来源,可以参照数据手册或者io430g2553.h头文件中“*?
Interrupt?
Vectors?
(offset?
from?
0xFFE0)”的定义如下:
/************************************************************
0xFFE0)
************************************************************/
#define?
PORT1_VECTOR?
(2?
2u)?
/*?
0xFFE4?
Port?
1?
*/
PORT2_VECTOR?
(3?
/