中断介绍

什么是中断?

在C语言中是没有中断的,一个标准的C语言程序,是从main函数开始执行的,main函数退出或者标准库中定义的一些退出函数被调用,程序也就结束了。对于单片机系统,如果硬件发生了一些事件需要应用程序立即来处理,这就需要用到中断了。要CPU立即暂停执行即将执行的指令,去执行一些特定的指令,执行完成之后再回到暂停的位置继续执行,这种机制就叫中断。

中断的优势

  • 让硬件可以把事件通知到软件,提高了响应的实时性。
  • 实现异常处理,提高了系统的稳定性。
  • 提高CPU的效率。注意:如果中断太频繁,由于频繁的保存和恢复现场会导致CPU的效率下降。

中断相关的几个概念

中断源

发生中断的外设,例如定时器事件到了,那么中断源就是定时器。

全局中断开关或总中断

系统中有很多中断开关,如果需要一次性关闭所有的中断,那么就需要用全局中断才行,也就是一个总中断,可以理解为一个电路的总电源吧。

中断使能寄存器

控制是否允许产生中断,也就是这个模块的中断开关,使能就是打开的意思,只有打开状态才允许产生中断,可以理解为在总电源下面的一个小的支路。

中断标志

表示是一个外设的那个具体事件发生了,比如说串口UART1,只有一个中断服务程序,硬件可以产生发送数据完成中断和接收数据完成中断,那么需要有个标志在中断服务程序中让程序知道具体的事件。

中断服务程序

当中断发生的时候要执行的函数,通常需要扩展的语法来编写。

中断优先级

如果CPU当前在执行低优先级的中断,这时候有高优先级的中断发生了,那么CPU会保存当前上下文环境,去执行高优先级的中断服务程序,高优先级的执行完之后会返回来继续执行低优先级的中断服务程序。直到所有的中断服务程序都执行完了,才会返回到原来被中断的位置继续执行。

寄存器分析

中断优先级

根据下图,可以看出,中断被分为了5组,有4个优先级,IP1_xx是优先级的高位,IP0_xx是优先级的低位。

codesys 外部 中断 外部中断c语言_codesys 外部 中断

所有的中断源

根据下图可以看出共有18个中断源。

codesys 外部 中断 外部中断c语言_服务程序_02

中断相关寄存器示意图

根据图片可以看出,外部中断的开关下面几个寄存器决定:

  • P0ICON 选择中断触发的边沿。0表示上升沿触发(低电平跳变为高电平);1表示下降沿触发(高电平跳变为低电平)。
  • P0IEN P0口的引脚中断开关,配置引脚是否允许触发中断。
  • P0IE P0口中断开关,配置P0端口的8个引脚是否允许中断。
  • EA 全局中断(总中断)开关。
  • P0IF P0口的中断标志,表示P0口是否发生了中断。
  • P0IFG 中断标志,表示那个引脚发生了中断。

codesys 外部 中断 外部中断c语言_codesys 外部 中断_03

具体实现

中断的初始化

//按键中断配置
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,不然可能发生不可预料的行为(见参考手册)。
  • 不要使用外部中断来实现按键检测,按键抖动会导致多次执行中断服务程序的。可以在中断服务程序中打上断点,测试一下就知道了。