解决keil单片编程ERROR L107: ADDRESS SPACE OVERFLOW问题及根源分析

到底是先code 再数据类型,还是先数据类型再指定存储区域code?

uchar code usRtc1[3] = {23, 59, 55};:先指定了变量的类型为uchar(即unsigned char),然后使用code关键字表明该数组存储在程序存储器中。

code uchar usRtc2[3] = {23, 59, 55};:先使用code关键字指定存储类型,再指定变量的类型为uchar

总结:在 Keil C51 这类支持code关键字的编译器中,ucharcode的先后顺序不会影响代码的正确性,两种写法都可以用来定义一个存储在程序存储器中的无符号字符型数组。

 
在 C51(用于 8051 单片机的 C 语言编译器)中,code区指的是程序存储器(ROM),将变量或数据放在code区有其独特的优缺点,下面为你详细介绍:

优点

1. 节省 RAM 空间

  • 原理:8051 单片机的片内 RAM 资源通常比较有限,一般只有 128 字节或 256 字节。将一些不需要在程序运行过程中修改的常量数据(如表格数据、固定的字符串等)存放在code区,这些数据会被存储到程序存储器中,而不会占用宝贵的 RAM 空间。这样可以为其他需要频繁读写的变量留出更多的 RAM 空间,避免因 RAM 不足而导致程序运行出现问题。

2. 数据安全性高

  • 原理:程序存储器(ROM)通常是只读的,一旦数据被写入到code区,在程序运行过程中就不能被修改。这对于一些重要的常量数据(如程序的配置信息、校准参数等)来说,可以防止因程序中的意外操作(如指针越界、误写等)而导致数据被修改,从而保证了数据的安全性和程序的稳定性。

3. 提高程序执行效率

  • 原理:由于code区的数据是程序存储器中的一部分,CPU 在读取code区的数据时可以直接从程序存储器中获取,不需要额外的内存管理操作。相比之下,如果将大量数据存放在 RAM 中,可能需要进行频繁的内存读写操作,会增加 CPU 的负担,降低程序的执行效率。

缺点

1. 数据不可修改

  • 原理code区是只读的,一旦程序烧录完成,存储在code区的数据就不能在程序运行过程中进行修改。这意味着如果需要动态更新某些数据,就不能将这些数据存放在code区,而必须将其存放在可读写的 RAM 中。
  • 示例场景:如果程序需要根据外部传感器的实时数据进行动态调整,那么这些实时数据就不能存放在code区,因为code区的数据无法在运行时修改。

2. 存储空间有限

  • 原理:虽然程序存储器的容量通常比片内 RAM 大,但它也是有限的。如果将大量的数据存放在code区,可能会导致程序存储器空间不足,无法容纳所有的程序代码和数据。特别是对于一些复杂的程序,可能需要合理规划code区的使用,避免因空间不足而导致程序无法正常烧录或运行。

3. 烧录和更新不便

  • 原理:由于code区的数据是在程序烧录时写入的,如果需要修改code区的数据,就必须重新烧录整个程序。这在一些需要频繁更新数据的应用场景中会带来不便,增加了开发和维护的成本。例如,在产品的现场调试过程中,如果需要修改存储在code区的校准参数,就需要重新烧录程序,而不能像修改 RAM 中的数据那样方便快捷。

 

Tisp:code 区是只读的,而 xdata 区用于存储程序运行过程中的动态数据,支持读写操作。

// ------------------------分 隔 符---------------------------

 

1、将部分声明的不需要修改的变量声明为程序存储器变量,即在变量名前增加code关键字,如:

unsigned char code  led_mod[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

当然,我们也可以使用关键字xdata将数据存储到片外存储器中去(如果我们不加任何关键字,就相当于默认使用了data关键字,也就是默认使用的是片内数据存储器)

2、修改存储器模式

对于代码行数比较多,程序运行空间需求大的程序,可能也会出现内存溢出的错误。但这个不是数据存储器的问题,而是程序存储器问题。程序存储器是用来供编译器控制指令small,compact和large指定编译时的存储器模式。

但是我自己测试 发现一个问题:

2.1如果把东西都放在PDATA

则不管是unsigned char 还是unsigned int全局变量,只要没有赋初值,大多都是默认为最大值,少量为随机数

2.2如果把东西都放在XDATA

总之就是可变的变量,不初始化放在PDATA或XDATA,则默认值都不正常(理论上应该全局变量不初始化,默认为0)。

3.放在data区

就正常了。

 

所以,我总结为,如果要改成XDATA,PDATA可变变量就都记得赋初值。
如果是DATA模式,则我们把不需要修改的变量声明为程序存储器变量(即在变量名前增加code关键字),以达到减少空间。如:

查看代码
code unsigned char led_mod[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

code unsigned char mode1[] = {0X01,0X02,0X04,0X08,    0X10,0X20,0X40,0X80};    //L1-L8
code unsigned char mode2[] = {0X80,0X40,0X20,0X10,    0X08,0X04,0X02,0X01};    //L8-L1
code unsigned char mode3[] = {0X81,0X42,0X24,0X18};                                            //两边向中间
code unsigned char mode4[] = {0X18,0X24,0X42,0X81};

code的作用就是告诉单片机,定义的数据要放在ROM(程序存储区64KB)里面,写入后就不能再更改,因为C语言中没办法详细描述存入的是ROM还是RAM(寄存器),所以在软件中添加了这一个语句起到代替汇编指令的作用,对应的还有data(128B)是存入RAM的意思。

关键词的意思:

code :程序存储区(64KB),
data :可直接寻址的内部数据存储区(128B)
idata:间接寻址的内部数据存储区(256B),Indirect addressing
bdata:可位寻址内部数据存储区(16B),Bitable internal data
xdata:外部数据存储区(64KB),External data store
pdata:分页的外部数据存储区,Pagination addressing

 

Keil C51中code、data、bdata、idata、xdata、pdata的解释点击跳转

posted @   iZJ"Qq4577105  阅读(2392)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)
点击右上角即可分享
微信分享提示