6.1 中断及其处理
中断是控制器或处理器为了快速响应及处理外部事件(如按键、触摸屏、AD转换结束、定时器计时到、以及与外部模块接口等等)而采取的一种应对机制。中断就是一种临时打断,如上一讲中的图5.1所示,CPU本来在那儿跑圈,如果我们的程序中允许了某些中断并开启了总中断,则当这些中断事件发生时,CPU就会去响应这些中断,也就是CPU先去处理这些中断事件(或称突发事件)。处理完中断事件后,CPU再返回到原来的被中断点,继续处理它原来的事情。这个过程会涉及到PC(程序计数器)值的变化及SP(堆栈指针)的改变等等,不过PC和SP的变化在我们的C程序中是不可见的,或者说是我们不需要关心的,我们只要写好C程序就一切OK了。
以下程序简单示例了中断及其中断服务程序的编写方法。
例6.1中断及其处理。
/********简单示例中断及其处理********/
#include"msp430.h"
void main(void)
{
WDTCTL=WDTPW+WDTHOLD; //关闭看门狗定时器
BCSCTL3|=LFXT1S_2; //选择 VLO 为低频时钟
P1DIR|=BIT6+BIT0; //P1.0,P1.6 输出
TA0CCTL0=CCIE; //TA0CCR0 中断使能
TA0CCR0=60000; //TA0CCR0预置数
TA0CTL=TASSEL_2+ID_0+MC_1; //选择SMCLK做时钟,不分频,增计数模式
//MC_1:增计数到 CCR0,并产生中断标志
//注:需根据用户手册,了解上述每个寄存器以及寄存器中每
//个位的控制作用。
_EINT(); //开启总中断。注意:先开启总中断,再进入低功耗休眠。
//若顺序颠倒了,先进入了低功耗休眠,则_EINT()就不会被执行了。则
//中断不被允许,也就无法执行中断程序了。
LPM1; //进入低功耗模式1,CPU休眠了。
}
//定时器A中断服务程序,MSP430的定时器中断不需要CPU的干预。
#pragma vector=TIMER0_A0_VECTOR //定时器A0的中断向量,注意:必须严格按此格式书写。
__interrupt void Timer_A_0 (void) //声明一个中断服务程序,名为Timer_A_0()
//注意:interrupt前为两条下划线。
{
P1OUT^=BIT6+BIT0; //P1.0,P1.6的输出值取反。该例中的中断服务程序只有这一//条语句。
} //中断函数(中断服务程序)到此结束
可以在CCS中建立工程,并添加上述程序,然后调试、下载到开发板中,让其运行,观察实验结果。
现在并不要求你对上述例子中各条语句都理解,在后续介绍了相关的模块后,才能明白这些语句的作用和含义,所以无需着急。
有关中断的问题,在后面章节的许多模块中还要涉及,现在只是一个简略的介绍。
以下各图示例了MSP430头文件中的宏定义,包括各寄存器的定义,寄存器中各位的定义等等。知道这些定义有助于我们对寄存器以及寄存器中每个位的理解。这些头文件中的内容千万不要动,不要改变,否则会很麻烦的,除非你很清楚你在干什么。
图6.1 头文件msp430g2553.h中对BIT0、BIT1、…BITF的定义
图6.2 头文件msp430g2553.h中对低功耗模式LPM0、LPM1、…、LPM4的定义
图6.3 头文件msp430g2553.h中对8位寄存器P1IN、P1OUT等等的定义
图6.4头文件msp430g2553.h中对看门狗控制器(WDTCTL)中各个位的定义
下图示例了msp430g2553.cmd文件中对寄存器地址的定义。
图6.5文件msp430g2553.cmd中对寄存器地址的定义
还有许多其它的定义(包括内部函数的定义),就不一一赘述了。有了这些定义,只要在程序中包含了头文件,则这些寄存器就可以被引用了,寄存器中的位可以被操作了,内部函数也可以被调用了。