目录

  • 硬知识
    • 定时器A 16位定时器原理
    • (1)时钟源选择和分频器
    • (2)Timer_A工作模式
    • (3)捕获/比较模块
    • (4)Timer_A中断(重要)
  • 定时器A API (机翻)
    • 定时器A配置和控制的函数
      • 参数
    • 定时器A 输出相关函数
      • 参数
    • 管理定时器A中断的程序
      • 参数
  • 中断向量
  • 上机实战
    • 定时器A 增计数模式CCR0中断
      • 初始化函数
      • 中断服务函数
      • 实验结果
    • 定时器A 增计数模式TAIE中断
      • 初始化函数
      • 中断服务函数
      • 实验结果
    • 输入捕获模式测量脉宽长度
      • 初始化函数
      • 中断服务函数
      • 被测信号产生
      • 实验结果

平台:Code Composer Studio 10.3.1
MSP430F5529 LaunchPad™ Development Kit
(MSP‑EXP430F5529LP)


硬知识

定时器A具有如下特点:
 4种运行模式的异步16位定时/计数器;
 参考时钟源可选择配置;
 高达7个可配置的捕获/比较寄存器;
 可配置的PWM输出;
 异步输入和输出锁存;
 具有可对Timer_A中断快速响应的中断向量寄存器。
       定时器A的结构框图如图所示。

定时器A 16位定时器原理

16位定时器的计数值寄存器TAR在每个时钟信号的上升沿进行增加/减少,可利用软件读取TAR寄存器的计数值。此外,当定时时间到,产生溢出时,定时器可产生中断。置位定时器控制寄存器中的TACLR控制位,可自动清除TAR寄存器的计数值,同时,在增/减计数模式下,清除了时钟分频器和计数方向。

(1)时钟源选择和分频器

定时器的参考时钟源可以来自内部时钟ACLK、SMCLK或者来自TACLK引脚输入,可通过TASSEL控制位进行选择。选择的时钟源首先通过ID控制位进行1、2、4、8分频,对于分频后的时钟,可通过TAIDEX控制位进行1、2、3、4、5、6、7、8分频。

(2)Timer_A工作模式

Timer_A共有4种工作模式:停止模式、增计数模式、连续计数模式和增/减计数模式,具体工作模式可以通过MC控制位进行选择,具体配置如表所示。

停止模式。停止模式用于定时器暂停,并不发生复位,所有寄存器现行的内容在停止模式结束后都可用。当定时器暂停后重新计数时,计数器将从暂停时的值开始以暂停前的计数方向计数。例如,停止模式前,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。增计数模式下中断标志位设置过程如右图所示。

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

连续计数模式的典型应用如下:
 产生多个独立的时序信号:利用捕获比较寄存器捕获各种其他外部事件发生的定时器数据。
 产生多个定时信号:在连续计数模式下,每完成一个TAxCCRn(其中n取值为0~6)计数间隔,将产生一个中断,在中断服务程序中,将下一个时间间隔计数值赋给TAxCCRn,如 图6.4.7表示了利用两个捕获比较寄存器TAxCCR0和TAxCCR1产生两个定时信号t0和t1。在这种情况下,定时完全通过硬件实现,不存在软件中断响应延迟的影响,具体实现示意图如图所示。

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

(3)捕获/比较模块

捕获/比较模块的逻辑结构如图所示,在此以捕获/比较模块TAxCCR6为例进行介绍。

捕获模式。当CAP控制位置为1时,捕获/比较模块配置为捕获模式。捕获模式被用于捕获事件发生的时间。捕获输入CCIxA和CCIxB可连接外部引脚或内部信号,这需通过CCIS控制位进行配置。可通过CM控制位将捕获输入信号触发沿配置为上升沿触发、下降沿触发或两者都触发。捕获事件在所选输入信号触发沿产生,如果产生捕获事件,定时器将完成以下工作:
 主计数器计数值复制到TAxCCRn寄存器中;
 置位中断标志位CCIFG。
输入信号的电平可在任意时刻通过CCI控制位进行读取。捕获信号可能会和定时器时钟不同步,并导致竞争条件的产生,将SCS控制位置位可在下一个定时器时钟使捕获同步。捕获信号示意图如左图所示。
如果第二次捕获在第一次捕获的值被读取之前发生,捕获/比较寄存器就会产生一个溢出逻辑,在此情况下,将置位COV标志位,如右图所示。注意COV标志位必须通过软件消除。

比较模式。当CAP控制位设为0时,捕获/比较模块工作在比较模式。比较模式用来产生PWM输出信号或者在特定的时间间隔产生中断。此时TAxCCRn的值可由软件写入,并通过比较器与主计数器的计数值TAR进行比较,当TAR计数到TAxCCRn时,将依次产生以下事件:
 置位中断标志位CCIFG;
 产生内部信号EQUn=1;
 EQUn信号根据不同的输出模式触发输出逻辑;
 输入信号CCI被锁存到SCCI。
       每个捕获/比较模块都包含一个输出单元,用于产生输出信号,例如PWM信号等。每个输出单元都有8种工作模式,可产生EQUx的多种信号。输出模式可通过OUTMOD控制位进行定义,具体定义如表所示。

增计数模式下,定时器比较输出
       在增计数模式下,当TAR增加到TAxCCRn或从TAxCCR0计数到0时,定时器输出信号按选择的输出模式发生变化。示例如图所示,该示例利用了TAxCCR0和TAxCCR1。

连续计数模式下,定时器比较输出
       在连续计数模式下,定时器输出波形与增计数模式一样,只是计数器在增计数到TAxCCR0后还要继续增计数到0FFFFh,这样就延长了计数器计数到TAxCCR1数值的时间。在连续计数模式下的输出波形如图所示。在该示例中同样用到了TAxCCR0和TAxCCR1。

增/减计数模式下,定时器比较输出
       在增/减计数模式下,各种输出模式与定时器工作在增计数模式或连续计数模式不同。当定时器计数值TAR在任意计数方向上等于TAxCCRn时或等于TAxCCR0时,定时器输出信号都按选定的输出模式发生改变。在增/减计数模式下的输出波形如图所示。该示例利用了TAxCCR0和TAxCCR2。

(4)Timer_A中断(重要)

16位定时器Timer_A具有两个中断向量,分别如下:
 TAxCCR0的中断向量CCIFG0
具有其余TAxCCRn的中断标志CCIFGn及TAIFG的中断向量TAIV

在捕获模式下,当定时计数器TAR的值被捕获到TAxCCRn寄存器内时,置位相关的CCIFGn中断标志位。在比较模式下,当定时计数器TAR的值计数到TAxCCRn的值时,置位相关的CCIFGn中断标志位。也可利用软件置位或清除任意一个CCIFG中断标志位,当相关的CCIE中断允许位和GIE总中断允许位置位,CCIFGn中断标志位将请求产生中断。
① TAxCCR0中断
       TAxCCR0中断标志位CCIFG0在Timer_A中断中具有最高的中断优先级,TAxCCR0中断产生逻辑如图所示。当相应的TAxCCR0中断请求被响应后,TAxCCR0中断标志位CCIFG0自动复位。
② TAIV中断
       TAxIV中断主要包括TAxCCRn的中断标志CCIFGn和TAIFG中断标志。中断向量寄存器可被用来判断当前被挂起的Timer_A中断,之后通过查中断向量表得到中断服务程序的入口地址,并将其添加到程序计数器中,程序将自动转入中断服务程序。禁用Timer_A中断功能并不影响TAxIV中断向量寄存器的值。
       对TAxIV中断向量寄存器的读或写,都将自动清除挂起的最高优先级中断标志位。如果同时也置位了其他中断标志位,在当前中断服务程序执行完毕后,将自动立即响应新的中断请求。
       例如,当中断服务程序访问TAxIV中断向量寄存器时,同时TAxCCRI和TAxCCR2的CCIFG中断标志位置位。首先响应TAxCCRI的CCIFG中断请求,并且自动复位TAxCCR1的CCIFG中断标志位。当在中断服务程序中执行RETI断回执后,CPU响应TAXCCR2的CCIFG中断请求。

Timer_A具有丰富的寄存器资源供用户使用,详细列表如表所示

定时器A API (机翻)

定时器A APl被分成三组函数:
处理定时器配置和控制的函数,
处理定时器内容的函数,
以及处理中断的函数。

定时器A配置和控制的函数

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)
//停止计时器计时

参数

baseAddress
是TIMER_A模块的基地址

TIMER_A0_BASE
TIMER_A1_BASE
TIMER_A2_BASE

timerMode

TIMER_A_STOP_MODE
TIMER_A_UP_MODE
TIMER_A_CONTINUOUS_MODE // [Default]
TIMER_A_UPDOWN_MODE

Timer_A_initUpModeParam

//*****************************************************************************
//
//! \brief Used in the Timer_A_initUpMode() function as the param parameter.
//
//*****************************************************************************
typedef struct Timer_A_initUpModeParam {//! Selects Clock source.//! \n Valid values are://! - \b TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK [Default]//! - \b TIMER_A_CLOCKSOURCE_ACLK//! - \b TIMER_A_CLOCKSOURCE_SMCLK//! - \b TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLKuint16_t clockSource;//! Is the desired divider for the clock source//! \n Valid values are://! - \b TIMER_A_CLOCKSOURCE_DIVIDER_1 [Default]//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_2//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_3//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_4//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_5//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_6//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_7//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_8//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_10//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_12//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_14//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_16//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_20//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_24//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_28//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_32//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_40//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_48//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_56//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_64uint16_t clockSourceDivider;//! Is the specified Timer_A period. This is the value that gets written//! into the CCR0. Limited to 16 bits[uint16_t]uint16_t timerPeriod;//! Is to enable or disable Timer_A interrupt//! \n Valid values are://! - \b TIMER_A_TAIE_INTERRUPT_ENABLE//! - \b TIMER_A_TAIE_INTERRUPT_DISABLE [Default]uint16_t timerInterruptEnable_TAIE;//! Is to enable or disable Timer_A CCR0 captureComapre interrupt.//! \n Valid values are://! - \b TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE//! - \b TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE [Default]uint16_t captureCompareInterruptEnable_CCR0_CCIE;//! Decides if Timer_A clock divider, count direction, count need to be//! reset.//! \n Valid values are://! - \b TIMER_A_DO_CLEAR//! - \b TIMER_A_SKIP_CLEAR [Default]uint16_t timerClear;//! Whether to start the timer immediatelybool startTimer;
} Timer_A_initUpModeParam;

Timer_A_initUpDownModeParam

//*****************************************************************************
//
//! \brief Used in the Timer_A_initUpDownMode() function as the param
//! parameter.
//
//*****************************************************************************
typedef struct Timer_A_initUpDownModeParam {//! Selects Clock source.//! \n Valid values are://! - \b TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK [Default]//! - \b TIMER_A_CLOCKSOURCE_ACLK//! - \b TIMER_A_CLOCKSOURCE_SMCLK//! - \b TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLKuint16_t clockSource;//! Is the desired divider for the clock source//! \n Valid values are://! - \b TIMER_A_CLOCKSOURCE_DIVIDER_1 [Default]//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_2//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_3//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_4//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_5//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_6//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_7//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_8//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_10//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_12//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_14//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_16//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_20//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_24//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_28//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_32//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_40//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_48//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_56//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_64uint16_t clockSourceDivider;//! Is the specified Timer_A perioduint16_t timerPeriod;//! Is to enable or disable Timer_A interrupt//! \n Valid values are://! - \b TIMER_A_TAIE_INTERRUPT_ENABLE//! - \b TIMER_A_TAIE_INTERRUPT_DISABLE [Default]uint16_t timerInterruptEnable_TAIE;//! Is to enable or disable Timer_A CCR0 captureComapre interrupt.//! \n Valid values are://! - \b TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE//! - \b TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE [Default]uint16_t captureCompareInterruptEnable_CCR0_CCIE;//! Decides if Timer_A clock divider, count direction, count need to be//! reset.//! \n Valid values are://! - \b TIMER_A_DO_CLEAR//! - \b TIMER_A_SKIP_CLEAR [Default]uint16_t timerClear;//! Whether to start the timer immediatelybool startTimer;
} Timer_A_initUpDownModeParam;

Timer_A_initContinuousModeParam

//*****************************************************************************
//
//! \brief Used in the Timer_A_initContinuousMode() function as the param
//! parameter.
//
//*****************************************************************************
typedef struct Timer_A_initContinuousModeParam {//! Selects Clock source.//! \n Valid values are://! - \b TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK [Default]//! - \b TIMER_A_CLOCKSOURCE_ACLK//! - \b TIMER_A_CLOCKSOURCE_SMCLK//! - \b TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLKuint16_t clockSource;//! Is the desired divider for the clock source//! \n Valid values are://! - \b TIMER_A_CLOCKSOURCE_DIVIDER_1 [Default]//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_2//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_3//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_4//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_5//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_6//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_7//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_8//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_10//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_12//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_14//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_16//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_20//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_24//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_28//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_32//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_40//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_48//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_56//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_64uint16_t clockSourceDivider;//! Is to enable or disable Timer_A interrupt//! \n Valid values are://! - \b TIMER_A_TAIE_INTERRUPT_ENABLE//! - \b TIMER_A_TAIE_INTERRUPT_DISABLE [Default]uint16_t timerInterruptEnable_TAIE;//! Decides if Timer_A clock divider, count direction, count need to be//! reset.//! \n Valid values are://! - \b TIMER_A_DO_CLEAR//! - \b TIMER_A_SKIP_CLEAR [Default]uint16_t timerClear;//! Whether to start the timer immediatelybool startTimer;
} Timer_A_initContinuousModeParam;

Timer_A_initCaptureModeParam

//*****************************************************************************
//
//! \brief Used in the Timer_A_initCaptureMode() function as the param
//! parameter.
//
//*****************************************************************************
typedef struct Timer_A_initCaptureModeParam {//! Selects the Capture register being used. Refer to datasheet to ensure//! the device has the capture compare register being used.//! \n Valid values are://! - \b TIMER_A_CAPTURECOMPARE_REGISTER_0//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_1//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_2//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_3//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_4//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_5//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_6uint16_t captureRegister;//! Is the capture mode selected.//! \n Valid values are://! - \b TIMER_A_CAPTUREMODE_NO_CAPTURE [Default]//! - \b TIMER_A_CAPTUREMODE_RISING_EDGE//! - \b TIMER_A_CAPTUREMODE_FALLING_EDGE//! - \b TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGEuint16_t captureMode;//! Decides the Input Select//! \n Valid values are://! - \b TIMER_A_CAPTURE_INPUTSELECT_CCIxA//! - \b TIMER_A_CAPTURE_INPUTSELECT_CCIxB//! - \b TIMER_A_CAPTURE_INPUTSELECT_GND//! - \b TIMER_A_CAPTURE_INPUTSELECT_Vccuint16_t captureInputSelect;//! Decides if capture source should be synchronized with timer clock//! \n Valid values are://! - \b TIMER_A_CAPTURE_ASYNCHRONOUS [Default]//! - \b TIMER_A_CAPTURE_SYNCHRONOUSuint16_t synchronizeCaptureSource;//! Is to enable or disable timer captureComapre interrupt.//! \n Valid values are://! - \b TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE [Default]//! - \b TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLEuint16_t captureInterruptEnable;//! Specifies the output mode.//! \n Valid values are://! - \b TIMER_A_OUTPUTMODE_OUTBITVALUE [Default]//! - \b TIMER_A_OUTPUTMODE_SET//! - \b TIMER_A_OUTPUTMODE_TOGGLE_RESET//! - \b TIMER_A_OUTPUTMODE_SET_RESET//! - \b TIMER_A_OUTPUTMODE_TOGGLE//! - \b TIMER_A_OUTPUTMODE_RESET//! - \b TIMER_A_OUTPUTMODE_TOGGLE_SET//! - \b TIMER_A_OUTPUTMODE_RESET_SETuint16_t captureOutputMode;
} Timer_A_initCaptureModeParam;

Timer_A_initCompareModeParam

//*****************************************************************************
//
//! \brief Used in the Timer_A_initCompareMode() function as the param
//! parameter.
//
//*****************************************************************************
typedef struct Timer_A_initCompareModeParam {//! Selects the Capture register being used. Refer to datasheet to ensure//! the device has the capture compare register being used.//! \n Valid values are://! - \b TIMER_A_CAPTURECOMPARE_REGISTER_0//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_1//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_2//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_3//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_4//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_5//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_6uint16_t compareRegister;//! Is to enable or disable timer captureComapre interrupt.//! \n Valid values are://! - \b TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE [Default]//! - \b TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLEuint16_t compareInterruptEnable;//! Specifies the output mode.//! \n Valid values are://! - \b TIMER_A_OUTPUTMODE_OUTBITVALUE [Default]//! - \b TIMER_A_OUTPUTMODE_SET//! - \b TIMER_A_OUTPUTMODE_TOGGLE_RESET//! - \b TIMER_A_OUTPUTMODE_SET_RESET//! - \b TIMER_A_OUTPUTMODE_TOGGLE//! - \b TIMER_A_OUTPUTMODE_RESET//! - \b TIMER_A_OUTPUTMODE_TOGGLE_SET//! - \b TIMER_A_OUTPUTMODE_RESET_SETuint16_t compareOutputMode;//! Is the count to be compared with in compare modeuint16_t compareValue;
} Timer_A_initCompareModeParam;

定时器A 输出相关函数

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计数值

参数

baseAddress
是TIMER_A模块的基地址

TIMER_A0_BASE
TIMER_A1_BASE
TIMER_A2_BASE

captureCompareRegister

TIMER_A_CAPTURECOMPARE_REGISTER_0
TIMER_A_CAPTURECOMPARE_REGISTER_1
TIMER_A_CAPTURECOMPARE_REGISTER_2
TIMER_A_CAPTURECOMPARE_REGISTER_3
TIMER_A_CAPTURECOMPARE_REGISTER_4
TIMER_A_CAPTURECOMPARE_REGISTER_5
TIMER_A_CAPTURECOMPARE_REGISTER_6

compareRegister

TIMER_A_CAPTURECOMPARE_REGISTER_0
TIMER_A_CAPTURECOMPARE_REGISTER_1
TIMER_A_CAPTURECOMPARE_REGISTER_2
TIMER_A_CAPTURECOMPARE_REGISTER_3
TIMER_A_CAPTURECOMPARE_REGISTER_4
TIMER_A_CAPTURECOMPARE_REGISTER_5
TIMER_A_CAPTURECOMPARE_REGISTER_6

synchronized

TIMER_A_READ_SYNCHRONIZED_CAPTURECOMPAREINPUT
TIMER_A_READ_CAPTURE_COMPARE_INPUT

outputModeOutBitValue

TIMER_A_OUTPUTMODE_OUTBITVALUE_HIGH
TIMER_A_OUTPUTMODE_OUTBITVALUE_LOW

Timer_A_outputPWMParam

//*****************************************************************************
//
//! \brief Used in the Timer_A_outputPWM() function as the param parameter.
//
//*****************************************************************************
typedef struct Timer_A_outputPWMParam {//! Selects Clock source.//! \n Valid values are://! - \b TIMER_A_CLOCKSOURCE_EXTERNAL_TXCLK [Default]//! - \b TIMER_A_CLOCKSOURCE_ACLK//! - \b TIMER_A_CLOCKSOURCE_SMCLK//! - \b TIMER_A_CLOCKSOURCE_INVERTED_EXTERNAL_TXCLKuint16_t clockSource;//! Is the desired divider for the clock source//! \n Valid values are://! - \b TIMER_A_CLOCKSOURCE_DIVIDER_1 [Default]//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_2//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_3//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_4//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_5//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_6//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_7//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_8//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_10//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_12//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_14//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_16//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_20//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_24//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_28//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_32//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_40//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_48//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_56//! - \b TIMER_A_CLOCKSOURCE_DIVIDER_64uint16_t clockSourceDivider;//! Selects the desired timer perioduint16_t timerPeriod;//! Selects the compare register being used. Refer to datasheet to ensure//! the device has the capture compare register being used.//! \n Valid values are://! - \b TIMER_A_CAPTURECOMPARE_REGISTER_0//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_1//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_2//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_3//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_4//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_5//! - \b TIMER_A_CAPTURECOMPARE_REGISTER_6uint16_t compareRegister;//! Specifies the output mode.//! \n Valid values are://! - \b TIMER_A_OUTPUTMODE_OUTBITVALUE [Default]//! - \b TIMER_A_OUTPUTMODE_SET//! - \b TIMER_A_OUTPUTMODE_TOGGLE_RESET//! - \b TIMER_A_OUTPUTMODE_SET_RESET//! - \b TIMER_A_OUTPUTMODE_TOGGLE//! - \b TIMER_A_OUTPUTMODE_RESET//! - \b TIMER_A_OUTPUTMODE_TOGGLE_SET//! - \b TIMER_A_OUTPUTMODE_RESET_SETuint16_t compareOutputMode;//! Specifies the dutycycle for the generated waveformuint16_t dutyCycle;
} Timer_A_outputPWMParam;

compareValue
是比较模式下需要比较的计数值

管理定时器A中断的程序

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中断标志

参数

baseAddress
是TIMER_A模块的基地址

TIMER_A0_BASE
TIMER_A1_BASE
TIMER_A2_BASE

captureCompareRegister

TIMER_A_CAPTURECOMPARE_REGISTER_0
TIMER_A_CAPTURECOMPARE_REGISTER_1
TIMER_A_CAPTURECOMPARE_REGISTER_2
TIMER_A_CAPTURECOMPARE_REGISTER_3
TIMER_A_CAPTURECOMPARE_REGISTER_4
TIMER_A_CAPTURECOMPARE_REGISTER_5
TIMER_A_CAPTURECOMPARE_REGISTER_6

mask

TIMER_A_CAPTURE_OVERFLOW
TIMER_A_CAPTURECOMPARE_INTERRUPT_FLAG

中断向量

TIMERx_A0_VECTOR 是 CCR0 的中断向量
TIMERx_A1_VECTOR 是 TAIV 的中断向量

#define TIMER2_A1_VECTOR        (43 * 1u)                    /* 0xFFD6 Timer2_A5 CC1-4, TA */
#define TIMER2_A0_VECTOR        (44 * 1u)                    /* 0xFFD8 Timer2_A5 CC0 */
#define TIMER1_A1_VECTOR        (48 * 1u)                    /* 0xFFE0 Timer1_A3 CC1-2, TA1 */
#define TIMER1_A0_VECTOR        (49 * 1u)                    /* 0xFFE2 Timer1_A3 CC0 */
#define TIMER0_A1_VECTOR        (52 * 1u)                    /* 0xFFE8 Timer0_A5 CC1-4, TA */
#define TIMER0_A0_VECTOR        (53 * 1u)                    /* 0xFFEA Timer0_A5 CC0 */

上机实战

定时器A 增计数模式CCR0中断

初始化函数

void Timer_A_Init(void)
{Timer_A_initUpModeParam htim = {0};htim.clockSource = TIMER_A_CLOCKSOURCE_ACLK;  //时钟源选为ACLK = 32768Hzhtim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_64;    //64分频htim.timerPeriod = 512 - 1;                                  //计数值设为512 - 1htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE;      //使能CCR0中断htim.timerClear = TIMER_A_DO_CLEAR;  //把定时器的定时计数器,分频计数器的计数值清零htim.startTimer = true;             //初始化后立即启动定时器//中断频率=32768Hz / 64 / 512 = 1HzTimer_A_initUpMode(TIMER_A0_BASE, &htim);//配置定时器A0为增计数模式
}

中断服务函数

#pragma vector=TIMER0_A0_VECTOR
__interrupt
void TIMER0_A0_ISR (void)
{GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN7);   //翻转P4.7
}

整个源文件如下

#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 SystemClock_Init(void)
{PMM_setVCore(PMM_CORE_LEVEL_3);     //高主频工作需要较高的核心电压//XT1引脚复用GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN4);GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN5);//起振XT1UCS_turnOnLFXT1(UCS_XT1_DRIVE_3,UCS_XCAP_3);//XT2引脚复用GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN2);GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN3);//起振XT2UCS_turnOnXT2(UCS_XT2_DRIVE_4MHZ_8MHZ);//XT2作为FLL参考时钟,先8分频,再50倍频 4MHz / 8 * 50 = 25MHzUCS_initClockSignal(UCS_FLLREF, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_8);UCS_initFLLSettle(25000, 50);//XT1作为ACLK时钟源 = 32768HzUCS_initClockSignal(UCS_ACLK, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);//DCOCLK作为MCLK时钟源 = 25MHzUCS_initClockSignal(UCS_MCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);//DCOCLK作为SMCLK时钟源 = 25MHzUCS_initClockSignal(UCS_SMCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);//设置外部时钟源的频率,使得在调用UCS_getMCLK, UCS_getSMCLK 或 UCS_getACLK时可得到正确值UCS_setExternalClockSource(32768, 4000000);
}void Timer_A_Init(void)
{Timer_A_initUpModeParam htim = {0};htim.clockSource = TIMER_A_CLOCKSOURCE_ACLK;htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_64;htim.timerPeriod = 512 - 1;htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_ENABLE;htim.timerClear = TIMER_A_DO_CLEAR;htim.startTimer = true;Timer_A_initUpMode(TIMER_A0_BASE, &htim);//配置定时器A为增计数模式
}int main(void)
{WDT_A_hold(WDT_A_BASE);SystemClock_Init();GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN7);Timer_A_Init();//interrupts enabled__bis_SR_register(GIE);while(1){}
}#pragma vector=TIMER0_A0_VECTOR
__interrupt
void TIMER0_A0_ISR (void)
{GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN7);
}

实验结果

如图,成功得到脉宽为1s的方波

定时器A 增计数模式TAIE中断

初始化函数

void Timer_A_Init(void)
{Timer_A_initUpModeParam htim = {0};htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //时钟源选为SMCLK = 25MHzhtim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_5;  //5分频htim.timerPeriod = 25000 - 1;                                 //计数值设为25000 - 1htim.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; //初始化后立即启动定时器Timer_A_initUpMode(TIMER_A0_BASE, &htim);  //配置定时器A为增计数模式
}

中断服务函数

#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_PIN7);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 SystemClock_Init(void)
{PMM_setVCore(PMM_CORE_LEVEL_3);     //高主频工作需要较高的核心电压//XT1引脚复用GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN4);GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN5);//起振XT1UCS_turnOnLFXT1(UCS_XT1_DRIVE_3,UCS_XCAP_3);//XT2引脚复用GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN2);GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN3);//起振XT2UCS_turnOnXT2(UCS_XT2_DRIVE_4MHZ_8MHZ);//XT2作为FLL参考时钟,先8分频,再50倍频 4MHz / 8 * 50 = 25MHzUCS_initClockSignal(UCS_FLLREF, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_8);UCS_initFLLSettle(25000, 50);//XT1作为ACLK时钟源 = 32768HzUCS_initClockSignal(UCS_ACLK, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);//DCOCLK作为MCLK时钟源 = 25MHzUCS_initClockSignal(UCS_MCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);//DCOCLK作为SMCLK时钟源 = 25MHzUCS_initClockSignal(UCS_SMCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);//设置外部时钟源的频率,使得在调用UCS_getMCLK, UCS_getSMCLK 或 UCS_getACLK时可得到正确值UCS_setExternalClockSource(32768, 4000000);
}void Timer_A_Init(void)
{Timer_A_initUpModeParam htim = {0};htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_5;htim.timerPeriod = 25000 - 1;htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE;htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;htim.timerClear = TIMER_A_DO_CLEAR;htim.startTimer = true;//设得中断频率为25MHz / 5 / 25000 = 200HzTimer_A_initUpMode(TIMER_A0_BASE, &htim);//配置定时器A为增计数模式
}int main(void)
{WDT_A_hold(WDT_A_BASE);SystemClock_Init();GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN7);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_PIN7);break;default:break;}
}

实验结果

如图所示,得到100Hz的方波,为所设定时器中断频率的一半。

输入捕获模式测量脉宽长度

初始化函数

先将Timer_A2初始化为连续计数模式
时钟源为SMCLK
将P2.5/TA2.2复用为输入捕获模式
TA2.2对应TIMER_A2_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_2
检测上升沿和下降沿

uint32_t Sign_Counts = 0;
void Timer_A2_Capture_Init()
{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);GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN5);Timer_A_initCaptureModeParam capture_htim = {0};capture_htim.captureRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2;capture_htim.captureMode = TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE;capture_htim.captureInputSelect = TIMER_A_CAPTURE_INPUTSELECT_CCIxA;capture_htim.synchronizeCaptureSource = TIMER_A_CAPTURE_SYNCHRONOUS;capture_htim.captureInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE;capture_htim.captureOutputMode = TIMER_A_OUTPUTMODE_OUTBITVALUE;Timer_A_initCaptureMode(TIMER_A2_BASE,&capture_htim);
}

中断服务函数

TA2.2对应TA2IV_TACCR2
检测到上升沿时记下初始计数值
检测到下降沿后记下结束时计数值,并将溢出次数清零
当被测信号为高电平时,每溢出一次,溢出次数增1,
最终信号长度即溢出次数*计时周期数+结束时计数值-初始计数值

#pragma vector=TIMER2_A1_VECTOR
__interrupt
void TIMER2_A1_ISR (void)
{static uint16_t Overflow_Times = 0;static uint16_t Sign_Begin = 0, Sign_End = 0;switch(TA2IV){case TA2IV_TACCR2:if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)){Sign_Begin = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);}else{Sign_End = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);if(!Overflow_Times)Sign_Counts = Sign_End - Sign_Begin;else{Sign_Counts = (uint32_t)65536 * Overflow_Times + Sign_End - Sign_Begin;Overflow_Times = 0;}}Timer_A_clearCaptureCompareInterrupt(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);break;case TA2IV_TAIFG:if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)){++Overflow_Times;}elseOverflow_Times = 0;Timer_A_clearTimerInterrupt(TIMER_A2_BASE);break;default:break;}
}

被测信号产生

信号产生引脚为P1.2
频率=25MHz/12500/40=50Hz
占空比为1/20=5%
脉宽长度为1/50*5%=1ms
将产生信号的P1.2接至检测信号的P2.5

#define TIMER_PERIOD 12500
void Timer_A0_PWM_Init(void)
{Timer_A_outputPWMParam htim = {0};//P1.2复用输出GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2);//时钟源选为SMCLK = 25MHzhtim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;//分频系数设为40htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_40;//装载值设为12500 - 1htim.timerPeriod = TIMER_PERIOD - 1;//P1.2 对应 TA0.1 故设为TIMER_A_CAPTURECOMPARE_REGISTER_1htim.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;htim.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;//脉宽为1mshtim.dutyCycle = TIMER_PERIOD / 20 ;//P1.2 对应 TA0.1 为TIMER_A0_BASETimer_A_outputPWM(TIMER_A0_BASE, &htim);
}

整个源文件如下

#include "driverlib.h"
#include "MSP430F5529_UART.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 SystemClock_Init(void)
{PMM_setVCore(PMM_CORE_LEVEL_3);     //高主频工作需要较高的核心电压//XT1引脚复用GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN4);GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN5);//起振XT1UCS_turnOnLFXT1(UCS_XT1_DRIVE_3,UCS_XCAP_3);//XT2引脚复用GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN2);GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN3);//起振XT2UCS_turnOnXT2(UCS_XT2_DRIVE_4MHZ_8MHZ);//XT2作为FLL参考时钟,先8分频,再50倍频 4MHz / 8 * 50 = 25MHzUCS_initClockSignal(UCS_FLLREF, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_8);UCS_initFLLSettle(25000, 50);//XT1作为ACLK时钟源 = 32768HzUCS_initClockSignal(UCS_ACLK, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);//DCOCLK作为MCLK时钟源 = 25MHzUCS_initClockSignal(UCS_MCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);//DCOCLK作为SMCLK时钟源 = 25MHzUCS_initClockSignal(UCS_SMCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);//设置外部时钟源的频率,使得在调用UCS_getMCLK, UCS_getSMCLK 或 UCS_getACLK时可得到正确值UCS_setExternalClockSource(32768, 4000000);
}#define TIMER_PERIOD 12500
void Timer_A0_PWM_Init(void)
{Timer_A_outputPWMParam htim = {0};//P1.2复用输出GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2);//时钟源选为SMCLK = 25MHzhtim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;//分频系数设为40htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_40;//装载值设为12500 - 1htim.timerPeriod = TIMER_PERIOD - 1;//P1.2 对应 TA0.1 故设为TIMER_A_CAPTURECOMPARE_REGISTER_1htim.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;htim.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;//脉宽为1mshtim.dutyCycle = TIMER_PERIOD / 20 ;//P1.2 对应 TA0.1 为TIMER_A0_BASETimer_A_outputPWM(TIMER_A0_BASE, &htim);
}uint32_t Sign_Counts = 0;
void Timer_A2_Capture_Init()
{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);GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P2, GPIO_PIN5);Timer_A_initCaptureModeParam capture_htim = {0};capture_htim.captureRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2;capture_htim.captureMode = TIMER_A_CAPTUREMODE_RISING_AND_FALLING_EDGE;capture_htim.captureInputSelect = TIMER_A_CAPTURE_INPUTSELECT_CCIxA;capture_htim.synchronizeCaptureSource = TIMER_A_CAPTURE_SYNCHRONOUS;capture_htim.captureInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE;capture_htim.captureOutputMode = TIMER_A_OUTPUTMODE_OUTBITVALUE;Timer_A_initCaptureMode(TIMER_A2_BASE,&capture_htim);
}int main(void)
{WDT_A_hold(WDT_A_BASE);SystemClock_Init();UART_Init(USCI_A1_BASE, 115200);Timer_A0_PWM_Init();Timer_A2_Capture_Init();//interrupts enabled__bis_SR_register(GIE);while(1){delay_ms(1000);UART_printf(USCI_A1_BASE, "Pulse width: %fms\r\n", 1000.*Sign_Counts/UCS_getSMCLK());}
}#pragma vector=TIMER2_A1_VECTOR
__interrupt
void TIMER2_A1_ISR (void)
{static uint16_t Overflow_Times = 0;static uint16_t Sign_Begin = 0, Sign_End = 0;switch(TA2IV){case TA2IV_TACCR2:if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)){Sign_Begin = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);}else{Sign_End = Timer_A_getCaptureCompareCount(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);if(!Overflow_Times)Sign_Counts = Sign_End - Sign_Begin;else{Sign_Counts = (uint32_t)65536 * Overflow_Times + Sign_End - Sign_Begin;Overflow_Times = 0;}}Timer_A_clearCaptureCompareInterrupt(TIMER_A2_BASE,TIMER_A_CAPTURECOMPARE_REGISTER_2);break;case TA2IV_TAIFG:if(GPIO_getInputPinValue(GPIO_PORT_P2,GPIO_PIN5)){++Overflow_Times;}elseOverflow_Times = 0;Timer_A_clearTimerInterrupt(TIMER_A2_BASE);break;default:break;}
}

MSP430F5529_UART.c

/** MSP430F5529_UART.c**  Created on: 2021年7月25日*      Author: Royic*/
#include "driverlib.h"#include <string.h>
#include <stdarg.h>
#include <stdio.h>
void UART_printf(uint16_t baseAddress, const char *format,...)
{uint32_t length;va_list args;uint32_t i;char TxBuffer[128] = {0};va_start(args, format);length = vsnprintf((char*)TxBuffer, sizeof(TxBuffer)+1, (char*)format, args);va_end(args);for(i = 0; i < length; i++)USCI_A_UART_transmitData(baseAddress, TxBuffer[i]);
}bool UART_Init(uint16_t baseAddress, uint32_t Baudrate)
{float UART_Temp = 0;USCI_A_UART_initParam huart = {0};if(baseAddress == USCI_A0_BASE)         //P3.3, P3.4 = USCI_A0 TXD/RXD{GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3, GPIO_PIN3);GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P3, GPIO_PIN4);}else if(baseAddress == USCI_A1_BASE)    //P4.4, P4.5 = USCI_A1 TXD/RXD{GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P4, GPIO_PIN4);GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN5);}if(Baudrate <= 9600){huart.selectClockSource = USCI_A_UART_CLOCKSOURCE_ACLK;UART_Temp = (float)UCS_getACLK()/Baudrate;}else{huart.selectClockSource = USCI_A_UART_CLOCKSOURCE_SMCLK;UART_Temp = (float)UCS_getSMCLK()/Baudrate;}if(UART_Temp < 16)huart.overSampling = USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION;else{huart.overSampling = USCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION;UART_Temp /= 16;}huart.clockPrescalar = (int)UART_Temp;if(huart.overSampling == USCI_A_UART_LOW_FREQUENCY_BAUDRATE_GENERATION){huart.secondModReg = (int)((UART_Temp - huart.clockPrescalar) * 8);}else{huart.firstModReg = (int)((UART_Temp - huart.clockPrescalar) * 16);}huart.parity = USCI_A_UART_NO_PARITY;huart.msborLsbFirst = USCI_A_UART_LSB_FIRST;huart.numberofStopBits = USCI_A_UART_ONE_STOP_BIT;huart.uartMode = USCI_A_UART_MODE;if (STATUS_FAIL == USCI_A_UART_init(baseAddress, &huart)){return STATUS_FAIL;}//Enable UART module for operationUSCI_A_UART_enable(baseAddress);//Enable Receive InterruptUSCI_A_UART_clearInterrupt(baseAddress, USCI_A_UART_RECEIVE_INTERRUPT);USCI_A_UART_enableInterrupt(baseAddress, USCI_A_UART_RECEIVE_INTERRUPT);return STATUS_SUCCESS;
}//******************************************************************************
//
//This is the USCI_A0 interrupt vector service routine.
//
//******************************************************************************
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR (void)
{uint8_t receivedData = 0;switch (__even_in_range(UCA0IV,4)){//Vector 2 - RXIFGcase 2:receivedData = USCI_A_UART_receiveData(USCI_A0_BASE);USCI_A_UART_transmitData(USCI_A0_BASE,receivedData);break;default:break;}
}//******************************************************************************
//
//This is the USCI_A1 interrupt vector service routine.
//
//******************************************************************************
#pragma vector=USCI_A1_VECTOR
__interrupt void USCI_A1_ISR (void)
{uint8_t receivedData = 0;switch (__even_in_range(UCA1IV,4)){//Vector 2 - RXIFGcase 2:receivedData = USCI_A_UART_receiveData(USCI_A1_BASE);USCI_A_UART_transmitData(USCI_A1_BASE,receivedData);break;default:break;}
}

MSP430F5529_UART.h

/** MSP430F5529_UART.h**  Created on: 2021年7月25日*      Author: Royic*/#ifndef MSP430F5529_UART_H_
#define MSP430F5529_UART_H_#include "driverlib.h"void UART_printf(uint16_t baseAddress, const char *format,...);
bool UART_Init(uint16_t baseAddress, uint32_t Baudrate);#endif /* MSP430F5529_UART_H_ */

实验结果

MSP430F5529 DriverLib 库函数学习笔记(五)定时器A相关推荐

  1. MSP430F5529 DriverLib 库函数学习笔记(十四)看门狗定时器 (WDT)

    目录 硬知识 看门狗定时计数器 (WDTCNT) 看门狗模式 定时计数模式 看门狗定时器中断 时钟故障保护功能 低功耗模式下的看门狗操作 看门狗定时器控制寄存器 WDT_A API (机翻) 参数 上 ...

  2. MSP430F5529 DriverLib 库函数学习笔记(六)定时器A产生PWM波

    目录 1.通过Timer_A_outputPWM配置产生PWM波 初始化函数 计算 修改占空比的函数 整体程序 效果 2.单定时器产生多路PWM信号 初始化函数 实验结果 3.对称PWM信号的产生 初 ...

  3. MSP430F5529 DriverLib 库函数学习笔记(七)定时器B

    目录 硬知识 Timer_B特点及结构 Timer_B寄存器 定时器B API 处理计时器配置和控制的函数 参数 处理计时器输出的函数 参数 管理定时器B中断的函数 参数 平台:Code Compos ...

  4. MSP430F5529 DriverLib 库函数学习笔记(四点五)printf打印输出

    目录 代码实现 使相应工程支持打印浮点数 实验结果 平台:Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP ...

  5. MSP430F5529 DriverLib 库函数学习笔记(十五)SFR 模块

    目录 API (机翻) SFR管理中断的函数 SFR 管理RST/NMI引脚控制的函数 参数 平台:Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ ...

  6. MSP430F5529 DriverLib 库函数学习笔记(十六)比较器B Comp_B

    目录 硬知识 比较器B介绍 比较器 B 的特点 比较器 B 的结构 模拟输入部分 比较部分 基准电压部分 低通滤波部分 比较器和普通运放的区别 比较器B测量电阻原理 利用比较器B实现电容触摸按键原理 ...

  7. MSP430F5529 DriverLib 库函数学习笔记(八)模数转换模块(ADC12)

    目录 硬知识 模数转换概述 MSP430单片机ADC12模块介绍 MSP430单片机ADC12模块操作 ADC12的转换模式 采样和转换 转换存储器 使用片内集成温度传感器 ADC12模块寄存器 AD ...

  8. MSP430F5529 DriverLib 库函数学习笔记(二)GPIO

    目录 硬知识 一.MSP430单片机端口概述 二.通用IO端口输出特性 三.端口P1和P2 1.输入寄存器PxIN 2.输出寄存器PxOUT 3.方向寄存器PxDIR 4.上拉/下拉电阻使能寄存器Px ...

  9. MSP430F5529 DriverLib 库函数学习笔记(十二)I2C实战

    目录 上机实战 I2C给 DAC 芯片 DAC7571 写入数字量 DAC7571 介绍 程序分析 引脚复用 I2C 初始化 发送一个字节 发送一个字 读取一个字节 读取多个字节 中断服务函数 整体代 ...

最新文章

  1. 一文读懂MQTT协议
  2. C#人爱学不学9[C#5.0异步实例+WPF自己的MVVM Async应用 1/12]
  3. python医学应用_数据分析工具鄙视链:Python、R语言是老大,Excel只能称小弟?
  4. python中def fun(a、b=200)_python 基础 函数
  5. Flowable 数据库表结构 ACT_HI_DETAIL
  6. 计算机的复数英语怎么读,英语的复数怎么读
  7. Prometheus+Grafana PG监控部署以及自定义监控指标
  8. 年轻人还在讨论要不要躺平时,阿里已经注册了“躺平”商标
  9. Facebook 开源 3D 深度学习函数库 PyTorch3D,也可用于二维场景
  10. 字符编码过滤器中对特殊的路径进行特殊处理
  11. CSDN账号注销问题
  12. 笔记本电脑运行卡顿的真正原因和解决方案
  13. format mla_MLA Format MLA格式
  14. CentOS上如何顺利地安装MySQL?
  15. 【区块链基础】2——BTC区块结构
  16. 任务三、学生喂养三种宠物:猫、狗和鸟
  17. 史上最全的NB-IoT知识,每个通信人都应该了解的
  18. c语言——数字特征值题
  19. Selenium基于Python的web自动化测试框架(1)-环境搭建
  20. 共模电感适用的频率_共模电感磁芯的选择决定其性能和应用场景——原文转自金昊德官网...

热门文章

  1. hdu 确定比赛名次
  2. cardsui-for-android
  3. MVC3.0+DWZ探索
  4. django时间问题和时区设置
  5. 一起谈.NET技术,.NET4.0 之 Dynamic VS Reflection 效率
  6. WP7基础学习---第九讲
  7. 转载:关于爱情、伴侣、承诺、人生、
  8. 点到点链路上的OSPF协议
  9. 交替最小二乘矩阵分解_使用交替最小二乘矩阵分解与pyspark建立推荐系统
  10. 使用协同过滤推荐电影