1.11 可重入函数和中断函数 |
|
Keil C51编译器在标准C语言函数上提供了很多扩展。
① 使用关键字reentrant指定函数是否可重入或可递归。
② 使用关键字interrupt将某函数定义为中断函数。
③ 使用关键字using选择函数使用的寄存器组。
在ANSI C中调用函数时,函数参数及局部变量将被压栈,但由于8051单片机内部堆栈空间有限,为提高效率,Keil C51没有默认提供这种堆栈方式,它为每个函数设置固定空间,用于存放局部变量。正是因为这种特征,普通Keil C51函数不能被递归调用,函数重入时,此前的参数值和局部变量将被覆盖。
定义为可重入的函数允许在函数体内调用自身,可重入函数在被递归调用或多重调用时不必担心变量被覆盖。因为每次调用时局部变量会被单独保存(压栈),如果编写的单片机C函数必须重入,则函数需要参照下面的示例编写:
在设计递归程序时必须将递归函数声明为reentrant,这一点不同于标准C语言函数。另外,在单片机程序中,如果一般函数Function1和中断函数INT_Fx都可能调用同一个函数Comm1,那么Comm1也必须设为可重入。虽然这种调用并非递归调用,因为Function1正在调用Comm1时,中断事件的发生会使中断函数INT_Fx打断Function1对它的调用,开始也调用Comm1,这时Comm1必须具有保护现场的能力,因此reentrant关键字是必需的。
中断函数也称中断服务程序、中断例程、中断例行程序等,中断函数设计是单片机C语言程序设计技术中的重要内容。下面是一个中断函数示例,中断号由interrupt关键字设置:
中断函数调用与普通C函数调用是不一样的,中断事件发生后示例中的“T0_INT”中断函数被自动调用,它没有函数参数,也没有返回值。用interrupt关键字将某函数设为中断函数会对生成的目标代码带来如下影响:
① 在必要时特殊功能寄存器ACC、B、DPH、DPL及PSW的内容被保存到堆栈中。
② 如果没有使用using关键字指明寄存器组,中断函数中的所有工作寄存器将被保存到堆栈中。
③ 退出中断函数时,所有保存在堆栈中的工作寄存器及特殊功能寄存器被恢复。
④ 函数由8051的RETI指令中止并返回。
⑤ 另外,Keil C51编译器会为中断函数自动生成中断向量。
上述代码中的using 1使中断函数使用寄存器组1,using可选择0~3,它们代表8051单片机的4个寄存器组,在中断函数中用using设置寄存器组,可使中断函数不使用堆栈保存和恢复数据。对于本书案例中的中断函数,调试时可自行添加using关键字选择寄存器组。