中断
MSP430F149内部有三种类型中断:系统复位中断,不可屏蔽中断,可屏蔽中断
中断过程
①完成当前正在执行的指令﹔
②把PC寄存器内容入栈;
③把SR寄存器内容入栈;
④如果同时有多个中断,则选择优先级最高的中断;
⑤如果中断是单源中断,则中断标志位自动复位;如果中断是多源中断,则需要中断服务程序复位;
⑥SR清零,结束低功耗模式。由于GIE被清除,其他的中断被屏蔽。因此,中断不能被嵌套;
7.中断向量被装入PC寄存器,并从该地址开始执行中断服务程序。
中断向量表
系统复位中断
POR PUC
不可屏蔽中断
外部管脚NMI的触发(也就是所说的复位模式)
标志位:OFIFG
Flash非法访问
标志位:ACCVIFG
振荡器不稳定
标志位:NMIIFG
可屏蔽中断
状态寄存器SR中的下标为3的GIE位为总中断允许控制位,这是区分是否屏蔽的主要依据
16个外部中断
特点
多元中断:2组8个中断(必须软件清零标志位)
只有边缘跳变中断
引脚配置
(以引脚P2.1为例)
P2DIR |= BIT1; //配置P2.1方向为输入模式
P2IE |= BIT1; //配置P2.1的中断使能
P2IES |= BIT1; //配置P2.1为下降沿中断响应
其他寄存器可配置,可不配置。引脚功能选择为一般引脚,不是功能引脚。
中断函数配置
(以引脚P2.1为例)
#pragma vector =PORT2_VECTOR
__interrupt void tangle_make(void)
{
//用户自定义函数
P2IFG = 0x00; //中断标志位软件清零
}
定时器中断
Timer_A,Timer_B,处于定时模式的看门狗
寄存器配置
//定时模式示例
CCTL0 = CCIE; // 捕获/比较中断使能
CCR0 = 6000; // 比较值为8000,即从0计数到8000产生一次中断
TACTL = TASSEL_2 + MC_1+TACLR; // 使用SMCLK时钟,使用增计数模式,清零TACCR寄存器
//捕获模式示例
TACTL = TACLR + TASSEL_2 + ID_3 + MC_3; //清零TACCR寄存器,使用SMCLK时钟,8分频,使用增减计数模式
TACCTL0 = CM_2+ CCIS_0 + SCS + CAP + CCIE; //设置为 下降沿捕获,捕获通道0,同步捕获,捕捉模式,捕获/比较中断使能
TACCTL1 = CM_3 + CCIS_1 + SCS + CAP + CCIE; //设置为 上升下降沿捕获,捕获通道1,同步捕获,捕捉模式,捕获/比较中断使能
//PWM输出模式示例
TACTL |= TASSEL_2 + ID_3 + MC_2 + TACLR + TAIE; //使用SMCLK时钟,8分频,使用连续计数模式,清零TACCR寄存器,定时器溢出中断
TACCTL0= CCIE;
CCR0 = 5000;
中断函数配置
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void) //定时器A中断服务程序
{
switch(TAIV)
{
case 2:
******
break;
case 4:
******
break;
case 10:
******
break;
}
}
使用独立按键作为外部中断控制LED灯,并在数码管显示
#include <msp430x14x.h>
unsigned char Seg_code[]={0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80};
// SEG 数字0—9 共阳
unsigned char Seg_Wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xff};
// 位选
unsigned char Flag = 0;
void Port_Init()
{
P1DIR = 0x00; //P1端口设置为输入模式
P1IE = 0xff; //P1端口多元中断使能
P1IES = 0xff; //P1端口下降沿触发中断
P3DIR = 0xff; //P3端口设置为输出模式
P3OUT = 0xff; //P3端口输出高电平
P5DIR = 0x07; //P4端口设置为输出模式 P5.0=STCP P5.1=SHCP P5.2=DS
P5OUT = 0xff; //P4端口输出高电平
}
void Clock_Init()
{
unsigned char i;
BCSCTL1 = RSEL0 + RSEL1 + RSEL2; // 采用最高频率7 ACLK = XT2
BCSCTL1&=~XT2OFF; //打开XT2振荡器
do
{
IFG1 &= ~OFIFG; // 清除振荡器失效标志
for (i = 255; i > 0; i--); // 延时,等待XT2起振
}
while ((IFG1 & OFIFG) != 0); // 判断XT2是否起振
BCSCTL2 |= SELS+SELM_2; // SMCLK = MCLK = XT2
}
void WR_595(unsigned char Data) //要写入的数据
{
unsigned char i;
for(i=0;i<8;i++)
{
if(Data&0x80)
P5OUT|=0x04;
else
P5OUT&=0xfB;
P5OUT|=0x02; // SHCP=1; 上升沿
P5OUT&=0xfD;
Data<<=1; //从高位开始取数据
}
P5OUT|=0x01; //STCP=1;
P5OUT&=0xfe; // STCP=0;
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; //关闭看门狗
Port_Init();
Clock_Init();
//_BIS_SR(LPM0_bits + GIE); // _BIS_SR(LPM0_bits + GIE) 具有同时打开全局中断和进入LPM0; 等同于:_EINT(); LPM0;
// 如果只使用定时器之类的功能时,可以使用低功耗模式,而不使用while(1)
_EINT();
while(1)
{
switch(Flag)
{
case 1:
{
P3OUT = 0xfe;
WR_595(Seg_Wei[0]);
WR_595(Seg_code[0]);
break;
}
case 2:
{
P3OUT = 0xfd;
WR_595(Seg_Wei[1]);
WR_595(Seg_code[1]);
break;
}
case 3:
{
P3OUT = 0xfb;
WR_595(Seg_Wei[2]);
WR_595(Seg_code[2]);
break;
}
case 4:
{
P3OUT = 0xf7;
WR_595(Seg_Wei[3]);
WR_595(Seg_code[3]);
break;
}
case 5:
{
P3OUT = 0xef;
WR_595(Seg_Wei[4]);
WR_595(Seg_code[4]);
break;
}
case 6:
{
P3OUT = 0xdf;
WR_595(Seg_Wei[5]);
WR_595(Seg_code[5]);
break;
}
case 7:
{
P3OUT = 0xbf;
WR_595(Seg_Wei[6]);
WR_595(Seg_code[6]);
break;
}
case 8:
{
P3OUT = 0x7f;
WR_595(Seg_Wei[7]);
WR_595(Seg_code[7]);
break;
}
}
Flag = 0;
P5OUT&=0xfe;
P5OUT|=0x01;
while(Flag == 0);
}
}
#pragma vector=PORT1_VECTOR
__interrupt void PORT_1 (void) //外部中断P1中断服务程序
{
switch(P1IFG)
{
case 0x01:
Flag = 1;
break;
case 0x02:
Flag = 2;
break;
case 0x04:
Flag = 3;
break;
case 0x08:
Flag = 4;
break;
case 0x10:
Flag = 5;
break;
case 0x20:
Flag = 6;
break;
case 0x40:
Flag = 7;
break;
case 0x80:
Flag = 8;
break;
}
P1IFG = 0x00;
}