woshigeshuai 发表于 2022-5-24 21:47:27

51单片机如何充分利用256字节RAM空间




写了一个程序,希望充分利用 单片机自身的256空间RAM

因为256 RAM访问速度最快。

如图: 堆栈设置成0X91   可是0X91后面还有大把的空间没有使用,我看过别人的程序堆栈初始地址是0XC0 ,0XC0前都当RAM用,这样就很合理

我写程序的时候,有些不重要的参数我都已经定义了 idata , 比如 u8 idata apple; 可是并没有放入0X80后面的区域,如图所示

可能有些朋友对51单片机RAM空间不是很熟悉, 51单片机RAM 空间 256个字节 ,堆栈用掉一小部分,其它的按理来说都可以使用。使用汇编语言写程序
这部分空间可以灵活使用。
0-127 字节空间 称为 data区域
128-255字节空间 称为 idata区域

arm 发表于 2022-5-24 22:20:16

本帖最后由 arm 于 2022-5-24 22:21 编辑

片内的256字节都是idata,低128和高128,都可以用间接寻址方式访问,data是指低128,data的访问速度是最快的

modbus 发表于 2022-5-24 22:40:44

使用频率高的变量优先定义为DATA型,DATA型不够了再定义为IDATA型

sfes 发表于 2022-5-24 22:45:11

高128尽量不要使用。堆栈空间要用

woshigeshuai 发表于 2022-5-24 22:48:27

sfes 发表于 2022-5-24 22:45
高128尽量不要使用。堆栈空间要用
(引用自4楼)

堆栈用不了那么多空间的

woshigeshuai 发表于 2022-5-24 22:50:23

modbus 发表于 2022-5-24 22:40
使用频率高的变量优先定义为DATA型,DATA型不够了再定义为IDATA型
(引用自3楼)

关键 不管我现在怎么定义,编译不了。提示RAM空间超了。但是我感觉RAM空间还有很大空间没利用。
看到别人空间利用的很发,所以想知道这方面技巧。 现在 正在研究 STARTUP.A51 文件,但找不到可以利用的。

t3486784401 发表于 2022-5-24 23:14:00

提示是 DATA 超了,纠结 IDATA 无济于事。

KEIL51 里边 00-7F 称作 DATA,00-FF 称作 IDATA,前 128 字节是重叠的。
低 128 即可以 DATA 也可以 IDATA,高 128 只能用作 IDATA。

makesoft 发表于 2022-5-25 06:33:09

其实这是编译软件不完善造成的,即使定义为idata编译器地址分配也是和data同区间存放的,要是认为设置idata起始存放地址要80以上的空间,然后上面堆栈,这样80一下存放data就相对宽裕了些。

1a2b3c 发表于 2022-5-25 07:57:11

我还以为楼主写了篇经验总结,结果是求助贴。。。
你把你把你代码简化一下到不泄漏你的机密,然后发上来,看你到底哪里错了,
如果你都到了去研究A51的程度了,都可以觉得你是高手了,
正常情况下,一般的代码压根不用去专门人为的设置堆栈或者啥的,直接默认的完全没有任何问题,所以你还是放上来吧,

niugangzhou 发表于 2022-5-25 08:50:30

我也对51的内存空间怎么分配很感兴趣(虽然还是才入行的菜鸡)。尽管现在的芯片资源一般都很够用,可能是有点奇怪的癖好吧,理线一定要理的非常整齐,程序一定要写的非常规整。垒砖头不垒的一点空隙没有,就会浑身难受。也是有点强迫症了

woshigeshuai 发表于 2022-5-25 10:59:14



问题解决了。如图所示。玩了快10年51单片机,又进步了一点。

当时我脑子 里面解决了这个问题,在想,要不要发出来。还是只让自己知道。感觉这样不太好。

来这个论坛也快10年了,是从当初的小白,一步一步问大神,走到今天。没有大家的分享我也不会学到这么 多。

modbus 发表于 2022-5-25 11:42:39

data u8 apple是被KEIL不推荐的格式,KEIL推荐的格式是u8 data apple

makesoft 发表于 2022-5-25 11:50:57

这明显不是正路子,不定义空间域的变量自动定义到xdata空间几年了,运行效率慢,并且系统要是没有xdata还运行出错。

woshigeshuai 发表于 2022-5-25 11:52:23

modbus 发表于 2022-5-25 11:42
data u8 apple是被KEIL不推荐的格式,KEIL推荐的格式是u8 data apple
(引用自12楼)

我以前也是u8 data apple; 发现发现 data u8 apple;也能用。

makesoft 发表于 2022-5-25 12:34:46


正确的做法是直接在BL51 LOCATE的IDATA中设置地址就可以了


modbus 发表于 2022-5-25 13:24:15

woshigeshuai 发表于 2022-5-25 11:52
我以前也是u8 data apple; 发现发现 data u8 apple;也能用。
(引用自14楼)

data u8 apple是老格式

dz20062008 发表于 2022-5-25 14:43:06

标准51单片机ram与rom可以外部扩展,都可以最大支持64k字节扩展。现在有stc增强51sram都12k绝对够用,我要说的说完了。

woshigeshuai 发表于 2022-5-25 14:47:29

dz20062008 发表于 2022-5-25 14:43
标准51单片机ram与rom可以外部扩展,都可以最大支持64k字节扩展。现在有stc增强51sram都12k绝对够用,我要 ...
(引用自17楼)

谢谢你的分享,现在好多51单片机都有 SRAM 而且空间还挺大。比如STC的

这次是特殊情况,所以想好好利用一下256 RAM空间

redworlf007 发表于 2022-5-25 15:43:43

能不能不要浪费生命了,换个ram大的片子,他不香么?省下的时间,外面浪浪,不香么?

dz20062008 发表于 2022-5-25 16:03:47

本帖最后由 dz20062008 于 2022-5-26 05:53 编辑

应该看看对应的单片机头文件,而不是STARTUP.A51。不同51单片机都用STARTUP.A51但是头文件不一样,比如reg51.h。如果不指明对应单片机的内部资源,编译器当然不能正确分配空间。这个问题的根源在于51单片机有4个独立的物理存储器,内部ramrom外部ramrom,所以会出现ramrom都有地址重叠问题,在汇编语言中访问内部ram用mov,访问外部ram用movc。访问内外rom都用movx指令。在c语言中就会出现数据空间地址错乱的感觉,或者不知道把数据放哪里好。

ps

上述有错误修改如下
内部 RAM - MOV
外部 RAM - MOVX
内部 ROM - MOVC+(EA=H)
外部 ROM - MOVC+(EA=L)

dz20062008 发表于 2022-5-25 16:16:08

t3486784401 发表于 2022-5-24 23:14
提示是 DATA 超了,纠结 IDATA 无济于事。

KEIL51 里边 00-7F 称作 DATA,00-FF 称作 IDATA,前 128 字节 ...
(引用自7楼)

大神,在物理ram映射上,这显然是内部ram与扩展ram的128B地址重叠了。那可不可以这么理解data就是内部ram 00-7f这个范围,idata就是外部ram的范围。那重叠的128B地址空间到底是能存128B还是256B数据。

ccjlhw 发表于 2022-5-25 21:58:47

楼主变量地址是怎样看的,你这个图片 idata区域

t3486784401 发表于 2022-5-26 04:08:07

dz20062008 发表于 2022-5-25 16:16
大神,在物理ram映射上,这显然是内部ram与扩展ram的128B地址重叠了。那可不可以这么理解data就是内部ram ...
(引用自21楼)

先说下 KEIL 里边关于 DATA / IDATA / PDATA / XDATA 的区别,这里写段程序比较直观,代码如下:

unsigned char dataVarD;
unsigned char idata VarID;
unsigned char pdata VarPD;
unsigned char xdata VarXD;

void main(void)
{
    VarD = 0x12;
    VarID= 0x56;
    VarPD= 0xab;
    VarXD= 0xef;
}

定义四个变量位于 DATA / IDATA / PDATA / XDATA 区,命名为 VarD/ID/PD/XD 以示区分。
使用老版本的 KEIL 在 DEBUG 模式下查看反汇编,截图如下。为了便于理解,每句反汇编代码都加了伪 C 样式的注解:



之后就可以说区别了:

a. DATA 变量使用直接寻址,汇编形如:MOV 地址,此种模式仅能访问 00-7F 范围片上内存,超过了就是 SFR 访问;
b. IDATA 变量使用间接寻址,汇编形如:MOV @R0,此种模式可以访问 00-FF 范围片上内存,并且前 128 B 与 DATA 物理重叠。
c. PDATA 变量使用 8bit MOVX 间接寻址,汇编形如 MOVX @R0,此种模式访问片外 256 B 内存段,一般要手动 CS 片选(高地址);
d. XDATA 变量使用 16bit MOVX 间接寻址,汇编形如 MOVX @DPTR,此种模式访问片外 64KB 内存,一般是自动 CS 片选。

然后 21L 问的啥..... 写太多了捋一捋:

A1. DATA/IDATA/PDATA/XDATA 是访问模式而非特定内存范围,一般只讨论各段内存用什么访问模式,反过来模式允许的内存段是存在重叠的;

A2. 以 256 B 的 89C52 为例,低 128 B 既可以用 DATA 模式也可以用 IDATA 模式,高 128 B 只能用 IDATA 模式;

A3. 关于重叠,实则是模式允许的内存段重叠了,这重叠的 128 B 只能存储 128 B,用任意一种模式访问都可以修改这 128 B,效果类似于 union;

A4. 为了不至于混乱,编译器默认将 DATA/IDATA 区域设定为不重叠,以下设定都是不重叠且有效的:
A4.1:DATA=00~7F, IDATA=80~FF
A4.2:DATA=00~1F, IDATA=20~FF

A5. 对于 PDATA/XDATA,同样存在对应内存段重叠问题,所以一般 STC 不推荐同时使用。

------------------------------------------------------------------------------------------------------

纯手敲,如有 BUG 欢迎指正

t3486784401 发表于 2022-5-26 04:35:11

dz20062008 发表于 2022-5-25 16:03
应该看看对应的单片机头文件,而不是STARTUP.A51。不同51单片机都用STARTUP.A51但是头文件不一样,比如reg5 ...
(引用自20楼)

写乱了:MOVC 专用于访问当前 ROM,内外 ROM 是用 /EA 脚切换的(不是中断那个EA)。
理论上如果运行着内部 ROM,你是没有指令可以访问到相同地址的外部 ROM 去的。
洞洞焊过 51 的大多数都知道,/EA 悬空根本就不跑程序,CPU 在纠结外部 ROM 上哪了...

内部 RAM - MOV
外部 RAM - MOVX
内部 ROM - MOVC+(EA=H)
外部 ROM - MOVC+(EA=L)

还有更爽的:如果在 KEIL-C51 里上指针,四个区效仿 const 指针那一堆事,单存储就有 4*4=16 种类型.....
然后似乎 KEIL 还把指针类型也保存在变量里了,好处是可以运行时动态区分指针类型,坏处是占内存

dz20062008 发表于 2022-5-26 07:27:54

t3486784401 发表于 2022-5-26 04:35
写乱了:MOVC 专用于访问当前 ROM,内外 ROM 是用 /EA 脚切换的(不是中断那个EA)。
理论上如果运行着内 ...
(引用自24楼)

感谢大神指正上面我关于movc与movx的错误表述。

同时也解答了关于内外重叠rom空间是否可以访问的疑惑。

内外rom都只能查表指令movc访问,所以内外有地址重叠。

ea为高,同时使用内外rom,外部重叠部分被屏蔽舍弃,任何时候不可访问有浪费。超过内部rom后在外部rom接着运行,同时产生psen外部rom读选通信号。

内外ram是两个完全独立的存储空间,内部ram用mov访问,外部ram用movx访问,因为内外ram使用不同指令访问,且是相互独立的两个物理存储器,所不存在重叠的地址。使用movx访问外部ram同时会产生rd与wr外部ram读写选通信号。

关于内外ram访问速度问题,mov大多数指令都是单指令周期的指令,movx只有4条指令都是双指令周期的指令。

作为汇编用户使用不同指令就决定访问速度。作为c用户就要指定数据空间,然后编译器把数据划分到对应空间对应的内外ram上。汇编用户直接算指令周期优化访问速度,c就要合理分配数据为data/idata/xdata/pdata让使用多的变量常量分配在内部ram。使用少的变量常量放外部ram中。不常用的常量放rom中,内外rom访问速度一样。movx与movc都是双指令周期。内部ram访问大多单指令周期,外部ram加内外rom都是双指令周期。




woshigeshuai 发表于 2022-5-26 09:32:28

ccjlhw 发表于 2022-5-25 21:58
楼主变量地址是怎样看的,你这个图片 idata区域
(引用自22楼)

工程目录里有一个.m51 文件

jetbo 发表于 2022-5-26 10:26:47

学习了,KEIL 里边关于 DATA / IDATA / PDATA / XDATA 的

dz20062008 发表于 2022-5-26 12:04:43

本帖最后由 dz20062008 于 2022-5-26 12:08 编辑

https://www.amobbs.com/forum.php?mod=viewthread&tid=5765755&extra=page=1&mobile=2

一篇同样探讨的帖子

9楼大神精彩回答如下:

本帖最后由 lyl1070 于 2022-5-16 17:13 编辑

memory model选项是指,将默认的变量存放到哪个位置(除了指定位置的变量外,没有指定的都放在这个位置)。
举例:

uchar idata i,flag; // 定义到idata区域。
uchar data i,flag; // 定义到data区域。
uchar xdata i,flag; // 定义到xdata区域。

uchar pdata i,flag; // 定义到pdata区域。

uchar i,flag; // 定义到memory model选项中的区域。

注:

data:固定指前⾯0x00-0x7f的128个RAM,可以⽤acc直接读写的,速度最快,⽣成的代码也最⼩。
idata:固定指前⾯0x00-0xff的256个RAM,其中前128和data的128完全相同,只是因为访问的⽅式不同。
idata是⽤类似C中的指针⽅式访问的。汇编中的语句为:mox ACC,@Rx.(不重要的补充:c中idata做指针式的访问效果很好)。

另外程序堆栈只能存放在idata中,而且是80H~0xFF之间,所以程序必须留出足够的idata空间,而不能超过128个。

xdata:外部扩展RAM,⼀般指外部0x0000-0xffff空间,⽤DPTR访问。

pdata:外部扩展RAM的低256个字节,地址出现在A0-A7的上时读写,⽤movx ACC,@Rx读写。

这个⽐较特殊。
有些说pdata是xdata的某一页,页数由某个寄存器控制。没用过,不好说。
所以楼主的程序使用pdata的前提是你的MCU要有xdata,还要指定页。

有例子:

MCU支持传统的访问外部RAM方法,可以使用MOVXA,@Ri或MOVX@Ri,A;来访问外部低256字节RAM;
使用MOVX A,@DPTR或MOVX@DPTR,A来访问外部480字节RAM。

用户也能用XPAGE寄存器来访问外部RAM,仅用MOVX A,@Ri或MOVX@Ri,A指令即可。
用户能用XPAGE来表示高于256字节的RAM地址。

czzhouyun 发表于 2022-5-26 13:21:38

都看糊涂了,51的data一旦超过100以上就要小心了,堆栈会有冲突,把子程序数量减少,调用一个子程序堆栈要占两个字节,现在芯片速度都不慢,可以用xdata
页: [1]
查看完整版本: 51单片机如何充分利用256字节RAM空间