原文:http://iamlinda1978.i.sohu.com/blog/view/108212475.htm interrupt 函数属性当包含在一个声明中指定函数为一个中断函数例如 unsigned int interruptcnt; unsigned char second; void timer0 (void) interrupt 1 using 2 { if (++interruptcnt == 4000) { /* count to 4000 */ second++; /* second counter */ interruptcnt = 0; /* clear int counter */ } interrupt 属性的参数为0 到31 的整常数值 函数属性用来选择和非中断程序不同的寄存器组 带操作数的表达式和interrupt 属性在函数原型中是不允许的 interrupt 属性影响如下函数的目标代码 1. SFR ACC B DPH DPL 和PSW 的内容在需要时在函数调用时保存 在堆栈中 2. 在中断函数中所用的寄存器如果不用using 属性指定一个寄存器组就保 存在堆栈中 3. 保存在堆栈中的寄存器和SFR 在退出函数前恢复 4. 函数由指令RETI 终止 另外Cx51 编译器自动产生中断矢量 下面的规则适用于中断函数 1.中断函数没有函数参数如果中断函数声明中带参数编译器就产生错误信 息 2.中断函数声明不能包含返回值必须声明为VOID 参考上面的例子如 果定义了一个返回值编译器就产生一个错误暗含的int 返回值被编译 器忽略 3.编译器不允许直接的对中断函数的调用对中断函数的直接调用是无意义 的因为退出程序指令RETI 影响8051 的硬件中断系统因为没有硬件存在 中断请求本指令的结果是不确定的通常是致命的不要通过一个函数指 针间接调用一个中断函数 4.编译器对每个中断函数产生一个中断矢量矢量的代码是跳转到中断函数的 起始在Cx51 命令行可用NOINTVECTOR 控制命令禁止产生中断矢量 在这种情况必须从单独的汇编模块提供中断矢量参考INTVECOTOR 和 INTERVAL 控制命令 5.Cx51 编译器的中断号为0-31 参考具体的派生的8051 文件决定可用的中 断 6.从一个中断程序中调用函数必须和中断使用相同的寄存器组当没用 NOAREGS 明确的声明编译器将使用绝对寄存器访问函数选择用using 或REGISTERBANK 控制的寄存器组当函数假定的和实际所选的寄存 器组不同时将产生不可预知的结果. 举一例子:当需要在中断内和中断外调用同一个函数,假定按照程序的流程控制,不会出现函数的递归调用现象,这样的调用会不会出现问题?若确定不会发生重入情况,则有以下两种情况: 1、如果 ISR 和主程序使用同一寄存器组(主程序缺省使用BANK 0,若 ISR 没有使用 using 为其指定寄存器区,则缺省也使用 BANK 0),则不需其他设置。 2、如果 ISR 和主程序使用不同的寄存器组(主程序缺省使用BANK 0,ISR 使用 using 指定了其他 BANK),则被调用函数必须放在: #pragma NOAREGS #pragma AREGS 控制参数对中,指定编译器不要对该函数使用绝对寄存器寻址方式;或者也可在 Options->C51,选中“Don't use absolute register accesses”,使所有代码均不使用绝对寄存器寻址方式(这样,执行效率将稍有降低)。不论以上的哪一种情况,编译器均会给出重入警告,需手工更改 OVERLAY 参数,做重入说明。 3、还有一种办法:如果被调用函数的代码不是很长,还是将该函数复制一份,用不同的函数名代替,这种情况适合ROM有足够多余的空间。 因此,对using关键字的使用,如果没把握,宁可不用,交给编译系统自己去处理好了。 |
|