关于单片机的using使用
寄存器寻址方式访问函数选定(即用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架构的使用方法。
单片机usin 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)