您的位置 首页 元件

关于单片机的using运用

C51的中断函数的格式为:voidFuncIr(void)interruptx[usingy]以下是梦游的一些分析:一、中断函数是一个特殊的函数,没有参数,…

C51的中止函数的格局为:void FuncIr(void) interrupt x [using y]

以下是梦游的一些剖析:
一、中止函数是一个特其他函数,没有参数,也没有回来值;可是程序中允不答应运用return呢?答案是答应的,不过只能用”return;”,不能用”return(z);”;用在一些需求快速回来的当地,对应的汇编会有多个ret句子,相对功率会高一些。
二、using的用法,using能够润饰任何函数,不过个人主张只用来润饰中止函数;简略的说,“using”会指定作业寄存器组,由于中止函数一般都是比较紧迫的作业,有时一条句子都会锱铢必较,所以运用using切换寄存器组能够省去一些压栈的动作,由于51只需两级中止,同级中止不能被打断,因而,咱们能够同级中止设成相同的寄存器组,从某种意义上来说,有一组寄存器是剩余的。一起个人主张中止函数应该运用using这个关键字。
三、中止中调用函数,首要要评论中止函数中调用函数的必要性,前天在论坛上我和他人争论过这个问题,现在我仍是这个观念:有些状况中止中调用函数仍是必要的,这个时分是不是该调用函数,其实和一般函数差不多,首要是这个函数假设调用屡次,或许要带一些参数什么的就愈加必要的;前天有人跟我叫劲,说假设只调用一次且无参数无回来的函数要直接写,由于假设用函数,至少会添加CALL和RET两条句子,我不敢苟同,我是实践调试发现的,当你程序比较复杂时,你将那部独自拉出来做成函数,或许代码和时刻都会更好。
四、中止中调用的函数最好不要被中止外的其它函数调用,由于会呈现“重复调用”的正告,有时这种调用是很丧命的,有人说这个函数能够用reentrant来润饰,是的,确实能够这样处理,不过个人不主张这么做,或许这样会跟你削减许多仓库空间,并且整个程序的优化要差许多,个人主张呈现这种状况就把这个函数写两遍,分红两个函数别离调用。
五、中止调用了函数,会呈现一些不行思议的问题,一些数据不对(我现在遇到这个问题)其实一般是由于汇编中运用了肯定寄存器引起的,有人说中止函数运用那个寄存器组,被中止调用的函数就运用哪个寄存器组(我以为好参阅C51.PDF:Functions called from an interrupt procedure must function with the same register bank as the interrupt procedure. When the NOAREGS directive is not explicitly specified, the compiler may generate absolute register accesses using the register bank selected (by the using attribute or by the REGISTERBANK control) for that function. Unpredictable results may occur when a function assumes a register bank other than the one currently selected. Refer to “Register Bank Access” on page 124 for more information.),我以为这样欠好:
这样会添加额定的耗费,运用using会添加一下句子:
PUSH PSW
MOV PSW, #XX
….
POP PSW
更重要的是,运用using的函数不能有回来值(这个当地有问题,应该能够有回来值,下文说是不能不能回来bit类型的值),这是丧命伤(所以这不是丧命伤,能够运用using处理这个问题)
个人引荐的方法有两种:
1、运用“#pragma NOAREGS”制止运用肯定寄存器
2、运用“#pragme RB(x)”来指定本文件的作业寄存器组
六、一般说来,要求中止函数尽或许的短,但也有特别状况,有些前/后台的体系中,就会把许多相对重要的作业放到守时中止(这个守时中止相似实时操作体系中的时钟节拍)去做,并且程序很长。我独自提出来这点是想告知我们,中止函数也是一个函数罢了,只需体系有必要,能够做一些看似不合理的作业,该出手时就出手,就像goto句子相同。

转自http://www.ednchina.com/blog/hotchip/,请我们去他的博客中支撑他,里边有不错的文章。括号中是我的了解
关于using:
举个比如来说:
界说一个函数
void func(unsigned char i) {

}
有如下一个中止函数
void int_0(void) interrupt 0 using 1 {
….
}
在默许状态下,func运用寄存器组0(BANK0),那么当int_0调用func时是否存在当传递参数时会形成参数传递过错?
假设在中止服务函数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的低两位挑选。在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关键字的运用,假设没把握,宁可不必,交给编译体系自己去向理好了。

比如

用上using能够精简代码,节约仓库,不过有时会呈现一个问题:
用上using ,在中止服务程序里调用函数要当心一点,由于keil C有时会发生依靠肯定地址的代码,例如如下函数,功用是从片外的存储设备中读取一个字节:
uchar ReadByte(uchar address)
{
retrun PBYTE[address];
}
会被编译成如下代码:
MOVR0,0x07
MOVXA,@R0
MOVR7,A
这时,假设在中止服务程序里调用 ReadByte(0xAA); 就会发现读出的数据底子不对,由于using 1使得中止服务程序在调用函数时运用第一组寄存器传递参数,编译器生成的代码如下:
MOVR7,#0xAA
LCALLReadByte
而ReadByte这个函数的代码是运用肯定地址为0x07的第0组寄存器的R7来传递参数的,所以会出问题。
处理方法是在界说ReadByte这个函数的前面加上”#pragma noaregs”,这样编译器就会生成不依靠于肯定地址的代码了,函数ReadByte被编译生成的代码如下:
XCHA,R0
MOVA,R7
XCHA,R0
MOVXA,@R0
MOVR7,A
这样就能够斗胆的运用using了,运用using才是充分利用51架构的运用方法。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/yuanjian/276718.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部