What
简单来说,单片机出了点事,需要离开程序原有的执行路径,去处理那件更重要的事,等这件事结束后再回到原有的路径。
中断一共有三种类型:
- 系统复位(POR/PUC)
- 不可屏蔽中断 NMI:不能由通用中断使能位 (GIE) 屏蔽
- 可屏蔽中断:可由通用中断使能位 (GIE) 屏蔽
其具体内容可见于用户指南28~37页。在其中需要注意以下内容:
中断服务程序里,不能长时间执行程序。
NMI是一个多源中断,一个中断向量对应多个中断标志,所以用户需要线判断中断为何种中断标志,然后手动清除中断标志。
单源中断标志系统可以自动清除(eg.串口通信中的接收中断和发送中断),多源中断标志需要用户手动清除(eg.上文的NMI)。
中断程序执行时,SR(状态寄存器被清除,这将终止任何低功耗模式1);如果GIE位被清除,之后的中断被禁用;如果中断程序在执行的时候,GIE置位,那在此中断执行时可以停下执行其他中断,无论哪个中断优先级更高。
中断向量实际就是保存中断函数入口地址的存储单元空间。
How
使用各种中断功能时,基本步骤大概为:使能相应中断;配置中断检测标志;选择相应的操作模式以实现低功耗;编写中断处理函数。
举例
将基础I/O章节的Task用中断实现
#include <msp430.h>
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗定时器
P1DIR |= BIT0; // 设置P1.0为输出
P1IE |= BIT3; // 使能P1.3中断
P1IES |= BIT3; // P1.3为下降沿中断
P1REN |= BIT3; // 使能SW2为上下拉 (P1.3)
P1OUT |= BIT3; // 设置SW2为上拉 (P1.3)
P1IFG &= ~BIT3; // P1.3 IFG 中断标志位清除
//BIT3 on Port 1 can be used as Switch2
_BIS_SR(LPM4_bits + GIE); // 进入LPM4模式,并使能中断
}
// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR//#pragma vector 是固定在程序中的格式,后面接的是中端向量地址
__interrupt void Port_1(void)//__interrupt 这个关键字用来指
//定一个函数应该被看成一个中断函数。当你使用
//interrupt 关键字时,编译器会按ISR 函数要求的寄存
//器保存规则去保存寄存器,然后生成一些特殊的返回代码序列(return sequence) 。
{
P1OUT ^= BIT0; // 改变P1.0输出电平
P1IFG &= ~BIT3; // P1.3 IFG 中断标志位清除
}
该程序有一个缺点:未进行按键消抖,宏观上按下一次按键后LED1的状态不确定。
Task
在以上程序基础上增加消抖程序,怎么“消”都行,只看最后效果。
经过学渣改变后的程序如下:
#include <msp430.h>
void Delay_ms(unsigned cnt)
{
unsigned int i,j;
for(j=0;j<cnt;j++)
{
i=1000/6;
while(i--);
}
}
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗定时器
P1DIR |= BIT0; // 设置P1.0为输出
P1IE |= BIT3; // 使能P1.3中断
P1IES |= BIT3; // P1.3为下降沿中断
P1REN |= BIT3; // 使能SW2为上下拉 (P1.3)
P1OUT |= BIT3; // 设置SW2为上拉 (P1.3)
//P1OUT &= ~BIT3; // 使能SW2为下拉 (P1.3)
P1IFG &= ~BIT3; // P1.3 IFG 中断标志位清除
//BIT3 on Port 1 can be used as Switch2
_BIS_SR(LPM4_bits + GIE); // 进入LPM4模式,并使能中断
}
// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
Delay_ms(10); //延时10ms进行按键消抖
if(!(BIT3 & P1IN)) //如果P1.3为低电平表示按键被按下,LED1状态翻转
{
P1OUT ^= BIT0;
}
while(!(BIT3 & P1IN)); //中断程序持续直到检测到按键未被按下
P1IFG &= ~BIT3; // P1.3 IFG 中断标志位清除
}
该程序虽然进行了按键消抖,但在中断程序中较长时间占用了CPU资源。其实还有其他方法可以实现,例如利用定时器定时间间隔检测按键状态后再进入中断。
sao话一下
如果你喜欢上一匹马,不要试图追上它,你肯定追不上。你应该试着去种草种花,等到草长莺飞的季节,这匹马自然会回来找你。 如果这匹马就是不回来找你呢? 没关系,你有了花和草,有了独特的魅力和资本,这匹马不来,别的马会来。
——《余香》
参考用户指南38~40页,简要概括为用户可以根据需要选择需要工作的模块,禁用暂时无用的模块从而降低功耗。 ↩︎