C51编写中断服务程序
C51编译器支持在C语言源程序中直接编写51单片机的中断服务程序,从而减轻了采用汇编语言编写中断服务程序的繁琐程度。为了能在C语言源程序中直接编写中断服务函数,C51编译器对函数的定义有所扩展,增加了一个扩展关键字interrupt。关键字interrupt是函数定义时的一个选项,加上这个选项即可以将函数定义成中断服务函数。
定义中断服务函数的一般形式如下:
函数类型 函数名(形式参数表)[interrupt n][using n]
Interrupt后面的n是中断号,n的取值范围为0~31,编译器从8n+3处产生中断向量,具体的中断号n和中断向量取决于不同的51系列单片机芯片;using后面的n是所选择的寄存器组,取值为0~3。51单片机常用的中断源和中断向量见表9-5。
表9-5 中断源和中断向量
在进入中断函数时,特殊功能寄存器ACC、B、DPH、DPL、PSW将被保存入栈;如果不使用寄存组切换,则将中断函数中所用到的全部工作寄存器都入栈;函数返回之前,所有的寄存器内容出栈;中断函数由8051单片机指令RETI结束。
编写8051单片机中断程序时应遵循的规则如下:
(1)中断函数不能进行参数传递,如果中断函数中包含任何参数声明都将导致编译出错。
(2)中断函数没有返回值,如果企图定义一个返回值将得到不正确的结果。因此建议在定义中断函数时将其定义为void类型,以明确说明没有返回值。
(3)在任何情况下都不能直接调用中断函数,否则会产生编译错误。因为中断函数的返回是由8051单片机指令RETI完成的,RETI指令影响8051单片机的硬件中断系统。如果在没有实际中断请求的情况下直接调用中断函数,RETI指令的操作结果会产生一个致命的错误。
(4)如果中断函数中用到浮点运算,必须保存浮点寄存器的状态,当没有其他程序执行浮点运算时可以不保存。C51编译器的数学函数库math.h中,提供了保存浮点寄存器状态的库函数fpsave和恢复浮点寄存器状态的库函数fprestore。
(5)如果在中断函数中调用了其他函数,则被调用函数所使用的寄存器组必须与中断函数相同。用户必须保证按要求使用相同的寄存器组,否则会产生不正确的结果,这一点必须引起足够的注意。如果定义中断函数时没有使用using选项,则由编译器选择一个寄存器组作绝对寄存器组访问。另外,由于中断的产生不可预测,中断函数对其他函数的调用可能形成递归调用,需要时可将被中断函数所调用的其他函数定义成再入函数。
(6)C51编译器从绝对地址8n+3处产生一个中断向量,其中n为中断号。该向量包含一个到中断函数入口地址的绝对跳传。在对源程序编译时,可用编译控制指令NOINTVECTOR抑制中断向量的产生,从而使用户能够从独立的汇编程序模块中提供中断向量。
1.中断允许控制寄存器IE
【例9-1】假设允许INT0、INT1、T0、T1中断,试设置IE的值。
解:(1)用C语言字节操作。
IE=0x8F
(2)用C语言位操作指令。
2.中断优先级控制寄存器IP
【例9-2】设定时器和串行口中断为高优先级,两个外部中断为低优先级,试设置IP的值。
解:(1)用C语言。
IP=0x3a
(2)用汇编语言:
使用字节操作指令:
MOV IP,#3AH
使用位操作指令: