历史上的今天
返回首页

历史上的今天

今天是:2025年01月16日(星期四)

正在发生

2020年01月16日 | TI - MCU - MSP430使用指南13 -> Timer定时器模块

2020-01-16 来源:eefocus

定时器,作为MCU最重要也是最基本的功能集成在每一个MCU中。随着MCU功能的日渐强大,定时器的功能也越来越强大,因此配置和使用起来也就比较麻烦,下面我们针对MSP430的Timer模块进行详细讲解,配合多种可以直接使用的例程,方便用户直接移植和深入理解。


首先,普及一下定时器知识:本质上就是一个计数器,可以由用户自定义计数的值,同时到达计数值后可以执行相应的动作,因此可以时间周期性动作,采集捕捉动作等,用于实时控制及多种功能实现。


MSP430 MCU中有三种定时器:Timer_A   Timer_B   Timer_D.


首先 Timer_D定时器基本没有集成在MCU中,很少很少使用,是一个高分辨率的定时器,因此我们不做讲解(内部寄存器和使用与Timer_A/B很是相似,如果有用户用到,可以直接参考,如果有人需要可以留言,我会开贴再次单独讲解Timer_D)。


因此本次内容主要讲解一下Timer_A和Timer_B定时/计数器。首先先说一下MSP430 MCU内部Timer的主要功能:


16位定时/计数器,支持四种工作模式/计数模式:STOP  UP Continuous UP/DOWN

输入捕捉功能

输出比较功能,即PWM波功能

主要就这三种功能,用户在使用过程中也就是这三种功能,然后Timer有一些自己的特点:


时钟源可以选择

异步输入,输出所存

中断向量寄存器等

那么为什么MSP430会有两种定时器呢:A和B,有什么区别呢:


B可以配置成8,10,12,16位模式,A只能用16位模式

B的CCRn寄存器是双缓冲,即Double-buffered,可以形成组

B的每一个输出口都可配置成高阻态

B中没有SCCI位

什么?不懂?没事,等我讲解完Timer所有功能后你就了解了,如果有疑问请接着往后看,最后在讲解完之后,我会重新详细分析一下Timer_A和Timer_B的区别。


首先先了解一下Timer_A的内部结构图,从下图可以看到,内部的定时器位数是16位,同时支持TAxCLK,ACLK,SMCLK,INCLK作为时钟源,后可以进行进一步的分频使用,同时拥有7个比较输出模块,可用于输出PWM波(注意 一个Timer只能输出6个PWM波,因为有一路计数器需要作为base使用:在可以调节PWM频率和占空比的情况下)

内部结构图决定的是模块的实现方式,因此可以清晰地看出实现的原理和寄存器中每个位的作用,因此最好养成观看内部结构图的习惯,这样有利于高效地调试自己的程序,当然现在刚开始看起来有点懵,不太理解也比较正常,但当学习完整个Timer后,对比着程序来看就会恍然大悟。


好啦,下面开始进入Timer地核心内容区域:使用模式。


简单来说就是如何使用它,怎么使用,有几种使用方法。对于MSP430 Timer_A定时器来说,总共有四种工作模式,如下图所示,由寄存器TAxCLT中MC位决定,如下图所示:

模式0:默认模式,即Stop,此模式下定时器内部不会开始计数,处于停止状态。

模式1:Up模式,此模式下定时器从0开始计数,一直计数到TAxCCR0寄存器中地值为止产生中断(如果使能了中断)并重新回到0,再次开始计数,如下图所示:

在使用这种模式下,中断在什么时候产生呢?这时候就要弄清楚一个问题:Timer_A模块  有两种中断:TAxIFG(定时器中断)和TAxCCRx(捕捉/比较中断),TAxIFG时定时器的基本中断,一个定时器模块只有一个,就是当内部计数到设定值后就会产生,TAxCCRx时输入/比较中断,其实内部就一个定时器在计数,但是有不同通道的几个值可以设定,也就是TAxCCRx寄存器,因此当相对应的通道设定了值之后,则会触发相应的中断。


触发中断的时间如下图所示:

TAxIFG是在计数完CCR0后会产生的,TAxCCR0中断时在计数完CCR0-1后产生的,两者相差一个时钟位。不过在使用过程中,基本可以忽略了,只是在理论上了解一下更好。


那么还有一个问题:当前的计数值是在寄存器TAxR(看内部结构框图可以发现)中的,TAxCCR0只是设定一个值,那么当模式从Stop开始到Up模式时,TAxR的值不一定为0,那么设定就会出现两个情况:


当设定CCR0值时,TAxR值小于CCR0的值,那么定时器从当前值(TAxR)开始计数,计数到CCR0值后产生中断,回到0,从新开始计数。。。。。

当设定CCR0值时,TAxR值大于CCR0的值,那么计数器会直接回到0,从0开始计数。

因此这个时候就会出现两种情况,然而你在设定时如果不去检查TAxR的值,那么可能对于第一个周期,就会出现不同的结果。为了避免这个情况,建议在设定CCR0值的时候,将MC设置成Stop模式(TI建议),其实这时候不仅仅应该设置成Stop模式,最重要的是要将TACLR设置成1(注意这个位是TAxR清除位,直接设置成1后会自动清0,去读的话 也都是0)。


模式2:Continuous模式,此模式下定时器从0开始计数,一直计数到0xFFFF为止产生中断(如果使能了中断)并重新回到0,和Up模式地区别就是Up是计数到TAxCCR0(用户自己设定)值,而Continuous模式是直接计数到0xFFFF,这个值是固定的,不能设置,这样的话,定时器溢出的之间只能由计数频率决定了。如下图所示:

这种模式下,仅有TAxIFG中断会用到,因为没有设定CCR寄存器,也不需要这个寄存器,产生中断的时刻如下图所示:

在完成0xFFFF计数后才会产生中断。那么当工作在Continuous模式下 CCRx就不能使用了吗?


NO,也可以使用,而且可以根据客户的需求来定义不同占空比 不同形状的波形,如下图所示,使用两个CCRx时可以产生的中断(加上TAxIFG中断会更多,灵活使用):

上图可以看到,在CCR0和CCR1处都会产生中断,同时TAxIFG也是存在的。这种模式下在设定CCRx值时就仅有一种情况了,因为TAxR一直在计数,因此设定CCRx值时并不影响计数,只是看什么时候会产证中断而已,如果当前计数到10000,你设定10001,那么下一个时钟就会中断,如果当前10000,你设定9999,那么需要等下一次TAxR值等于9999时才能产生中断了,与Up模式不同的时,设定CCRx的值,不会改变或影响TAxR的值。


模式3:Up/down模式,这个模式下和Up比较类似,唯一的区别是Up模式下计数到TAxCCR0时会产生中断并再次从0开始,但是Up/down模式下则不会从0开始,而是从现在值开始往下计数(减计数),如下图所示:

触发中断的时间如下图所示:

TAxIFG会在计数到0(计完1)后触发,CCIFG会在计数完CCR0-1后触发。


那么改变CCRx值时是什么状况呢?


当设定CCR0值时,TAxR值小于CCR0的值,那么定时器从当前值(TAxR)开始计数,不影响TAxR的值。

当设定CCR0值时,TAxR值大于CCR0的值,那么计数器会立刻开始递减,进行减计数,减到0后再开始递增计数,最后正常工作。

因此此时设定CCRx值时,推荐和Up模式下保持一致。

上图显示的是在Up/down模式下CCRx使用方式,当然 这个也是PWM的输出方法,由CCR0通道作为base计数,用于调节PWM的频率,CCRx则用来调节占空比,而且还支持多种输出模式。这个模式的区别,后面会详细讲解。


到此处位置,Timer_A的四种工作模式,其实就三种(除去Stop)已经全部讲解完成,本质上也就是每个定时器模块内有一个计数器,一直在计数,然后有一些CCRx寄存器,可用于用户设定相应的值,当计数到这个值时产生相应的中断,去执行相应的操作。那么如何使用描述的这些功能呢? 我认为需要了解五块内容,会和你的使用息息相关:


中断方式,寄存器,输入捕捉,输出比较(PWM),例程。


下面按照这种方法来进行讲解(比较乱,但是我认为这种方式比较合理,先搞清楚定时器原理及模式,在进一步细看寄存器,中断实现方式,在面向使用去了解输入捕捉和输出比较,最后进行例程的学习)。


Timer_A定时器的中断

在细看完上面的讲解后,你可能会有个印象,Timer_A模块有两种中断:TAxIFG和TAxCCRx中断,那么中断向量如何呢?(中断向量是中断的入口)


如果拆开看有8个中断:TAxIFG,CCR0IFG-CCR6IFG,每个都分配一个中断向量? 太浪费了吧! 因此MSP430只分配了两个中断向量:


TAxCCR0自己单独一个中断向量,名字叫做:TIMER0_A0 (TimerA0),这个不需要记,去看工程下的cmd文件即可。


剩下的TAxIFG和TAxCCRx共同享用一个中断向量:TIMER0_A1 (TimerA0),因此你会发现每个定时器仅有两个中断向量,也就够使用了,那么如何用呢?


对于CCR0中断:


// Timer0_A0 interrupt service routine

#pragma vector = TIMER0_A0_VECTOR

__interrupt void Timer0_A0_ISR (void)

{

  P1OUT ^= BIT0;

}

对于其他中断,进入中断后需要进行中断类型判断:


// Timer0_A1 Interrupt Vector (TAIV) handler

#pragma vector=TIMER0_A1_VECTOR

__interrupt void TIMER0_A1_ISR(void)

{

  switch(__even_in_range(TA0IV, TA0IV_TAIFG))

  {

    case TA0IV_NONE:   break;               // No interrupt

    case TA0IV_TACCR1: break;               // CCR1 not used

    case TA0IV_TACCR2: break;               // CCR2 not used

    case TA0IV_TACCR3: break;               // reserved

    case TA0IV_TACCR4: break;               // reserved

    case TA0IV_TACCR5: break;               // reserved

    case TA0IV_TACCR6: break;               // reserved

    case TA0IV_TAIFG:                       // overflow

      P1OUT ^= BIT0;

      break;

    default: break;

  }

}

注意:并不是所有的Timer_A都有6个CCR寄存器,具体有几个看每个芯片的datasheet。


Timer_A寄存器

先看一下总共有多少寄存器:18个寄存器,但是只有六类寄存器,其他都是相同的。

TAxCTL寄存器

TASSEL :  时钟源选择,如上图所示,有四种时钟源。

ID : 时钟源分频,对选中的时钟源进行分频后再输入Timer用于计数。

MC : 定时器模式选择,设定上述所讲的四种模式。

TACLR : 计数器清零位,写1会清除当前计数值,会自动复位。

TAIE : Timer_A中断使能位。

TAIFG : Timer_A中断标志位,即使中断不使能,当产生中断信号时,标志位也会置位。


TAxR寄存器

TAxR : 计数器当前计数的值,可以进行读写操作。


TAxCCTLn寄存器

CM : 捕捉边沿类型,这个用于捕捉外部的信号,可以选择上升沿,下降沿,上升/下降沿。

CCIS :  捕捉输入通道选择,可以选择成A, B, GND, VCC,每个通道对应的GPIO口不同,具体看datasheet。

SCS : 同步捕捉还是异步捕捉,是否将输入信号与时钟信号进行同步,看结构图可以看到内部就是使用了一个与门,可以实现时钟信号与输入信号的同步,这个根据客户需要进行选择,一般来说两种模式都可以,具体看客户使用场景,在学习是注意一下有这个点即可,当遇到问题时,如果可能是时序问题的话,查看一下这个。

SCCI : 同步输入信号加载紧EQU失能位选择,就是给EQU多一个输入源CCI。

CAP : 输入捕捉模式还是输出比较模式选择。

OUTMOD : 输出模式类型,总共有7中模式,也就是再不同中断情况下进行不同的操作,可能是置位,也可能是复位,或者反转等,很多模式都可以输出PWM波,用户自己看就可以。

给出一个再Up模式下不同模式的波形图:


模式1(001) :   CCR1中断时直接置位。


模式2(010)  :     CCR1中断时反转,CCR0中断时复位。


模式3(011)  :     CCR1中断时置位,CCR0中断时复位。


模式4(100)  :     CCR1中断时反转。


模式5(101)  :     CCR1中断时复位。


模式6 (110):      CCR1中断时反转,CCR0中断时置位。


模式7 (111):      CCR1中断时复位,CCR0中断时置位。

CCIE : 输入捕捉或输出比较使能。

CCI : 只读寄存器,可以读取被选中通道的点评状态。

OUT : 输出比较模式时初始输出状态。当OUTMOD=000时,就直接一致输出这个状态。

COV : 输入捕捉overflow产生,即溢出了,当输入的数大于0xFFFF时会溢出,这一位必须软件复位。注意,在计算输入捕捉到的脉冲数量时,需要检测这一位,否则会出现溢出情况导致捕捉到的脉冲是负数或者差一个0xFFFF。

CCIFG : 输入捕捉/输出比较中断标志位。


TAxCCRn寄存器

TAxCCRn : 输出比较时使设定值,输入捕捉时是当收到捕捉信号时定时器的值。


TAxIV寄存器

TAIV : 只读寄存器,中断类型标志位,用来识别是哪个中断源引起的中断(因为除了TAxCCR0,其他中断源共享一个中断向量)


TAxEX0寄存器

TAxIDEX : 输入时钟分频寄存器,和TAxCTL寄存器中ID位效果一致,用来对所选的时钟进行分频后再输入给Timer_A。

Timer_A输入捕捉

首先看,什么叫输入捕捉,用在什么地方:主要用于测量脉冲数量,监控外部脉冲等功能,其实最主要的就是连接增量式编码器来获取固定时间内的脉冲数量从而计算电机的转速,这个是最最常用的功能。


如下是MSP430 输入捕捉功能的工作流程图:

那么如何设定输入捕捉呢?


这个主要再TAxCCTLn寄存器,首先你需要将CAP设置成1,代表使用输入捕捉模式,其次根据你的硬件连接选择A或者B通道,然后设定同步位,捕捉类型等,最后依旧是要设定最基本的定时器功能,因为定时器要工作,开始计数嘛!


当然设置完这些后输入捕捉就可以工作了,但是捕捉到信号之后怎么办呢? 需要开中断嘛,这时进中断,将这个时刻计数器的值给记下来,用于脉冲频率等的测量。


后续如何使用此项功能,在后面会给出详细的Example Code.


Timer_A输出比较

输出比较最常用的就是输出PWM波了,这个电机控制,LED控制等中非常常用,原理上前面已经描述清除,就是靠Base计数器和CCRx计数器,当计数到CCRx寄存器时会进行相应的动作,从而实现PWM功能的输出,通过CCR0调节PWM频率,CCRx调节占空比。


Timer_A例程

好啦,上面讲了一大堆最最主要的还是程序应该怎么写,怎么使用每个功能,下面给出几种常用的程序。(例程使用MSP430FR5969,别问为什么 主要因为刚好有这个板子。。。其实MSP430 内部Timer_A模块都是一样的,因此程序基本通用,可能仅仅有一些寄存器不一样或者功能有点区别而已,总的来说大同小异。)


基本定时功能(20ms中断)

#include

 

int main(void)

{

  WDTCTL = WDTPW | WDTHOLD;                 // Stop WDT

  // Configure GPIO

  P1DIR |= BIT0;

  P1OUT |= BIT0;

 

  // Disable the GPIO power-on default high-impedance mode to activate

  // previously configured port settings

  PM5CTL0 &= ~LOCKLPM5;

  TA0CCTL0 = CCIE;                          // TACCR0 interrupt enabled

  TA0CCR0 = 20000;                          // SMCLK default 1MHz,

                                     // Set 20000 : 20000/1000000 = 20ms

  TA0CTL = TASSEL__SMCLK | MC__UP;          // SMCLK, UP mode

 

  __bis_SR_register(LPM0_bits + GIE);       // Enter LPM0 w/ interrupt

  __no_operation();                         // For debugger

}

 

// Timer0_A0 interrupt service routine

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)

#pragma vector = TIMER0_A0_VECTOR

__interrupt void Timer0_A0_ISR (void)

#elif defined(__GNUC__)

void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer0_A0_ISR (void)

#else

#error Compiler not supported!

#endif

{

  P1OUT ^= BIT0;

}

 

输入捕捉功能 (开始捕捉中断,捕捉到20个脉冲后反转P1.1口,同时记录下每个脉冲时刻的计数器的值)

#include "msp430.h"

 

#define NUMBER_TIMER_CAPTURES       20

volatile unsigned int timerAcaptureValues[NUMBER_TIMER_CAPTURES];

unsigned int timerAcapturePointer = 0;

 

int main(void)

{

  WDTCTL = WDTPW | WDTHOLD;                 // Stop watchdog timer

 

  // Configure GPIO

  P1OUT &= ~0x01;                           // Clear P1.0 output

  P1DIR |= 0x01;                            // Set P1.0 to output direction

 

  // Disable the GPIO power-on default high-impedance mode to activate

  // previously configured port settings

  PM5CTL0 &= ~LOCKLPM5;

 

  // Clock System Setup

  CSCTL0_H = CSKEY >> 8;                    // Unlock CS registers

  CSCTL2 &= ~SELA_7;

  CSCTL2 |= SELA__VLOCLK;                   // Select ACLK=VLOCLK

  CSCTL0_H = 0x00;                        // Lock CS module (use byte mode to upper byte)

 

  __delay_cycles(1000);                     // Allow clock system to settle

推荐阅读

史海拾趣

Gigabit Logic Inc公司的发展小趣事
用户只需通过触摸即可实现调速,无需手动旋转旋钮或按钮。
Hi-Light Electronic Co Ltd公司的发展小趣事
采用集成电路等现代电子元器件,提高了电路的可靠性和稳定性。
Frolyt Condensers & Elements GmbH公司的发展小趣事

面对电子行业日益增长的定制化需求,Frolyt Condensers & Elements GmbH积极调整策略,提供从设计咨询到产品生产的全方位定制化服务。公司建立了一支专业的技术团队,能够根据客户的具体需求,快速响应并设计出符合要求的电容器产品。这种高度定制化的服务模式赢得了众多客户的信赖和好评,使得Frolyt在竞争激烈的市场中脱颖而出。

GE Power Electronics Inc公司的发展小趣事
合理设计电路布局和布线,避免信号干扰和串扰。同时,采用适当的保护电路,如过压保护、过流保护等。
Esterline Power Systems公司的发展小趣事

Esterline Power Systems公司在其早期阶段就致力于研发创新技术,以满足航空和国防行业对高性能电源系统的需求。一次关键的技术突破发生在公司对一种新型高效能电源控制器的研发上。面对市场上已有的产品性能瓶颈,公司的研发团队经过数月的深入研究与实验,成功开发出了具有更高效率和更稳定性能的电源控制器。这一创新不仅赢得了客户的认可,也为公司赢得了市场份额,奠定了在电源系统领域的领先地位。

Headland Technology Product Group公司的发展小趣事

近年来,随着环保意识的日益增强,HBControls积极响应国家号召,致力于绿色环保产品的研发和生产。公司投入大量资金引进环保设备和技术,对生产流程进行改造升级,以减少对环境的影响。同时,HBControls还积极推广绿色供应链理念,与供应商共同构建绿色、低碳的供应链体系。这些举措不仅提升了公司的社会形象,也为企业的可持续发展奠定了坚实的基础。

问答坊 | AI 解惑

卫星拒绝“出让”WiMax频谱,印度将错过无线宽带“革命”?

WiMax论坛警告说,如果不重新分配WiMax服务所需的2.5-2.69GHz频段内的频谱,印度将可能错过无线宽带革命。但是,这一频谱目前被印度的空间部用于其Insat卫星,而它不愿意拱手相让。 WiMax论坛主席兼总裁Ron Resnick在The Economic Times的一则报导 ...…

查看全部问答>

请问ASN.1的大侠,ASN.1的编译器哪个好?什么价位?

国外的有几个公司但好像没有见到国内的,不知什么原因是技术瓶颈还是国内不屑微小的市场份额????asn.1 到JAVA或者到c 语言的商用编译器哪个好?一般什么价位?望大虾指教,感激不尽…

查看全部问答>

winCE OCX 控件调用

大家好!      WinCE 中 OCX的调用问题?      Primary dispatch interface      的接口的GUID是不是需要DllRegisterServer的注册,如果需要,怎么注册,不需要的话,外部网页怎 ...…

查看全部问答>

求硬件方面的开发资料!!

例如Z80汇编语言资料、硬件驱动程序开发资料、嵌入式开发资料等等!!!…

查看全部问答>

请问在VxWorks下,如何在CF卡中安装文件系统?

我用CF作为启动盘,通过网络启动VxWorks,我已经用MkBoot将CF做成启动盘了,请问CF中是否已经包含了文件系统?还是需要另外再安装相应的文件系统呢?我想在CF卡中创建一个文本文件,肯定需要文件系统的吧!请大侠们指点小弟,不胜感激!…

查看全部问答>

关于全国电设大赛的准备工作请教

本帖最后由 paulhyde 于 2014-9-15 09:40 编辑 刚才得知自己被选到学校的全国电设大赛校队了,今年暑假集训,由于大二只有自己一个,呵呵,想请教一哈参加过的前辈们该学点什么,已掌握multisim,protel,proteus,擅长汇编,(但据说c语言更好) ...…

查看全部问答>

哪位大侠知道IQ(0.0000052)是啥意思

哪位大侠知道IQ(0.0000052)是啥意思,不胜感激…

查看全部问答>

【TI技术文章】:工业流程计量及控制指南

题目:工业流程计量及控制指南   简介:本篇主要讲述,流程处理及控制系统应用于许多不同的领域,包括了测试实验室、军用装配及加工设备、医疗及自动化。此类系统采用不同类型的传感器及反馈机制,通过采集、存储、分析数据来实现对本地环境 ...…

查看全部问答>

如何将连续输入的多组并行数据转换成串行输出

如何将连续输入的多组并行数据转换成串行输出?求教高手!例如,第一组并行数据为:11,12,14,5,12,现将它们串行输出,输出完后就进行一下组数据的并串转换。…

查看全部问答>

JEDEC的DDR4技术标准的公布

微电子产业标准机构JEDEC固态技术协会终于发布了下一代同步DDR内存的技术标准:DDR4,它的数据传输速度将比DDR3快一倍,且功耗更低。“JEDEC的DDR4技术标准的公布是数年来世界各地的内存、系统、部件和模块制造商共同努力的结果,”JEDEC下属组织JC ...…

查看全部问答>