简要理解MSP430的中断(以IO和定时器为例)

感觉应该会有很多刚刚学单片机的人跟我一样最初对中断有挺大疑惑,今天就简单写一写目前我对于中断的理解吧。
我呢首先接触的是FPGA,由于FPGA是并行运算,所以里面是没有中断的。而MSP430是串行运算,程序只能一个一个执行,于是在430中需要中断。
一、基本
那么什么是中断呢。我们可以认为是放下目前要做的事A,去做另外的事B,做完B后再回来继续做A。比如说我们要写一个程序,中途渴了要去喝水,我们喝完水后再继续写程序。停止写程序就相当于中断,而喝水就相当于是中断里面做的事情。中断里面做的事情就是中断函数。,
把它类比到函数中,写程序就相当于main函数,那么去喝水就相当于是中断函数。
430中的IO中的一部分、定时器、USCI等都具有中断功能。
二、各种中断(其实只有IO和定时器)
1、IO中的中断。
F5529中有多个IO port,但只有其中的P1和P2具有中断功能,g2553中也只有P1P2具有中断,这个可以在user’s guide的IO部分找到。
IO的中断的判断条件是输入/输出电平变化的上下沿,上沿或是下沿可以配置。
主义是输入/输出电平,也就是输入电平改变可以触发中断,而把端口设置为输出然后改变输出电平同样可以触发中断!
话不多说,上一个我学的时候写的一个测试程序
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include <msp430.h>
///用来测试2.0的中断功能
/*

  • main.c
    /
    #define CPU_F ((double)8000000)
    #define delay_us(x) __delay_cycles((long)(CPU_F
    (double)x/1000000.0))
    #define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
    int main(void) {
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
    P4DIR|=BIT0+BIT3; //4.3 4.0为输出检测口
    P4OUT|=BIT0; //初始状态P4.0为高电平
    P4OUT&=~BIT3; //初始状态P4.3为低电平
    P2DIR&=~BIT0; //2.0为中断测试口
    P2IES|=BIT0;//设置为下降沿触发,即检测到4.0的高电平变成了低电平从而出发中断
    P2IFG=0; //清除中断IFG标志
    P2IE|=BIT0;//中断使能添加
    delay_ms(1000);
    P4OUT&=~BIT0; //P4.0变为低电平
    _EINT(); //启用总中断

}
#pragma vector = PORT2_VECTOR
__interrupt void PORT2_ISR(void)
{
//-----启用Port2事件检测函数-----
//检测通过,则会调用事件处理函数
if(P2IFG&BIT0)
P4OUT|=BIT3;
P2IFG=0; //退出中断前必须手动清除IO口中断标志
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
这一段程序可以大致了解下P2.0的中断。
将P2.0设置为输入,p4.0位输出。将P4.0和P2.0用杜邦线连接,初始状态P4.0为高电平,一秒后,P4.0输出低电平。可以观察到P4.3的输出改变。为了让现象更加直观,可将4.3换成LED,这样就可以观察LED的亮灭来观察。
而配置的流程大致为:
(1)配置中断触发的上下沿 PxIES
(2)清除IFG(实际上在PUC后IFG就会被程序清除,但是还是可以写一下)
(3)添加中断使能 PxIE
一般这个放在端口配置的最后
(4)_EINT()开启总中断使能,这个是使能总开关,不写的话什么中断都没用
中断函数的基本写法
(1)#pragma vector = PORT2_VECTOR
在不同的中断中用不同的vector,需要改变的只是等号后面部分
这个可以在ccs的头文件中找到,按住ctrl点击像是BIT0这种都可以进入到头文件,然后在这个部分。
在这里插入图片描述
可以找到所有中断的向量表示。
(2)__interrupt void PORT2_ISR(void)
{
}
中断函数,就像C中任意一个函数一样,写上中断里面要做的事情。
2、定时器的中断
上一篇文章里面写了定时器其实还是中断。现在来简单谈一谈用比较器的中断。
比较器中中断发生的条件是计数器中的值与CCR做比较。在UP模式中就是当计数器的值大于CCR就会触发中断。并且在UP模式中,CCR0是计数的终点,当计数到CCR0后,计数器会变为0重新计数。而CCR1等等都不会影响计数。
并且计数器不是由CPU执行计数的,也就是说在CPU执行程序的时候,计数器会独立的计数,这也就是计数器重要的原因!
现在上程序!(只是我练习时候想能不能用CCR2来改变CCR1的值写的一个测试程序)
//////////////////////////////////////////////////////////////////////////////////////////////////////
#include <msp430.h>
//用TA0里面的CCR2来控制CCR1;
/*

  • main.c
    */
    unsigned int t;
    int main(void) {
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
    UCSCTL5=DIVS__2 ; //现在SMCLK为500 000HZ
    t=600;
    P4DIR|=BIT2;
    P4OUT|=BIT2;
    P4DIR|=BIT3;
    P4OUT|=BIT3; //配置IO

    TA0CTL=TASSEL__SMCLK+MC__UP+ID__8+TACLR;
    //配置定时器,时钟选择SMCLK,UP模式,八分频
    TA0CCR0=10000; //CCR0设置为10000,也就是说,当以500000/8的周期计数记//到10000的时候,重新计数
    TA0CCR1=t; //CCR1为t
    TA0CCR2=5000; //CCR2为5000
    TA0CCTL0 = CCIE;
    TA0CCTL1 = CCIE;
    TA0CCTL2 = CCIE;
    //开启每一个捕获器的中断使能
    _EINT(); //开启总中断
    }
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void TIME0_A0_ISR(void)
    {
    P4OUT|=BIT2;
    P4OUT|=BIT3;

}
#pragma vector=TIMER0_A1_VECTOR
__interrupt void TIME0_A1_ISR(void)
{
{
switch(TA0IV)
{
case 2:
{
P4OUT &= ~BIT2;
break;
}
case 4:
{
P4OUT &= ~BIT3;
if(t<8000)
t=t+100;
else
t=600;
TA0CCR1=t; //当CCR2产生中断的时候改变CCR1的值
break;
}
case 10:break;
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
程序不是很好,但是还是可以简单说基本配置的流程
(1)TAxCTL的配置
(2)TAxCCR的配置
所有的CCR中CCR0是最重要的
(3)TA0CCTL0 = CCIE;
让需要中断的比较器中断使能打开
(4)_EINT();开启总中断
(5)中断函数
#pragma vector=TIMER0_A0_VECTOR
#pragma vector=TIMER0_A1_VECTOR
定时器中的CCR0和CCR1的定时器中断向量是不同的,CCR0是一个,而CCR1到其他是另外一个。以此也能够凸显出CCR0的重要性
而正如上一篇文章中讲的,CCR1到往后的CCR写中断函数中需要判断TAxIV。在给的程序中也有体现。

////////////////////////////////////////////////////////////////////////////////////////// 大概就是这个样子吧。至于其他的中断,大同小异。还是看好了user’s guide最重要。初学430,如果有错误请指正。