重学C51之DATA、BDATA、XDATA的区别

周末闲着没事做,便把之前在学校时买的C51开发板拿出来玩。这次主要是想练习以1602为显示模块、4X4矩阵键盘为按键模块的Keil C下的多文件编程。

在编译程序时,Keil C提示“..\SRC\MAIN.C(466): 错误 C249: 'DATA': SEGMENT TOO LARGE”。该原因是因为程序的大小超过了所用单片机的片内RAM。把存储模式改为Large,编程成功“Program Size: data=77.3 xdata=237 code=1753”,于是把Hex文件下进单片机中。

满怀期望地等它出现我希望的结果。谁知程序烧进去没多久,开发板便发出“滴”的长鸣声。经过排查后,确定是蜂鸣器发出来的,但我的程序里并没有用到蜂鸣器,并且也没有用到与蜂鸣器相关的引脚。伴随着这一现象发生的还有1602上显示乱码。

一时之间,我是丈二和尚摸不着头脑。因为这些功能在单文件下都是可以正常进行的。万般无奈,只好一一排查可能导致这些这些现象的问题。

1,检查了函数指针的使用情况,主要检查指针指向的地址是否有误。。蜂鸣器报警使我想到了会不会是指针溢出造成该现象。因为Keil C并不能很好的支持函数指针,Keil C调用函数时,函数参数、局部变量是存储在片内RAM区,确切地讲是DATA区,而不是存储在堆栈中。因而有可能在用函数指针间接调用具有参数或返回值的函数时,DATA区内某些地方的值被覆盖了,造成C51读取数据时出错。但由于我是先在单文件下实现的代码,并且功能可以正常实现。因此,我排除了函数指针的问题。

2,文件的组织结构上的问题。该问题的可能性比较小。因为我已成功编译、生成Hex文件。个人理解,若文件组织结构上有问题,那代码是没法通过编译的,更不要说生成Hex文件了。

3,堆栈溢出的问题。相对上述两种情况,该问题的可能性更大,因为一旦堆栈溢出,DATA区低字节的地址会被覆盖,C51有可能会一直重启。但是我查看M51文件里关于堆栈的信息“ IDATA   0057H     0001H     UNIT         ?STACK"。堆栈基址在片内RAM的0x57H处,以片内RAM总大小256Byte(0xff)来看,堆栈可用空间为 0xff - 0x57 = 160Byte。这么大的空间,堆栈是不可能溢出的。

就这问题我纠结了好长时间。某天瞥到我使用的单片机是AT89C52,于是想起这款单片机只有256Byte RAM,无片外数据存储区。要想使用Large模式的话,得扩展片外数据存储器。想到这,我立马换了一个单片机,STC的89C52RC,该单片机除了有256Byte 片内RAM,还集成了256Byte的片外RAM。

果然,89C52RC不会出现上述现象,程序运行得好好的。有鉴于此,我决定重新学下C51存储区的知识。

 

以下内容为转载

×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

keil C51存储区域分为程序存储区和数据存储区2大类型。

.程序存储区(Pragram Area:

欲将声明的数据存放在程序存储区域,可以使用关键字“code”说明。

unsigned char code i=10;则表示 i为无符号字符型数据存放区域为程序存储区。

.数据存储区(Data Memory:

数据存储区域分为内部数据存储区、外部数据存储区域和特殊功能寄存器寻址区。

1.内部数据存储区域(InternalData Memory:可以使关键字"dataiadtabdata"做相应说明。

data:直接寻址区,声明的数据存储范围为内部RAM128字节 0X000X7F

unsigned char data i=10;则表示 i为无符号字符型数据存放区域为数据存储区域(RAM)的低128字节范围内。

idata:间接寻址区,声明的数据存储范围为整个内部RAM 0X000XFF

unsigned char idatai=10;则表示 i为无符号字符型数据存放区域为数据存储区域(RAM)内。

bdata:可位寻址区,寻址范围为0X200X2F

2.外部数据存储区(ExternalData Memory):可以使用关键字"pdataxdata"进行说明。

pdata:主要用于紧凑模式,能访问1页(256字节)的外部RAM,即在访问使用,pdata定义的数据时,不会影响P2口的输出电平(在访问某些自身内部扩展的外部RAM时本身就不会影响I/O端口)。

unsigned char pdata i;则表示 i为无符号字符型数据存放区域为外部数据存储区域(RAM)内(只能在一页范围内)具体操作哪一页,可由其他i/o口设定。

xdata:可访问64k的外部数据存储区,地址范围0X00000XFFFF,同pdata一样在访问芯片自身内部扩展的RAM时也不会影响I/O端口。

unsigned char pdata i;则表示 i为无符号字符型数据存放区域为外部数据存储区(RAM)

3.特殊功能寄存器寻址区域(SpeciacFunction Register Memory-SFR:8051提供128字节的SFR寻址区,该区域可以字节寻址,字寻址,能被8整除的地址单元还可以位寻址。该区域用于控制定时器、计数器、串口等外围接口。使用时可用关键字“sfrsfr16sbit”做相应的声明。

字节寻址 sfr P0=0x80;P0口地址为80H0X000XFF 之间的常数。

字寻址 sfr16 T2=0XCC;指定Timer2 口地址T2L=0XCC T2H=0XCD

位寻址 sbit EA=0xAF;指定第0xAF 位为EA,即中断允许

存储模式

在使用C51时有时我们并没有明确指定所定义的数据的存储类型,然而依然正确。这是由于存储模式决定了没有明确指定存储类型的变量,函数参数等的缺省存储区域。

供有3种存储模式(存储模式在 C51 编译器选项中选择)

1.Small模式

所有缺省变量参数均装入内部 RAM,优点是访问速度快,缺点是空间有限,只适用于小程序。

2. Compact 模式
所有缺省变量均位于外部RAM区的一页(256Byte)
3. Large
模式
所有缺省变量可放在多达 64KB 的外部RAM 区,优点是空间大,可存变量多,缺点是速度较慢。

 

C51存储器类型有bit   sbit  data   xdata   bdata pdata  sfr   code等,可能不全面有遗漏

对应的物理存储器是:

bit,即位数据:数据存储器位寻址区,即20H~2FH的范围,共16个字节,16*8=128个位,位地址00h~7fh,连续的。

sbit:特殊功能寄存器中的位数据:只有能够被8整除的那些特殊功能寄存器中的各个位才能被称为sbit,位地址80H~FFH,不连续的,间断的。

data:数据区,对51为00H~7FH共128个字节,对52为00H~FFH,共256个字节,用MOV寻址,前128用直接寻址或寄存器(R0~R7)寻址,后128用R0、R1间接寻址。

xdata:外部数据区,0000H~FFFFH连续,用DPTR间接寻址(MOVX指令)

bdata:位寻址去的字节,20H~2FH

sfr:特殊功能寄存器(80H~FFH),直接寻址

pdata:外部数据区,P2口保持数据,用R0R1间接寻址(MOVX指令)

code:程序存储器,用MOVC指令只读

×××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××××

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值