C51的中止函数的格局为:void FuncIr(void) interrupt x [using y]
interrupt和using都是C51的关键字。C51中止进程经过运用interrupt关键字和中止号(0到3)来完成,中止号指明晰中止程序的进口地址。有了这一声明,编译器不需理睬寄存器组参数的运用和对累加器A、状况寄存器、寄存器B、数据指针和默许的寄存器的维护。只需在中止程序中用到,编译器会把它们压栈,在中止程序结束时将他们出栈。C51支撑一切5个8051规范中止(从0到4)和在8051系列(增强型)中多达27个的中止源。
using关键字用来指定中止服务程序运用的寄存器组。用法是:using后跟一个0到3的数,对应着4组作业寄存器。一旦指定作业寄存器组,默许的作业寄存器组就不会被压栈,这将节约32个处理周期,由于入栈和出栈都需求2个处理周期。这一做法的缺陷是一切调用中止的进程都有必要运用指定的同一个寄存器组,不然参数传递会产生过错。因而关于using,在运用中需灵敏取舍。
假设在ISR(中止服务函数)中运用寄存器,那么有必要处理好using的运用问题:
1、中止服务函数运用using指定与主函数不同的寄存器组(主函数一般运用Register bank 0)。
2、中止优先级相同的ISR可用using指定相同的寄存器组,但优先级不同的ISR有必要运用不同的寄存器组,在ISR中被调用的函数也要运用using指定与中止函数相同的寄存器组。
3、假设不必using指定,在ISR的进口,C51默许挑选寄存器组0,这相当于中止服务程序的进口首要履行指令:MOV PSW #0
这点确保了,没运用using指定的高优先级中止。能够中止运用不同的寄存器组的低优先级中止。
4、运用using关键字给中止指定寄存器组,这样直接切换寄存器组而不必进行许多的PUSH和POP操作,能够节约RAM空间,加快MCU履行时刻。寄存器组的切换,总的来说比较简略犯错,要对内存的运用状况有比较明晰的知道,其正确性要由你自己来确保。特别在程序中有直接地址拜访的时分,一定要小心翼翼!至于“什么时分要用到寄存器组切换”,一种状况是:当你企图让两个(或以上)作业一起运转,并且它们的现场需求一些阻隔的时分,就会用上了。在ISR或运用实时操作体系RTOS中,寄存器十分有用。
寄存器组运用的准则:
1、8051的最低32个字节分红4组8寄存器。别离为寄存器R0到R7。寄存器组由PSW的RS1(PSW^4)、RS0(PSW^3)两位挑选。在ISR中,MCU能够切换到一个不同的寄存器组。对寄存器的拜访不行位寻址,C51编译器规则运用using或制止中止的函数(#pragma disable)均不能回来bit类型的值。
2、主程序(main函数)运用一组,如bank 0;低中止优先级的一切中止均运用第二组,如bank 1;高中止优先级的一切中止均运用其他一组,如bank 2。明显,同级其他中止运用同一组寄存器不会有问题,由于不会产生中止嵌套;而高优先级的中止则要运用与低优先级中止不同的一组,由于有或许呈现在低优先级中止中产生高优先级中止的状况。编译器会主动判别何时可运用肯定寄存器存取。
3、在ISR中调用其它函数,有必要和中止运用相同的寄存器组。当没用NOAREGS指令做清晰的声明,编译器将运用肯定寄存器寻址办法拜访函数选定(即用using或REGISTERBANK指定)的寄存器组,当函数假定的和实践所选的寄存器组不一起,将产生不行预知的成果,然后或许呈现参数传递过错,回来值或许会在过错的寄存器组中。
举一比如:当需求在中止内和中止外调用同一个函数,假定依照程序的流程操控,不会呈现函数的递归调用现象,这样的调用会不会呈现问题?若确认不会产生重入状况,则有以下两种状况:
1、假设ISR和主程序运用同一寄存器组(主程序缺省运用BANK 0,若ISR没有运用using为其指定寄存器区,则缺省也运用BANK 0),则不需其他设置。
2、假设ISR和主程序运用不同的寄存器组(主程序缺省运用BANK 0,ISR运用using指定了其他BANK),则被调用函数有必要放在:#pragma NOAREGS和#pragma AREGS操控参数对中,指定编译器不要对该函数运用肯定寄存器寻址办法;或许也可在Options->C51,选中“Dont use absolute register accesses”,使一切代码均不运用肯定寄存器寻址办法(这样,履行功率将稍有下降)。不管以上的哪一种状况,编译器均会给出重入正告,需手艺更改OVERLAY参数,做重入阐明。
3、还有一种办法:假设被调用函数的代码不是很长,仍是将该函数仿制一份,用不同的函数名替代,这种状况合适ROM有满足剩余的空间。
因而,对using关键字的运用,假设没把握,宁可不必,交给编译体系自己去向理好了。
————————————————————————————————
以下是梦游的一些剖析:
一、中止函数是一个特别的函数,没有参数,也没有回来值;可是程序中允不答应运用return呢?答案是答应的,不过只能用”return;”,不能用”return(z);”;用在一些需求快速回来的当地,对应的汇编会有多个reti句子,相对功率会高一些。
二、using的用法。using能够润饰任何函数,不过个人主张只用来润饰中止函数;简略的说,“using”会指定作业寄存器组,由于中止函数一般都是比较紧迫的作业,有时一条句子都会锱铢必较,所以运用using切换寄存器组能够省去一些压栈的动作,由于51只需两级中止,同级中止不能被打断,因而,咱们能够同级中止设成相同的寄存器组,从某种意义上来说,有一组寄存器是剩余的。一起个人主张中止函数应该运用using这个关键字。
三、中止中调用函数,首要要评论中止函数中调用函数的必要性,前天在论坛上我和他人争论过这个问题,现在我仍是这个观念:有些状况中止中调用函数仍是必要的,这个时分是不是该调用函数,其实和一般函数差不多,首要是这个函数假设调用屡次,或许要带一些参数什么的就愈加必要的;前天有人跟我叫劲,说假设只调用一次且无参数无回来的函数要直接写,由于假设用函数,至少会添加CALL和RET两条句子,我不敢苟同,我是实践调试发现的,当你程序比较复杂时,你将那部独自拉出来做成函数,或许代码和时刻都会更好。
四、中止中调用的函数最好不要被中止外的其它函数调用,由于会呈现“重复调用”的正告,有时这种调用是很丧命的,有人说这个函数能够用reentrant来润饰,是的,确实能够这样处理,不过个人不主张这么做,由于这样会削减许多仓库空间,并且整个程序的优化要差许多,个人主张呈现这种状况就把这个函数写两遍,分红两个函数别离调用。
五,中止调用了函数,会呈现一些不可思议的问题,一些数据不对。其实一般是由于汇编中运用了肯定寄存器引起的,有人说中止函数运用哪个寄存器组,被中止调用的函数就运用哪个寄存器组,我以为这样欠好:
这样会添加额定的耗费,运用using会添加一下句子:
更重要的是,运用using的函数不能有回来值,这是丧命伤。
个人引荐的办法有两种:
1、运用“#pragma NOAREGS”制止运用肯定寄存器
2、运用“#pragma RB(x)”来指定本文件的作业寄存器组
六、一般说来,要求中止函数尽或许的短,但也有特别状况,有些前/后台的体系中,就会把许多相对重要的作业放到守时中止(这个守时中止相似实时操作体系中的时钟节拍)去做,并且程序很长。我独自提出来这点是想告知我们,中止函数也是一个函数罢了,只需体系有必要,能够做一些看似不合理的作业,该出手时就出手,就像goto句子相同。