② 中断子程序使用自己专用的寄存器组。这种情况下不需要保存R0~R7的内容,可以减少堆栈需求,其他的内容仍需要压栈保护。中断发生时,保存中断子程序的返回地址需要2个字节。中断发生后,在中断子程序中系统会自动进行如下操作:将ACC、B、DPH、DPL、PSW共5个寄存器压栈。加上、中断返回地址,这种堆栈的需
求为7个字节。但是这种情况应该注意:如果中断子程序中调用子函数,且函数需要参数和返回值,则被调用的子函数和中断子程序要使用相同的寄存器组,否则会出现不可预料的后果。以一个温度测试系统为例。系统采用8051作为处理器,温度信号在A/D转换结束后通过外部中断0提醒单片机接收处理。定时中断0作为监控程序,中断周期为20 ms。温度信号可以自动测量(每秒一次)或者手动测量(按测量键后测量),这两种测量方法可以通过控制键切换。中断子程序和普通子函数的嵌套情况为:在定时中断程序中调用显示子程序,外部中断0内部没有函数调用。部分程序如下:
接下来分析这段程序的最大堆栈需求。假设定时器0中断时,调用了显示函数void leddisp(unsigned char *pt),在调用显示函数时A/D转换结束发生了外部中断0的中断。这时应该是程序对堆栈的最大需求,堆栈的大小是:定时器0(15字节)+显示函数(2字节)+外部中断0(7字节)=24字节。
结语
通过精确的计算编译系统分配给用户的堆栈空间和用户自己最大的堆栈需求,不仅能从根本上解决堆栈溢出的问题,还可以很好地安排单片机比较紧张的资源。此外,通过在片内存储器存放适量局部变量,还可以有效地提高软件的执行速度。