AN2001


CREATE: 2008/12/30
UPDATE: 2010/06/25
Version 1.1

   AN2001 中断系统的应用

概述

除了PLC系统使用的中断服务,GUTTA平台向PLC程序的编写者开放了一部分中断接口用于配置和编程。中断的发生使PLC放弃当前正在执行的任务转而去执行中断对应的任务。主循环扫描是PLC的一般性任务,它在PLC上电启动后重复执行且优先级最低,因此它可以被其他任何中断事件打断。不同的中断有不同的优先级。多个中断同时发生时,先运行中断优先级高的任务,然后运行中断优先级低的任务。GUTTA系统中中断的使用主要包括中断事件与中断函数的连接,中断函数的程序编写这两部分内容。

纯粹的单片机控制器开发一般说来有下面几种形式:

  • 1. 循环模式:所有的工作都在主循环中完成。中断不被使能。这种模式最简单。
  • 2. 中断模式:所有的工作都在中断中完成。一但进入主循环就开始休眠。这种模式通常在低功耗设计中采用。
  • 3. 前后台模式:这种模式是前面两种模式的结合,一方面主循环程序在不停的工作,用于处理一般性逻辑或者运算。另一方面中断也是允许的,中断服务程序用于处理对响应要求较高的事件。
  • 4. 合作调度模式:在这种模式下,任务是程序的组织单元。中断程序里不执行任务,而是设置标志。中断结束后返回被中断的任务。该任务结束后调度系统根据前面中断设置的标志决定是否运行该中断对应的任务。需要注意的是,调度系统只有在某个任务结束后才会工作。因此任何任务的运行时间都不应该设计得太长,否则会导致其他任务被阻塞。
  • 5. 抢占调度模式:在抢占式调度模式下,中断不仅可以设置该中断对应任务的标志,如果需要的话,还可以打断当前任务。当前任务的现场由调度系统保存以等待其他任务运行结束后恢复。抢占式调度模式一般需要使用支持抢占的实时操作系统。

GUTTA PLC系统本质上也是一个单片机程序。为了保证系统的最简化,GUTTA采用了合作调度模式。在PLC正常运行的情况下,主循环重复调用PLC程序中的MAIN(INT0)函数。从PLC的使用者看来,MAIN(INT0)就是PLC的主循环。其余对PLC用户开放的中断只设置中断标志。与普通合作调度模式相比,最大的优点是:PLC程序是一条指令一条指令执行的。不论是解释型PLC,还是编译型PLC,也不论是在主循环程序中,还是在中断程序中,在每条PLC指令执行完后,系统都会对中断发生标志进行检查并决定是否中断当前任务。这样即使每个PLC函数程序很复杂耗时很长,中断的响应时间也最多不过是一条PLC指令的时间。

应用

指令介绍

在GUTTA系统中,中断的使用主要包括中断事件与中断函数的连接,中断函数的程序编写这两部分内容。若需要连接中断事件与函数,就需要用到ATCH指令。ATCH指令有两个操作数:中断函数号INT、中断事件号EVENT。中断函数号INT应该是一个无符号单整数:数值1就表示中断函数INT1,数值2就表示中断函数INT2,依此类推。中断事件号EVENT也是一个无符号单整数。数值的含义由PLC的实现定义。

    EVENT含义

EVENT NAME
0INT_EVENT_INPUTP0外部中断0
1INT_EVENT_INPUTP1外部中断1
2INT_EVENT_TIMER0时间中断0
3INT_EVENT_TIMER1时间中断1
4INT_EVENT_TIMER_SECOND秒中断
5INT_EVENT_INPUTP2外部中断2
6INT_EVENT_INPUTP3外部中断3

    EVENT和实际硬件中断的对应关系

EVENT NAME CPU-EC20 (AVR) CPU-EC20 (8051) CPU-EC20 (Cortex-M3)
0INT_EVENT_INPUTP0INT7EXT1EXTI1_IRQHandler
1INT_EVENT_INPUTP1
2INT_EVENT_TIMER0TIMER0_OVFTIMER1_OVFSysTickHandler
3INT_EVENT_TIMER1TIMER0_OVFTIMER1_OVFSysTickHandler
4INT_EVENT_TIMER_SECONDINT5 (PCF8563T)EXT0 (PCF8563T)RTC_IRQHandler
5INT_EVENT_INPUTP2
6INT_EVENT_INPUTP3

    EVENT和实际硬件中断的对应关系(PLC核)

EVENT NAME EC30-EK51 EC30-EKSTM32
0INT_EVENT_INPUTP0EXT0EXTI*_IRQHandler
1INT_EVENT_INPUTP1EXT1EXTI*_IRQHandler
2INT_EVENT_TIMER0TIMER1_OVFSysTickHandler
3INT_EVENT_TIMER1TIMER1_OVFSysTickHandler
4INT_EVENT_TIMER_SECONDRTC_IRQHandler
5INT_EVENT_INPUTP2EXTI*_IRQHandler
6INT_EVENT_INPUTP3EXTI*_IRQHandler

例如ATCH 1,2表示中断函数INT1连接时间中断0。这也就意味着若时间中断0到达,PLC系统就自动调用中断函数INT1。

有中断连接指令ATCH,就有中断分离指令DTCH。和指令ATCH相反,指令DTCH取消中断事件与函数的连接。这个指令的操作数只有一个:EVENT。操作数EVENT的含义和ATCH指令中操作数EVENT含义一致。执行DTCH指令后,EVENT中断事件相关的连接关系被取消。一个EVENT只能挂接一个中断函数INT,一个中断函数INT可以同时服务于多个EVENT。

有的时候,不希望某些程序被中断,就可以使用中断禁止指令DISI。指令DISI全局性的禁止所有中断。等这段程序结束后,再运行中断允许指令ENI。指令ENI全局性的允许所有中断。在中断禁止的这段时间,若发生了中断,对应的中断标志依然被置位但是不立即执行对应的中断函数,而是延迟到中断允许后执行。

PLC系统在复位后进入主循环扫描时,所有中断是被禁止的。

最简单的例子

http://www.plcol.com/technologies/anindex/an2001/Sample1.vcw

这个程序创建了3个中断函数:

第1个函数是主循环MAIN(INT0):

SM0.1是PLC热启动标志位。PLC每次启动后,SM0.1在第一个扫描周期保持为ON。第一个扫描周期结束后被系统设置为OFF。MAIN只有一个梯级,具体操作是:在系统热启动后,将I0.1上升沿事件和中断函数INT_1(INT1)进行连接;将时间中断0事件和中断函数INT_2(INT2)进行连接;同时允许中断。由于SM0.1只在第一个扫描周期保持为ON,主循环扫描设置好中断后以后,就不进行任何操作了。

第2个函数是中断INT_1,这个中断和I0.1上升沿事件相关联:

这个函数很简单,每执行一次,将MW0自加1。其实也就是用MW0来记录INT_1(INT1)的调用次数。

第3个函数是中断INT_2,这个中断和时间中断0事件相关联:

这个函数很简单,每执行一次,将MW2自加1。其实也就是用MW2来记录INT_2(INT2)的调用次数。

同时,在系统块编辑窗口中设定时间中断0的时间间隔:

这里时间间隔设置为50ms。也就是说每过50ms产生一个时间中断0事件。

将本程序下载到实验板或者是PLC模拟器GUTTA Simulator中,进入监控模式,观察变量MW0和MW2的变化。通过实验我们可以发现,每当按下I0.1时,MW0发生一次自加。MW2则根据时间连续的自加,由于中断事件设置为50ms,意味着MW2每秒自加20次(1000ms / 50ms = 20)。

中断打断主循环的证明

下面的这个程序是中断打断主循环的证明:

http://www.plcol.com/technologies/anindex/an2001/Sample2.vcw

这个程序创建了2个中断函数:

第1个函数是主循环MAIN(INT0):





这个函数说明如下:

第2个函数是中断INT_1(INT1),这个中断和I0.1上升沿事件相关联:

这个函数很简单,每执行一次,将MW0自加1。

将本程序下载到实验版或者是PLC模拟器GUTTA Simulator中,进入监控模式,观察变量的值。

如上图,不断的点击输入I0.1。直到Q0.0被置位。

观察主循环函数MAIN(INT0)。MW0在NETWROK 1被设置为1234,延时一段时间后在NETWORK 5中判断MW0的值。由于MW0的值发生了改变,最终Q0.0被置位。这说明主循环MAIN(INT0)的执行被中断。INT_1(INT1)的INCW MW0指令是造成MW0的值发生改变的唯一理由。