keil C51绝对地址访问
在利用keil进行8051单片机编程的时,常常需要进行绝对地址进行访问.特别是对硬件操作,如DA AD 采样 ,LCD 液晶操作,打印操作.等等.
C51提供了三种访问绝对地址的方法:
1. 绝对宏
在程序中,用“#include<absacc.h>”即可使用其中定义的宏来访问绝对地址,包括:CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD 具体使用可看一看absacc.h便知
例如:
rval=CBYTE[0x0002] ;指向程序存贮器的0002h地址 rval=XWORD[0x0002] ;指向外RAM的0004h地址
2. _at_ 关键字
直接在数据定义后加上_at_ const即可,但是注意:
(1)绝对变量不能被初使化;
(2)bit型函数及变量不能用_at_指定。
例如:
idata struct link list _at_ 0x40 ;指定list结构从40h开始。 xdata char text[25b] _at_ 0xE000 ;指定text数组从0E000H开始
提示:如果外部绝对变量是I/O端口等可自行变化数据,需要使用volatile关键字进行描述,请参考absacc.h。
3. 连接定位控制
此法是利用连接控制指令code xdata pdata \data bdata对“段”地址进行,如要指定某具体变量地址,则很有局限性,不作详细讨论。
附:(c51)
/*-------------------------------------------------------------------------- ABSACC.H Direct access to 8051, extended 8051 and Philips 80C51MX memory areas. Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. --------------------------------------------------------------------------*/ #ifndef __ABSACC_H__ #define __ABSACC_H__ #define CBYTE ((unsigned char volatile code *) 0) #define DBYTE ((unsigned char volatile data *) 0) #define PBYTE ((unsigned char volatile pdata *) 0) #define XBYTE ((unsigned char volatile xdata *) 0) #define CWORD ((unsigned int volatile code *) 0) #define DWORD ((unsigned int volatile data *) 0) #define PWORD ((unsigned int volatile pdata *) 0) #define XWORD ((unsigned int volatile xdata *) 0) #ifdef __CX51__ #define FVAR(object, addr) (*((object volatile far *) (addr))) #define FARRAY(object, base) ((object volatile far *) (base)) #define FCVAR(object, addr) (*((object const far *) (addr))) #define FCARRAY(object, base) ((object const far *) (base)) #else #define FVAR(object, addr) (*((object volatile far *) ((addr)+0x10000L))) #define FCVAR(object, addr) (*((object const far *) ((addr)+0x810000L))) #define FARRAY(object, base) ((object volatile far *) ((base)+0x10000L)) #define FCARRAY(object, base) ((object const far *) ((base)+0x810000L)) #endif #endif
附:(c166)
/*-------------------------------------------------------------------------- ABSACC.H Direct access to 166 memory areas for C166/EC++ Version 5. Copyright (c) 1992-2004 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. --------------------------------------------------------------------------*/ #ifndef __ABSACC_H__ #define __ABSACC_H__ #if (__MODEL__ == 0) #define MVAR(object, addr) (*((object volatile *) (addr))) #define MARRAY(object, base) ((object volatile *) (base)) #else #define MVAR(object, addr) (*((object volatile far *) (addr))) #define MARRAY(object, base) ((object volatile far *) (base)) #define HVAR(object, addr) (*((object volatile huge *) (addr))) #define HARRAY(object, base) ((object volatile huge *) (base)) #define XVAR(object, addr) (*((object volatile xhuge *) (addr))) #define XARRAY(object, base) ((object volatile xhuge *) (base)) #endif #endif
使用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
MyBuf1[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?MAIN(0x28),如果是pdata,则使用?PD?MAIN(0x28)
3、堆栈定位:
在STARTUP.A51文件中定义了堆栈区?STACK,其起始地址同样可以在BL51 Locate页中设置,在Stack栏写上?STACK(0x80)
BL51 locate 选项卡中code range 和 xdata range如果不填写,编译默认将程序中相应代码和变量从空间前面取起
网上看到有人提到在keil中使用_at_进行绝对地址定位问题,我简单介绍一下它的用法。
使用_at_关键字对存储器进行绝对地址定位程序如下
#include<reg51.h>
] _at_ 0x8000;
main()
{
LED_Data[] = 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复位后要保持变量不变,防止意外改变(比如升级到新程序,变量地址可能被编译器优化到其他地方),比较有用!!!!
STARTUP.A51 这个文件有什么用,有必要添加到工程吗?
如果不添加"startup.a51"文件,编译器就会自动加入一段初始化内存以及堆栈等的代码,这时的内存初始化部分你就无法去控制了,当然这在大部分情况下没什么关系。但是如果你想你的程序在复位后,内存里面的信息依然还保存着(所说的“热复位”),那么你就需要添加该启动文件,并且去里面修改内存初始化部分,不要初始化你需要保留的部分内存。
如何在keil编译器里,编程时指定函数的绝对地址 (无内容)
不好意思啊,我还从来没有接触过有这样要求情况,不过从网上其他地方找了一篇你参考一下吧,函数定位:假如要把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、若有多个变量或函数要进行绝对地址定位,则应按地址从低到高的顺序排列。
keil C51绝对地址访问的更多相关文章
- 51单片机C语言学习笔记4:keil C51绝对地址访问
在利用keil进行8051单片机编程的时,常常需要进行绝对地址进行访问.特别是对硬件操作,如DA AD 采样 ,LCD 液晶操作,打印操作.等等.C51提供了三种访问绝对地址的方法: 1. 绝对宏: ...
- KEIL C51高级编程
第一节 绝对地址访问C51提供了三种访问绝对地址的方法: 1. 绝对宏:在程序中,用“#include”即可使用其中定义的宏来访问绝对地址,包括:CBYTE.XBYTE.PWORD.DBYTE.CWO ...
- Keil C51 知识点
第一节 Keil C51扩展关键字 深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一.因为大多数扩展功能都是直接针对8051系列CPU硬件的.大致有以下8类: 8051存储类型 ...
- keil C51 指针总结
变量就是一种在程序执行过程中其值能不断变化的量.要在程序中使用变量必须先用标识符作为变量名,并指出所用的数据类型和存储模式,这样编译系统才能为变量分配相应的存储空间.定义一个变量的格式如下: [存储种 ...
- Keil C51 中指针的使用
指针是C语言中比较难的一个内容,Keil C51在指针方面有和标准C不一样的地方,今天看了一些资料学习了一下Keil C51 中指针的使用. keil51的指针,包含两种指针:普通指针,兼容标准C:内 ...
- keil c51笔记
第一章 Keil C51开发系统基本知识 第一节 系统概述 Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上.结构性.可读性. ...
- Keil C51中变量的使用
引言 8051内核单片机是一种通用单片机,在国内占有较大的市场份额.在将C语言用于51内核单片机的研究方面,Keil公司做得最为成功.由于51内核单片机的存储结构的特殊性,Keil C51中变量的使用 ...
- Keil C51 vs 标准C
深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一.因为大多数扩展功能都是直接针对8051系列CPU硬件的.大致有以下8类: 8051存储类型及存储区域 存储模式 存储器类型声明 变量类 ...
- Keil C51里关于堆栈指针的处理
Keil C是非常优秀的C51编译器,可能是最好的C51编译器,提供各种优化模式,对变量的优化和地址安排做得非常好.这是用C语言写代码的好处之一,如果用汇编写,得费一大番功夫给各个变量安排内存物理地址 ...
随机推荐
- jquery常用见的正则表达式
quickexpr = /^(?:[^<]*(<[ww]+>)[^>]*$|#([w-]+)$)/ (?:…)表示是一个非捕获型 [^<]表示是以"<& ...
- spring mvc使用ClassPathXmlApplicationContext或FileSystemXmlApplicationContext和XmlWebApplicationContext类的操作其中 XmlWebApplicationContext是专为Web工程定制的。
一.简单的用ApplicationContext做测试的话,获得Spring中定义的Bean实例(对象).可以用: ApplicationContext ac = new ClassPathXmlAp ...
- 谈论C++当然结果
C++编程课程的考试已经结束.这是第一次OJCBT.摸着石头过河,考试没有给学生理解的说法.现在尘埃落定.一些交代. 先说大的成就的治疗原则.事实上,有很多的纠结. 按理说,合格的太,无法挂.但实际情 ...
- How to load jars residing over NFS in JBossAS7 classpath ? --reference
In this article we will discuss how can we load jars residing over NFS in JBoss AS-7 classpath. In s ...
- ubuntu12.10中没有/etc/inittab文件探究
1. 我们首先来看一下Linux系统开机启动过程: Ubuntu是Linux系统的衍生系统,其开机启动过程与上图相差不大,但是随着系统的不断发展,终究还是有不同的地方,下面,我们来了解一下Ubuntu ...
- 几句话实现导航栏透明渐变 – iOS
首先我们来看下效果 一开始当我们什么只设置了一张图片作为它的头部视图的时候,它是这样的 首当其冲的,我们先得把导航栏弄透明 那么我们首先得知道,设置navigationBar的BackgroundCo ...
- url编码解码-js编码、C#编码
JS编码解码 函数一定义和用法encodeURI() 函数可把字符串作为 URI 进行编码. 语法 encodeURI(URIstring) 参数 描述 URIstring 必需.一个字符串,含有 U ...
- Linux入门之——安装虚拟机软件
/** ****************************************************************************** * @author 暴走的小 ...
- 连接管理VMware SphereESXi
连接管理VMware SphereESXi 1. 准备 下载VMware-viclient-all-5.5.0-1993072,并按照提示安装 2. 使用VMware Sphere Client链接事 ...
- 开源的Android开发框架-------PowerFramework使用心得(二)图片异步加载ImageTask
图片异步加载.可以备注图片是否缓存.缓存状态. 1.缓存-SD卡,路径可设置 2.图片压缩 3.可加载本地和网络图片 4.url为本地视频文件可以显示缩略图 5.中文url图片地址FileNotFou ...