中断介绍
什么是中断?
在C语言中是没有中断的,一个标准的C语言程序,是从main
函数开始执行的,main
函数退出或者标准库中定义的一些退出函数被调用,程序也就结束了。对于单片机系统,如果硬件发生了一些事件需要应用程序立即来处理,这就需要用到中断了。要CPU立即暂停执行即将执行的指令,去执行一些特定的指令,执行完成之后再回到暂停的位置继续执行,这种机制就叫中断。
中断的优势
- 让硬件可以把事件通知到软件,提高了响应的实时性。
- 实现异常处理,提高了系统的稳定性。
- 提高CPU的效率。注意:如果中断太频繁,由于频繁的保存和恢复现场会导致CPU的效率下降。
中断相关的几个概念
中断源
发生中断的外设,例如定时器事件到了,那么中断源就是定时器。
全局中断开关或总中断
系统中有很多中断开关,如果需要一次性关闭所有的中断,那么就需要用全局中断才行,也就是一个总中断,可以理解为一个电路的总电源吧。
中断使能寄存器
控制是否允许产生中断,也就是这个模块的中断开关,使能就是打开的意思,只有打开状态才允许产生中断,可以理解为在总电源下面的一个小的支路。
中断标志
表示是一个外设的那个具体事件发生了,比如说串口UART1,只有一个中断服务程序,硬件可以产生发送数据完成中断和接收数据完成中断,那么需要有个标志在中断服务程序中让程序知道具体的事件。
中断服务程序
当中断发生的时候要执行的函数,通常需要扩展的语法来编写。
中断优先级
如果CPU当前在执行低优先级的中断,这时候有高优先级的中断发生了,那么CPU会保存当前上下文环境,去执行高优先级的中断服务程序,高优先级的执行完之后会返回来继续执行低优先级的中断服务程序。直到所有的中断服务程序都执行完了,才会返回到原来被中断的位置继续执行。
寄存器分析
中断优先级
根据下图,可以看出,中断被分为了5组,有4个优先级,IP1_xx
是优先级的高位,IP0_xx
是优先级的低位。
所有的中断源
根据下图可以看出共有18个中断源。
中断相关寄存器示意图
根据图片可以看出,外部中断的开关下面几个寄存器决定:
-
P0ICON
选择中断触发的边沿。0表示上升沿触发(低电平跳变为高电平);1表示下降沿触发(高电平跳变为低电平)。 -
P0IEN
P0口的引脚中断开关,配置引脚是否允许触发中断。 -
P0IE
P0口中断开关,配置P0端口的8个引脚是否允许中断。 -
EA
全局中断(总中断)开关。 -
P0IF
P0口的中断标志,表示P0口是否发生了中断。 -
P0IFG
中断标志,表示那个引脚发生了中断。
具体实现
中断的初始化
//按键中断配置
PICTL |= 0x01; //P0_1脚下降沿触发 0表示上升沿触发,1表示下降沿触发
P0IEN |= 0x02; //P0_1脚中断使能
P0IE = 1; //P0端口的中断使能
EA = 1; //全局总中断使能
中断服务函数的实现
//定义中断服务程序
//打上断点调试,按下一次按键由于抖动会进入多次中断服务程序
#pragma vector = P0INT_VECTOR
__interrupt void KeyInterrupt(void)
{
if ((P0IFG & 0x02) == 0x02) {
P0IFG &= ~0x02; //清除这个引脚的中断标志
LED1 = !LED1;
}
//注意:必须在P0IFG标志清除之后再清除
P0IF = 0; //清除P0端口的中断标志
}
注意事项
- 中断服务函数中的实现,需要先清除引脚的中断标志
P0IFG
,然后再清楚端口的中断标志P0IF
,不然可能发生不可预料的行为(见参考手册)。 - 不要使用外部中断来实现按键检测,按键抖动会导致多次执行中断服务程序的。可以在中断服务程序中打上断点,测试一下就知道了。