MSP430 定时器A.docx

上传人:b****3 文档编号:4046773 上传时间:2022-11-27 格式:DOCX 页数:17 大小:28.41KB
下载 相关 举报
MSP430 定时器A.docx_第1页
第1页 / 共17页
MSP430 定时器A.docx_第2页
第2页 / 共17页
MSP430 定时器A.docx_第3页
第3页 / 共17页
MSP430 定时器A.docx_第4页
第4页 / 共17页
MSP430 定时器A.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

MSP430 定时器A.docx

《MSP430 定时器A.docx》由会员分享,可在线阅读,更多相关《MSP430 定时器A.docx(17页珍藏版)》请在冰豆网上搜索。

MSP430 定时器A.docx

MSP430定时器A

上次Cloud和大家一起学习完了MSP430的时钟配置,这一篇,我们来学习MSP430单片机的TimerA(定时/计数器A)。

MSP430单片机的TimerA具有非常强大的功能,相关的寄存器配置也相当复杂,Cloud花了好久才逐步理清学习思路,尤其是学习数据手册的相关描述。

在这里Cloud提醒大家,虽然现在网上有中文汉化版的数据手册,但Cloud阅读英文原版后对比发现还是英文原版对器件特性描述得更加清楚,而中文汉化版的省略掉了一些内容。

好吧,扯远了。

下面进入正题:

一、MSP430的Timer结构

首先让我们通过官方描述来初步了解一下MSP430单片机的Timer资源:

定时器A是一个16位的定时/计数器。

定时器A支持多重捕获/比较,PWM输出和内部定时。

定时器还有扩展中断功能,中断可以由定时器溢出产生或由捕获/比较寄存器产生。

定时器A的特性包括:

?

?

·四种运行模式的异步16位定时/计数器

?

?

·可选择配置的时钟源

?

?

·可配置的PWM输出

?

?

·异步输入和输出锁存

?

?

·对所有TA中断快速响应的中断向量寄存器

MSP430G2553单片机共有两个TimerA,分别是Timer0A和Timer1A。

OK,零零总总说了这么多,大家一定带有很多的疑惑,比如什么叫“捕获/比较”等,这里Cloud先不作解释,会用才是王道。

我们呢先找来定时器A的结构图给大家初步了解一下定时器A的结构:

我们先从上面部分开始解释。

中间红色的是一个16位的TimerA,TAR,这其实就是MSP430单片机内部的一个定时计数器了,类似于51中的TH0和TL0的合体。

既然可以拿来计时,那么肯定可以有时钟信号输入,让我们最左边黄色的框,是一个选择器,由上面的TASSEL来选择TACLK、ACLK、SMCLK、INCLK的其中一种时钟。

上次我们已经学习过ACLK和SMCLK,也知道如何配置这两个时钟了(这也是为什么先学习时钟的原因),另外两个是外部时钟源,其中TACLK可以由P1.0输入。

跟在时钟源后面的是一个分频器,由ID来控制,将时钟源的时钟信号1、2、4、8分频后作为定时/计数器的时钟源。

TAR右边的蓝色框代表TimerA在计数模式下由MC来控制TAR的四种计数方式。

同时我们还注意到TAR的左下方有一个TACLAR连接至TAR的Clear端,显然是清零作用的,数据手册还告诉我们置位TACLAR,不但会清零TAR的计数值还会清除时钟分频信息。

TACLAR一旦置1,会自动归零,所以可以当做是TimerA的复位按钮。

再看下半部分的CCR2,CCR2是TimerA的其中一个独立的捕获/比较单元,其实在MSP430G2553中,还有CCR0和CCR1(连接上半部分和下半部分的虚线省略处),其结构和CCR2基本一致。

我们可以看到从上面TAR输出的空心粗箭头指向了TACCR2和Comparator2,TACCR2是RRC2的捕获/比较寄存器,虚线框左上角部分表示了TimerA的捕获通道,用于将CCIS所选择的信道经过所选择的捕获模式和同步操作传递给TACCR2。

虚线框下半部分表示不同的输出模式的信号输出逻辑。

二、Timer相关寄存器介绍

OK,Cloud基本为大家介绍了TimerA的结构,确实略复杂。

按照以往教程惯例,Cloud先从寄存器开始和大家一起学习(这里提醒大家,在msp430头文件中,很多不同标示符的定义其实都来自同一个对象,在MSP430G2553中,有Timer0A和Timer1A,相关的寄存器有TA0CTL、TA0CCR0、TA1CTL、TA1CCR0等,由于这两个时钟基本一样,这里就只以Timer0A为例。

Timer0A的相关寄存器可以将TA0字样省略为TA,例如TACTL=TA0CTL、TACCR0=TA0CCR0等,大家在实际使用和学习时要知道这两种表示方式都是一样的):

1、TA0CTL:

TimerA控制寄存器

TA0CTL?

?

TimerA控制寄存器

15

14

13

12

11

10

9

8

-

-

-

-

-

-

TASSEL1

TASSEL0

7

6

5

4

3

2

1

0

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的计数模式

?

?

0:

停止模式?

?

1:

增模式?

?

2:

连续模式?

?

3:

增减模式

·2:

TACLR:

TimerA清零位,该位置位会复位TAR,时钟分频和计数方向,完成后TACLR自动清零

·1:

TAIE:

TimerA中断允许位,用来允许TAIFG中断请求

?

?

0:

中断禁止1:

中断允许

·0:

TAIFG:

TimerA中断标志位?

?

0:

无中断挂起?

?

1:

有中断挂起

2、TA0R:

TimerA寄存器

TA0R?

?

TimerA寄存器

15

14

13

12

11

10

9

8

X

X

X

X

X

X

X

X

7

6

5

4

3

2

1

0

X

X

X

X

X

X

X

X

TA0R(也可以写TAR)是一个用来存放当前计数值的一个16位的寄存器,类似于51的TH0和TL0的合体。

3、TA0CCRx:

TimerA捕获比较寄存器x

TA0CCRx?

?

TimerA捕获比较寄存器x

15

14

13

12

11

10

9

8

X

X

X

X

X

X

X

X

7

6

5

4

3

2

1

0

X

X

X

X

X

X

X

X

TA0CCRx(也可以写TACCRx)是一个用来存放定时计数器捕获值的16位寄存器,在MSP430G2553中x可以是0、1、2,对应相应的TA0CCTLx。

另外TA0CCR0还可以用来设置TimerA计数模式中增模式和增减模式的峰值,详细后面将会讲。

?

4、TA0CCTLx:

TimerA捕获比较控制寄存器x

TA0CCRx?

?

TimerA比较控制寄存器x

15

14

13

12

11

10

9

8

CM1

CM0

CCIS1

CCIS0

SCS

SCCI

-

CAP

7

6

5

4

3

2

1

0

OUTMODE2

OUTMODE1

OUTMOD0

CCIE

CCI

OUT

COV

CCIFG

TA0CCTLx(也可以写TACCTLx),在MSP430G2553中x可以是0、1、2(其他型号单片机可能有更多的支持,详细看相关数据手册),对应相应的TA0CCRx,TA0CCTLx定义了很多TimerA捕获比较控制控制相关的位,让我们来一一学习:

·15~14-CM:

捕获模式控制寄存器

?

?

0:

不捕获?

?

1上升沿捕获?

?

2:

下降沿捕获?

?

3:

上升和下降沿都捕获

·13~12-CCIS:

捕获比较选择,该位选择TA0CCRx的输入信号,

·11-SCS:

同步捕获源,该位用于将捕获通信和时钟同步?

?

0:

异步捕获?

1:

同步捕获

·10-SCCI:

同步的捕获/比较输入,所选择的CCI输入信号由EQUx信号锁存,并可通过该位读取

·8-CAP:

比较/捕获模式选择?

?

0:

比较模式?

?

1:

捕获模式

·7~5-OUTMODE:

输出模式位,由于在模式2、3、6、7下EAQUx=EQU0,因此这些模式对TA0CCRx无效

?

?

0:

OUT位的值?

?

?

?

?

1:

置位?

?

?

?

?

?

?

?

2:

翻转/复位?

?

?

?

3:

置位/复位

?

?

4:

翻转?

?

?

?

?

?

?

?

?

?

?

5:

复位?

?

?

?

?

?

?

?

6:

翻转/置位?

?

?

?

7:

复位/置位

·4-CCIE:

捕获比较中断允许位,该位允许相应的CCIFG标志请求

?

?

0:

中断禁止?

1:

中断允许

·3-CCI:

捕获比较输入,所选择的输入信号可以通过该位读取

·2-OUT:

输出状态位,对于输出模式0,该位直接接控制输出状态

?

?

0:

输出低电平?

?

1:

输出高电平

·1-COV:

捕获溢出位,该位表示一个捕获溢出发生。

COV必须由软件复位

?

?

0:

没有捕获溢出发生?

?

1:

有捕获溢出发生

·0-CCIFG:

捕获比较中断标志位?

?

0:

没有中断挂起?

?

1:

有中断挂起

三、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

0

输出

输出信号OUTx由OUTx位定义。

当OUTx位更新时,OUTx信号立刻更新

001

1

置位

当计时器计数到TA0CCRx值时,输出置位,并保持置位直到定时器复位或选择了另一个输出模式

010

2

翻转/复位

当定时器计数到TA0CCRx值时,输出翻转。

当定时器计数到TA0CCR0值时,输出复位

011

3

置位/复位

当定时器计数到TA0CCRx值时,输出置位。

当定时器计数到TA0CCR0值时,输出复位

100

4

翻转

当定时器计数到TA0CCRx值时,输出翻转。

输出信号的周期是定时器的2倍

101

5

复位

当定时器计数到TA0CCRx值时,输出复位,并保持复位直到选择了另一个输出模式

110

6

翻转/置位

当定时器计数到TA0CCRx值时,输出翻转。

当定时器计数到TA0CCR0值时,输出置位

111

7

复位/置位

当定时器计数到TA0CCRx值时,输出复位。

当定时器计数到TA0CCR0值时,输出置位

看了上面的表,是不是有些云里雾里的赶脚?

没事,下面,我们将以定时器计数的三种模式(这里因为停止模式没有意义所以不举例)下看一下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?

CCIFG

最高

0x04

捕获/比较2

TACCR2?

CCIFG

0x06

-

-

0x08

-

-

0x0A

定时器溢出

TAIFG

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)

{

?

?

TA0CTL?

&=?

~TAIFG;?

?

?

//清空TAIFG中断标志

?

?

//在这里书写中断服务函数代码

}

上面的函数体是一个模板,【中断向量】表示中断服务函数的中断来源,可以参照数据手册或者io430g2553.h头文件中“*?

Interrupt?

Vectors?

(offset?

from?

0xFFE0)”的定义如下:

/************************************************************

*?

Interrupt?

Vectors?

(offset?

from?

0xFFE0)

************************************************************/

#define?

PORT1_VECTOR?

?

?

?

?

?

?

?

(2?

*?

2u)?

?

/*?

0xFFE4?

Port?

1?

*/

#define?

PORT2_VECTOR?

?

?

?

?

?

?

?

(3?

*?

2u)?

?

/

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1