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