KEIL C51之绝对地址定位

单片机空间分配看*.M51文件,ARM,DSP空间分配看*.map文件 

1、函数定位:

假如要把C源文件 tools.c 中的函数

int BIN2HEX(int xx)

{

    ...

}

放在CODE MEMORY的0x1000处,先编译该工程,然后打开该工程的M51文件,在

* * *     C O D E     M E M O R Y     * * *

行下找出要定位的函数的名称,应该形如:

CODE      xxxxH       xxxxH       UNIT           ?PR?_BCD2HEX?TOOLS

然后在:

Project->Options for Target ...->BL51 Locate:Code

中填写如下内容:

?PR?_BCD2HEX?TOOLS(0x1000)

再次Build,在M51中会发现该函数已放在CODE MEMORY的0x1000处了

2.赋初值的变量定位

要将某变量定位在一绝对位置且要赋初值,此时用 _at_ 不能完成,则如下操作:

在工程中建立一个新的文件,如InitVars.c,在其中对要处理的变量赋初值(假设是code变量):

char code myVer = {"COPYRIGHT 2001-11"};

然后将该文件加入工程,编译,打开M51文件,若定义的是code型,则在

* * *     C O D E     M E M O R Y     * * *

下可找到:

CODE      xxxxH       xxxxH       UNIT           ?CO?INITVARS

然后在:

Project->Options for Target ...->BL51 Locate:Code

中填入:

?CO?INITVARS(0x200)

再次编译即可。

相应地,如为xdata变量,则InitVars.c中写:

char xdata myVer = {"COPYRIGHT 2001-11"};

然后将该文件加入工程,编译,打开M51文件,在

* * *    X D A T A     M E M O R Y    * * *

下可找到:

XDATA     xxxxH       xxxxH       UNIT           ?XD?INITVARS

然后在:

Project->Options for Target ...->BL51 Locate:Xdata

中填入:

?XD?INITVARS(0x200)

再次编译即可。相应地,若定义的是data/idata等变量,则相应处理即可。

3、若有多个变量或函数要进行绝对地址定位,则应按地址从低到高的顺序 

使用KeilC51软件,可以很方便地将代码或者数据绝对定位到某个地址。

1、代码定位:

方法1:使用伪指令CSEG。比如要将MyFunc1定位到代码区C:0x1000,则新建一个A51文件,添加以下内容:

PUBLIC  MYFUNC1

CSEG AT 1000H

MYFUNC1:

;其它代码

RET

在其它源文件中,就可以调用MyFunc()函数了。需要注意的是,编译器不检测传递参数的数目,仅检测函数是否有返回值。

方法2:使用BL51 Locate选项。比如在main.c中定义了一个MyFunc2函数,并且要将该函数定位到代码区C:0x2000,则从菜单中选择Project->Options for Target 'Target1',在弹出的对话框中选择BL51 Locate页,在下面的code栏中写上?PR?MYFUNC2?MAIN(0x2000)即可。

如果想定位多个函数,也可以使用*通配符。

2、变量定位:

只有全局变量可以绝对定位,局部变量无法实现绝对定位。

方法1:使用_at_关键字。声明一个全局变量unsigned char data

yBuf1[8] _at_ 0x20;

方法2:使用BL51 Locate选项。比如将main.c中定义的所有data型的全局变量定位到数据区D:0x28开始的空间,则从菜单中

选择Project->Options for Target 'Target1',在弹出的对话框中选择BL51 Locate页,在下面的data栏中写上?DT?MAIN(0x28)即可。

如果是idata,则使用?ID?MAIN(0x28),如果是xdata,则使用?XD?

AIN(0x28),如果是pdata,则使用?PD?MAIN(0x28)

3、堆栈定位:

在STARTUP.A51文件中定义了堆栈区?STACK,其起始地址同样可以在BL51 Locate页中设置,在Stack栏写上?STACK(0x80)

还可以通过汇编实现

// my.a51

public my_flash_var

cseg at 0F100H

my_flash_var:

db 55h

end

然后C声明

// flash.c

extern unsigned char code my_flash_var;

BL51 locate 选项卡中

code range 和 xdata range如果不填写,编译默认将程序中相应代码和变量从空间前面取起

网上看到有人提到在keil中使用_at_进行绝对地址定位问题,我简单介绍一下它的用法。

使用_at_关键字对存储器进行绝对地址定位程序如下

#i nclude<reg51.h>

char xdata LED_Data[50] _at_ 0x8000;

main()

{

  LED_Data[0] = 0x23;

}

在keil中运行以上程序可以在存储器窗口中输入 x:0x8000 可以看到0x8000地址中的值为0x23.

值得指出的几点是

1.在给变量LED_Data[50]定位绝对地址空间时,不能对其赋初值。

2.char xdata LED_Data[50] _at_ 0x8000;这条语句不能主函数中。有些网友提到在按着keil说明中用_at_进行绝对地址定位时,编译会出现错误274,就是将这条语句放在主函数中的原因。

3.keil中地址是自动分配的,所以除非特殊情况否则不提倡使用绝对地址定位。初学者因帖别注意。不要把c当作汇编使用。

对需要/RST复位后要保持变量不变,防止意外改变(比如升级到新程序,变量地址可能被编译器优化到其他地方),比较有用!!!!

永不止步步 发表于04-15 10:25 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67417个|学分:363741个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号