The difference between data, idata, xdata, and pdata in the 51 series

Publisher:JoyfulSerenadeLatest update time:2015-09-25 Source: eefocusKeywords:data  idata  xdata  pdata Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
dATa: Fixed to the first 128 RAM from 0x00 to 0x7f, which can be read and written directly with acc, with the fastest speed and the smallest generated code.

     idATa: Fixed to the first 256 RAM from 0x00 to 0xff, the first 128 of which are exactly the same as the 128 of dATa, but the access method is different. idATa is accessed in a pointer-like manner similar to C. The statement in the assembly is: mox ACC, @Rx. (Unimportant supplement: pointer-style access to idATa in C works very well)

     xdATa: External extended RAM, generally refers to the external 0x0000-0xffff space, accessed using DPTR.

     pdATa: The lower 256 bytes of external extended RAM, read and write when the address appears on A0-A7, use movx ACC, @Rx to read and write. This is quite special, and C51 seems to have a bug for this, so it is recommended to use it less. But it also has its advantages. The specific usage belongs to the intermediate problem, so it will not be mentioned here.

     The role of startup.a51 is the same as that of assembly. The variables and arrays defined in C are initialized in startup.a51. If you define a global variable with a value, such as unsigned char dATa xxx="100";, then startup.a51 will have a related assignment. If there is no =100, startup.a51 will clear it to 0. (startup.a51 == variable initialization). After these initializations are completed, the SP pointer will also be set. There will be no assignment or clearing of non-variable areas, such as the stack area.

Some people like to modify startup.a51 to satisfy their own hobbies. This is unnecessary and may be wrong. For example, if you want to save some variables during power-off protection, it is a stupid method to modify startup.a51. In fact, you can just use the characteristics of the non-variable area and define a pointer variable to point to the lower part of the stack: 0xff. Why do you still need to modify it? It can be said that you don't need to modify startup.a51 at any time if you understand its characteristics.

Bit
is the address of a bit in the 20H .. 2FH area in the internal data storage space. This appears in byte form after 20H of DATA and can be referenced. In addition, the 8051 addressable SFR, but just tried, only 00H--7FH works, that is, when the data changes, the color turns red, and the subsequent from 80H to--FFH is not a bit addressable area, but a bit addressable special register. If the 11 bit addressable ones are involved, of course there will be a response.

After reset, the content of the program counter PC is 0000H, and the value of each unit of the internal RAM is uncertain. The reset values ​​of each function register are as follows: the reset value of the stack pointer SP is 07H, the reset value of the accumulator ACC and register B is 00H, the reset value of the data pointer DPTR is 0000H, and the reset value of the four ports p0, p1, p2, and p3 is 0FFH. The reset values ​​of other SFRs such as PSW, TCON, TMOD, TL0, TH0, TL1, and TH1 are also 00H.

The wave consists of the lower 128 bytes and the upper 128 bytes (0-7FH). The lower 128 bytes are the on-chip RAM area, and the upper 128 bytes (80-FFH) are the SFR (special function register) bits, which are located in the 20H .. 2FH area of ​​the lower 128 bytes. That is, the 20H .. 2FH area of ​​the data

is
a code address between 0000H .. 0FFFFH.

I use
ORG      5000H
TAB:     DB       22H, 3BH, 43H, 66H, 5H, 6DH, 88H,
CODE from 5000H onwards becomes DB


data

is a data memory address between 0 and 127, or a special function register (SFR) address in the range of 128 .. 255 plus. The two are accessed in different ways. In fact, since the reset setting of PSW PSW.3=RS0 and PSW.4=RS1 are both 0, the general working register area is area 0, so the 00--07H part of data corresponds to R0--R7 in the REG column. The latter only represents the lower 128 bytes of internal RAM.


idata
is an idata memory address in the range of 0 to 255.

idata and data overlap in the lower 128 bytes. In some places, only DATA represents 256 bytes of on-chip RAM.
xdata is an xdata memory address in the range of 0 to 65535.

Detailed explanation of the relationship between pointer type and storage area

1. Relationship between storage type and storage area

     data      --->      addressable on-chip ram
     bdata      --->      bit-addressable on-chip ram
     idata      --->      addressable on-chip ram, allowing access to all internal ram
     pdata      --->      paged addressable off-chip ram (MOVX @R0) (256 BYTE/page)
     xdata      --->     addressable off-chip ram (64k address range FFFFH)
     code      --->     program storage area (64k address range), corresponding to MOVC @DPTR

2. Relationship

     between pointer type and storage area When declaring a variable, you can specify the storage type of the variable, such as:
     uchar data x and data uchar x are equivalent, both of which are variables allocated one byte in the internal ram area.

     Similarly, for the declaration of pointer variables, the corresponding storage area type keywords are used because the storage location of the pointer variable itself and the storage area pointed to by the pointer are different.
For example:

     uchar xdata * data pstr

     means that a pointer variable is allocated in the internal ram area (the function of the data keyword after the "*"), and this pointer itself points to the xdata area (the function of the xdata keyword before the "*").
It may be a little difficult to understand and remember when you first learn C51. It doesn't matter. We can immediately see what happens when the corresponding keywords before and after the "*" are used during compilation.

     ......
     uchar xdata tmp[10];      // Open up 10 bytes of memory space in the external ram area, the address is 0x0000-0x0009 of the external ram
     ......

     Case 1:

     uchar data * data pstr;
     pstr="tmp";

     First of all, I would like to remind you that such code has bugs. It cannot correctly access the tmp space in this way. Why? After compiling, we see the following assembly
code:

     MOV 0x08,#tmp(0x00)          ; 0x08 is the storage address of the pointer pstr

     . Did you see it? Originally, accessing the external ram requires 2 bytes to address the 64k space, but because the data keyword (the one before the "*") is used,
it is compiled into a pointer variable pointing to the internal ram according to the KeilC compilation environment. This is also a bug caused by beginners of C51 who do not understand the keyword definitions of each storage type. Especially when
the default storage area class in the project is large, and tmp[10] is declared as uchar tmp[10], such bugs are very hidden and not easy to find.

     The second case:

     uchar xdata * data pstr;
     pstr = tmp;

     This case is fine. This method of use means allocating a pointer variable in the internal ram (the function of the data keyword after the "*"), and this pointer itself points to the
xdata area (the function of the xdata keyword before the "*"). The compiled assembly code is as follows. [page]

     MOV 0x08,#tmp(0x00)          ; 0x08 and 0x09 are the pstr pointer variable address space allocated in the internal ram area.
     MOV 0x09,#tmp(0x00)

     This situation should be the most efficient way to access external ram among all the situations introduced here. Please remember it.

     The third situation:

     uchar xdata * xdata pstr;
     pstr="tmp";

     This situation is also correct, but the efficiency is not as good as the second situation. The compiled assembly code is as follows.

     MOV DPTR, #0x000A          ; 0x000A, 0x000B are the pstr pointer variable address space allocated in the external ram area .
     MOV A, #tmp(0x00)
     MOV @DPTR, A
     INC DPTR
     MOV A, #tmp(0x00)
     MOVX @DPTR, A

     This method is generally used in projects where the internal ram resources are relatively tight and the efficiency requirements are not high.

     Case 4:

     uchar data * xdata pstr;
     pstr="tmp";

     If you have read Case 1 in detail, you will find that this writing method is very similar to Case 1. Yes, there is a bug in this method as in Case 1, but this time pstr is allocated
to the external RAM area. The compiled assembly code is as follows.

     MOV DPTR, #0x000A          ; 0x000A is the address space of the pstr pointer variable allocated in the external RAM area
     MOV A, #tmp(0x00)
     MOVX @DPTR, A

     Case 5:

     uchar * data pstr;
     pstr="tmp";

     You will notice that the keyword declaration before "*" is gone. Yes, what will happen? Write it like this! By the way, to use the title of an old song by Chyi Yu, it is "Please follow me
". Please follow me to see the compiled assembly code. Someone asked if this is not talking about C51? Why do we need to show the assembly code. To use C51 well, you need to improve
the efficiency of C51 after compilation as much as possible. Looking at the compiled assembly will help you become an expert in producing efficient C51 code as soon as possible. Let's look at the code!

     MOV 0x08, #0X01             ; 0x08-0x0A is the address space of the pstr pointer variable allocated in the internal RAM area
     MOV 0x09, #tmp(0x00)
     MOV 0x0A, #tmp(0x00)

     Note: This is a new introduction. You may wonder why the pstr pointer variable in the previous cases uses 2 bytes but only 3 bytes here
? This is an internal process of KeilC. In KeilC, a pointer variable occupies a maximum of 3 bytes. For pointers that do not declare the pointer to the storage space type,
the system compiles the code and forces a byte of pointer type identification value to be loaded. For specific correspondence, please refer to the C51 User's Guide in KeilC's help.

     Case 6:

     uchar * pstr;
     pstr="tmp";

     This is the most direct and simplest pointer variable declaration, but it is also the least efficient. Again, let's talk about it together! The compiled assembly code is as follows.

     MOV DPTR, #0x000A          ; 0x000A-0x000C is the address space of the pstr pointer variable allocated in the external RAM area
     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

     This situation is very similar to the combination of the 5th and 3rd situations. It not only allocates pstr in the external RAM space but also increases the resolution value of the pointer type.

Keywords:data  idata  xdata  pdata Reference address:The difference between data, idata, xdata, and pdata in the 51 series

Previous article:Why is the serial port initialization of C51 microcontroller like this?
Next article:The role of startup.a51 in Keil C

Recommended ReadingLatest update time:2024-11-16 21:01

ARM assembly: the difference between pseudo-instructions DATA and EQU
1. EQU instruction Definition: Used to assign a value or register name to a specified symbolic name. Format: Symbol name EQU expression Symbolic name EQU Register name   Note: The expression must be a simple relocation expression. The character name assigned by the EQU instruction can be used as a data address, code a
[Microcontroller]
Recommended Content
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号