MSP430F149——中断及案例

    科技2022-07-16  121

    中断

    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; }
    Processed: 0.009, SQL: 8