首页 > 编程知识 正文

51单片机xdata,单片机xdata

时间:2023-05-06 07:29:38 阅读:124508 作者:4590

就数据存储类型而言,8051系列包括片上、片外程序存储器、片上和片外数据存储器。 片上程序存储器还分为直接地址区域和间接地址类型,分别对应于根据code、data、xdata、idata和51系列的特点设定的pdata类型,使用不同的存储器时会出现程序编写C51程序时与ANSI-C略有不同,分为SAMLL、COMPACT、LARGE模式,每种模式对应不同的实际硬件系统,也能得到不同的编译结果。

在51系列中,data、idata、xdata、pdata的区别data:固定了前面0x00-0x7f的128个RAM,能够直接在acc上读写,是最快的,生成的代码也最小。 idata:固定是指前一个0x00-0xff的256个RAM。 其中,前面的128和data的128完全相同,只是访问方法不同。 idata以类似于c的指针方式访问。 程序集中的语句是mox

ACC,@Rx.(不重要的补充:在c中,idata提供指针式访问是有效的(xdata:外部扩展RAM通常指向外部0x0000-0xffff空间,通过DPTR访问)。

pdata:外部扩展RAM的低位256字节,地址出现在A0-A7上时读写,使用movx

ACC,@Rx读写。 这很特殊,而且C51上好像有这个漏洞,所以建议不要使用。 但是,也有他的优点,具体的使用方法是中级的问题,所以在这里不提及。

startup.a51的作用

与程序集一样,在c中定义的变量和数组的初始化在startup.a51中进行。 如果在定义全局变量(如无符号字符数据)时指定了数字

xxx='100 '; 有与startup.a51相关的赋值。 如果没有=100,startup.a51将他清除为0。 (startup.a51==变量初始化)。

这些初始化完成后,还将设置SP指针。 堆栈区域等非变量区域不进行赋值或清零

制作。

有些人喜欢改变startup.a51,但为了满足自己理所当然想做的爱好,那是不必要的。 有可能是错的。 例如,想在断电保护时保存几个变量

但是,变更startup.a51来实现是愚蠢的方法,实际上只要利用非变量区域的特性,将指针变量定义在堆栈最低部:0xff就可以实现。为什么需要更改?

只要知道startup.a51的特性,就不需要随时更改startup.a51。

位元

内部数据存储区域内的20H . 2FH

区域内的1位地址。 这在DATA的20H以后作为字节出现,可以相互参照。 添加8051后可寻址

的SFR,虽然刚试过,但只有00H--7FH起作用。 也就是说,数据发生变化时颜色会变红,之后的80H开始--FFH不是地址区域,而是寻址的特殊寄存器。 如果涉及11个可寻址的话,当然会做出反应。 复位后,程序计数器PC的内容为0000H,内部RAM的各单元的值不确定。 各功能寄存器复位值是堆栈指针SP的复位值为07H、累加器ACC、寄存器b的复位值为00H、数据指针DPTR的复位值为0000H、p0、p1、p2、p3这4个端口的复位值其他SFR,例如PSW、TCON、TMOD、TL0、TH0、TL1、TH1的复位值也是00H。

在wave中,低位128字节和高位128字节(0-7FH ),低位128字节是片上RAM区域,高位128字节(80-FFH )是SFR )特殊功能寄存器) bit是位于低位128字节20H

. 2FH区域,即data的20H . 2FH区域代码是0000H . 0FFFFH之间的代码地址。

我来用

ORG 5000H

TAB:

在DB22H、3BH、43H、66H、5H、6DH、88H之后,

代码从5000H变为DB的每个data加上0到127之间的数据存储地址或128 . 255

范围内的特殊功能寄存器(SFR )地址。 两者访问的方式不同

国际数据中心

是0 to 255范围内的idata内存地址。

idata与data重叠,低128字节,在某些位置,只有data表示256字节的片上RAM,xdata是0 to 65535范围内的xdata存储器地址。

有关指针类型和存储区关系的详细信息

一.记忆类型与记忆领域的关系

data ---可寻址片上ram

bdata ---位可寻址片上ram

idata ---

允许访问可寻址的片上ram、所有内置ram

pdata ---寻呼地址片外ram(movx

@R0 () 256字节/页) )

xdata ---可寻址片外ram(64k

地址范围FFFFH )

代码--- -程序商店(64k

地址范围)、MOVC @DPTR、指针类型和存储区之间的关系

声明变量时,可以指定变量的存储类型,例如:

uchar data x和data
uchar x相等价都是在内ram区分配一个字节的变量。    
同样对于指针变量的声明,因涉及到指针变量本身的存储位置和指针所指向的存储区位置不同而进行相应的存储区类型关键字的
使用如:
     uchar xdata * data
pstr    
是指在内ram区分配一个指针变量("*"号后的data关键字的作用),而且这个指针本身指向xdata区("*"前xdata关键字的作用),可能初学C51时有点不好懂也不好记。没关系,我们马上就可以看到对应“*”前后不同的关键字的使用在编译时出现什么情况。
     ......
     uchar xdata
tmp[10];     //在外ram区开辟10个字节的内存空间,地址是外ram的0x0000-0x0009
     ......
     第1种情况:
     uchar data * data
pstr;     pstr=tmp;
     首先要提醒大家这样的代码是有bug的,
他不能通过这种方式正确的访问到tmp空间。 为什么?我们把编译后看到下面的汇编
代码:
     MOV
0x08,#tmp(0x00)        
;0x08是指针pstr的存储地址
     看到了吗!本来访问外ram需要2
byte来寻址64k空间,但因为使用data关键字(在"*"号前的那个),所以按KeilC编译环境来说就把他编译成指向内ram的指针变量了,这也是初学C51的朋友们不理解各个存储类型的关键字定义而造成的bug。特别是当工程中的
默认的存储区类为large时,又把tmp[10] 声明为uchar tmp[10]
时,这样的bug是很隐秘的不容易被发现。
     第2种情况:
     uchar xdata * data
pstr;     pstr = tmp;
    
这种情况是没问题的,这样的使用方法是指在内ram分配一个指针变量("*"号后的data关键字的作用),而且这个指针本身指向xdata区("*"前xdata关键字的作用)。编译后的汇编代码如下。
     MOV
0x08,#tmp(0x00)        
;0x08和0x09是在内ram区分配的pstr指针变量地址空间
     MOV 0x09,#tmp(0x00)
    
这种情况应该是在这里所有介绍各种情况中效率最高的访问外ram的方法了,请大家记住他。
     第3种情况:
     uchar xdata * xdata
pstr;
     pstr=tmp;
    
这中情况也是对的,但效率不如第2种情况。编译后的汇编代码如下。
     MOV DPTR,
#0x000A        
;0x000A,0x000B是在外ram区分配的pstr指针变量地址空间
     MOV A, #tmp(0x00)
     MOV @DPTR, A
     INC DPTR
     MOV A, #tmp(0x00)
     MOVX @DPTR, A
    
这种方式一般用在内ram资源相对紧张而且对效率要求不高的项目中。
     第4种情况:
     uchar data * xdata
pstr;     pstr=tmp;
    
如果详细看了第1种情况的读者发现这种写法和第1种很相似,是的,同第1 种情况一样这样也是有bug的,但是这次是把pstr分
配到了外ram区了。编译后的汇编代码如下。
     MOV DPTR,
#0x000A        
;0x000A是在外ram区分配的pstr指针变量的地址空间
     MOV A, #tmp(0x00)
     MOVX @DPTR, A
     第5种情况:
     uchar * data pstr;     pstr=tmp;
    
大家注意到"*"前的关键字声明没有了,是的这样会发生什么事呢?下面这么写呢!对了用齐豫的一首老歌名来说就是 “请跟我
来”,请跟我来看看编译后的汇编代码,有人问这不是在讲C51吗?
为什么还要给我们看汇编代码。C51要想用好就要尽可能提升C51
编译后的效率,看看编译后的汇编会帮助大家尽快成为生产高效C51代码的dzdhf的。还是看代码吧!
     MOV 0x08,
#0X01            
;0x08-0x0A是在内ram区分配的pstr指针变量的地址空间
     MOV 0x09, #tmp(0x00)
     MOV 0x0A, #tmp(0x00)
    
注意:这是新介绍给大家的,大家会疑问为什么在前面的几种情况的pstr指针变量都用2 byte空间而到这里就用3 byte空间了
呢?这是KeilC的一个系统内部处理,在KeilC中一个指针变量最多占用 3
byte空间,对于没有声明指针指向存储空间类型的指针,
系统编译代码时都强制加载一个字节的指针类型分辩值。具体的对应关系可以参考KeilC的help中C51
User's Guide。
     第6种情况:
     uchar * pstr;
     pstr=tmp;
    
这是最直接最简单的指针变量声明,但他的效率也最低。还是那句话,大家一起说好吗!编译后的汇编代码如下。
     MOV DPTR,
#0x000A        
;0x000A-0x000C是在外ram区分配的pstr指针变量地址空间
     MOV A, #0x01
     MOV @DPTR, A
     INC DPTR
     MOV DPTR, #0x000A
     MOV A, #tmp(0x00)
     MOV @DPTR, A
     INC DPTR
     MOV A, #tmp(0x00)
     MOVX @DPTR, A
    
这种情况很类似第5种和第3种情况的组合,既把pstr分配在外ram空间了又增加了指针类型的分辨值。


转载于:https://www.cnblogs.com/zzili/archive/2012/12/06/6663362.html

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。