MSP430F5529库函数定时器A——定时中断

目录

定时器A介绍

(1)资源简介

(2)定时器A时钟选择

(3)Timer_A工作模式

 【1】增计数模式(01)

【2】连续计数模式(10)

【3】增减计数模式(11)

 (4)Timer_A中断

函数介绍

Timer_A_startCounter()

函数声明

作用

参数

Timer_A_initUpMode() 

函数声明

作用

参数

中断 

使用

Timer_A_initContinuousMode() 

函数声明

作用

参数

使用

Timer_A_initUpDownMode() 

函数声明

作用

参数

使用

实验

TALE中断

CCIFG0中断

实验现象


MSP430F5529的定时器有定时器A与定时器B,定时器B比定时器A强大一点。这里先只简单介绍定时器A,主要是教你使用库函数,详细资料请看用户手册,其他博客视频教程

定时器A可以硬件输出PWM,脉冲捕获,定时中断。本文只讲定时中断部分

定时器A介绍

(1)资源简介

定时器 A 是一个十六位的定时/计数器,MSP430F5529 中包含有 3 个定时器 A 的子模块 和 7 个捕捉/比较模块。定时器 A 支持多重捕获/比较,PWM 输出和内部定时。定时器还有 扩展中断功能,中断可以由定时器溢出产生或由捕获/比较寄存器产生。定时器 A 的特性包括:

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

 可选择配置的时钟源

 可配置的 PWM 输出

 异步输入和输出锁存

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

(2)定时器A时钟选择

MSP430F5529定时器时钟 TACLK 可以选择 ACLKSMCLK 或者来自外部的 TAxCLK。SMCLK系统默认 1048576Hz,ACLK系统默认为32768Hz。

(3)Timer_A工作模式

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

 【1】增计数模式(01)

此模式下,从0开始计数,可通过TAxCCR0的数值定义定时的周期。TAxCCR0数值小于0FFFFh。

一般用于软件PWM,定时中断。这个用到应该是最多的

【2】连续计数模式(10)

从0开始计数,直至计数到0FFFFh之后从0开始重新计数。与增计数模式不同的是,不能被提前结束,必须是从0计数到0FFFFh。定时周期只能由时钟源频率决定

一般用于捕获脉冲

【3】增减计数模式(11)

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

 (4)Timer_A中断

Timer_A有两个中断向量,CCIFG0中断TAIV中断。后面会有介绍

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

函数介绍

Timer_A_startCounter()

函数声明

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        //增减计数模式

Timer_A_initUpMode() 

函数声明

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);
}

Timer_A_initContinuousMode() 

函数声明

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);

Timer_A_initUpDownMode() 

函数声明

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

因为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;
    }
}


CCIFG0中断

看注释掉的部分,就是要改的地方。 

#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);
}

实验现象

  • 23
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风正豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值