关于MSP430中断的使用
多个中断请求发生时,响应最高优先级中断。响应中断时,MSP430会将不可屏蔽中断控制位SR.GIE复位。因此,一旦响应了中断,即使有优先级更高的可屏蔽中断出现,也不会中断当前正在响应的中断,去响应另外的中断。但SR.GIE复位不影响不可屏蔽中断,所以仍可以接受不可屏蔽中断的中断请求。
中断响应的过程:(1)如果CPU处于活动状态,则完成当前指令;(2)若CPU处于低功耗状态,则退出低功耗状态;(3)将下一条指令的PC值压入堆栈;(4)将状态寄存器SR压入堆栈;(5)若有多个中断请求,响应最高优先级中断;(6)单中断源的中断请求标志位自动复位,多中断源的标志位不变,等待软件复位;(7)总中断允许位SR.GIE复位。SR状态寄存器中的CPUOFF、OSCOFF、SCG1、V、N、Z、C位复位;(8)相应的中断向量值装入PC寄存器,程序从此地址开始执行。
中断返回的过程:(1)从堆栈中恢复PC值,若响应中断前CPU处于低功耗模式,则可屏蔽中断仍然恢复低功耗模式;(2)从堆栈中恢复PC值,若响应中断前CPU不处于低功耗模式,则从此地址继续执行程序。
MSP430的外部中断资源丰富,P1口和P2口共16个IO口都可以作为外部中断源。
要想让一个IO口作为外部中断的中断源必须有三个设置。
第一,必须将该IO口的方向设置为输入;第二,选择外部中断的触发方式,即选择是上升沿触发还是下降沿触发;第三,使能该IO口的中断。
比如,如果我们想设置P1.0口作为外部中断源就可以这样设置:
P1DIR&= ~BIT0;//方向设置为输入
P1IES |= BIT0;//触发方式设置
P1IE |=BIT0;//使能中断
其中触发方式设置中0为上升沿触发、1为下降沿触发。设置完成之后就可以使用P1.0端口的下降沿或者上升沿触发的外部中断了。
需要特别说明的是如果在一个设计程序中如果用到了中断,那么在使用中断之前必须使能总中断。使能总中断的语句是:_EINT(); 就像我们如果想开A、B、C三个灯,我们除了需要把A、B、C三个灯的开关打开之外还需要把总电源开关打开,不然的话灯还是不会亮的。相应的关闭总中断的语句是:_DINT();
#include<msp430F169.h> //自定义数据结构,方便使用 #define uchar unsigned char #define uint unsigned int #define ulong unsigned long /* * 软件延时函数 */ #define CPU_F ((double)8000000) //外部高频晶振8MHZ #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)) /* * 端口初始化 */ void Init_IO(){ P2SEL = 0x00; P2DIR = 0xF0; //高4位为输出模式,低4位为输入模式 } /* * 键盘扫描 */ uchar key_scan(){ uchar a=1,s,count=1; uchar value=0; for(a=1;a<0x10;a<<=1){ P2DIR = 0xFF; P2OUT = 0x00; P2DIR=0x0f; P2OUT=a; if(P2IN!=a){ if(0x10&P2IN) //这里是设置按键,S1、S2、S3分别对应0x20、0x40、0x80 s=0; value=s*4+count; } count++; } return value; } /** * 主函数 */ void main(void) { WDTCTL = WDTPW + WDTHOLD; //关看门狗 _DINT(); //关中断 Init_IO(); P6DIR = 0xff; P6OUT = 0xff; while(1){ if(key_scan()==0) continue; else P6OUT = key_scan(); delay_ms(500); } }

浙公网安备 33010602011771号