data,bdata,idata,pdata,xdata,code storage types and storage areas

Publisher:breakthrough2Latest update time:2024-08-22 Source: cnblogsKeywords:data  bdata  idata  pdata  xdata  code Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

bit

It is the address of a bit in the 20H .. 2FH area of ​​the internal data memory space, or a bit address of an 8051 bit-addressable SFR.

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

data

is a data memory address between 0 and 127, or a special function register (SFR) address in the range 128 .. 255.

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

xdata is an xdata memory address in the range 0 to 65535.


Detailed explanation of the relationship between pointer types and storage areas

1. Relationship between storage type and storage area

data ---> addressable on-chip ram
bdata ---> bit-addressable on-chip ram
idata ---> addressable on-chip ram, allows access to all internal ram
pdata ---> paged addressable off-chip ram (MOVX @R0) (256 BYTE/page)
xdata ---> addressable off-chip ram (64k address range)
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 allocate a one-byte variable in the internal RAM area.

Similarly, for the declaration of pointer variables, the corresponding storage area type keyword is 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

It means to allocate a pointer variable 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 using different keywords before and after the "*" 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 want to remind you that this code has a bug. 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 pointer pstr

Did you see it? Originally, accessing external RAM requires 2 bytes to address 64k space, but because the data keyword (the one before the "*") is used,
it is compiled into a pointer variable pointing to 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 a bug is very hidden and not easy to be discovered.

Case 2:

uchar xdata * data pstr;
pstr = tmp;

This 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.

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.

Case 3:

uchar xdata * xdata pstr;
pstr=tmp;

This is also true, but not as efficient as case 2. 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 RAM resources are relatively tight and efficiency requirements are not high.

Case 4:

uchar data * xdata pstr;
pstr=tmp;

If you have read the first case in detail, you will find that this method is very similar to the first case. Yes, it has a bug just like the first case, 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;

Everyone noticed that the keyword declaration before "*" is gone. 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 about C51? Why do we need to show us the assembly code? If you want to use C51 well, you must try to improve
the efficiency of C51 after compilation. 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 discrimination value to be loaded. For the 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 say it together! The compiled assembly code is as follows.

MOV DPTR, #0x000A; 0x000A-0x000C is the pstr pointer variable address space 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, which not only allocates pstr in the external RAM space but also increases the resolution value of the pointer type.

To summarize: you have seen the above 6 situations, among which the most efficient is the second situation, which can correctly access the RAM area and save code, and the worst efficiency is the sixth
situation, but it does not mean that you can only use the second method. It depends on the situation. Generally speaking, the internal RAM resources of the system architecture of the 51 series are very tight. It is best
to use the internal RAM when defining local variables inside functions or program segments, and try not to declare global variables as internal RAM areas. So for global pointer variables, I recommend using the third
situation, and for local pointer variables, use the second method.

The role of startup.a51
Like 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 action for non-variable areas, such as the stack area.
Some people like to modify startup.a51 to satisfy their own hobbies, which is unnecessary and may be wrong. For example, when power-off protection is performed, you want to save some variables, but modifying startup.a51 to achieve this is a stupid method. In fact, you only need to 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

8051 unique memory types


code
program memory read with MOVC @A+DPTR
data
internal data memory that can be directly accessed
idata
internal data memory accessed with MOV @Rn
bdata
bit addressable internal memory
xdata
external data memory accessed with MOVX @DPTR
pdata
external data memory accessed with MOVX @Rn

Special data types
bit
general bit variable
sbit
absolute addressing bit variable
Syntax
sbit
my_flag
=
location;
(location range from 0x00 ~ 0x7F)
Example
sbit
EA =
0xAF;
or bit variable declared with bdata
char
bdata
my_flags;
sbit
flag0 =
my_flags ^ 0;

(Note that static cannot be added before sbit)

sfr
Special Function Register

Syntax
sfr
my_sfr
=
location;
(location range from 0x80 ~ 0xFF)

Example
sfr
P0
=
0x80;

Specify the absolute address of the variable


In a single module, the following syntax can be used to declare

[memory_space]
type
variable_name
_at_
location

Example
pdata
char
my_pdata
_at_
0x80;

If the variable must be used by multiple modules (Global Variable),

it is more convenient to define it in the header file as an abstract pointer.

#define
variable_name
*((data_type *)
location)

Example
#define
my_pdata
*((char pdata *)
0x80)

(Note the order of char and pdata)

ABSACC.H provides the following convenient macro definitions.

#define CBYTE ((unsigned char volatile code *) 0)
#define DBYTE ((unsigned char volatile data *) 0)
#define PBYTE ((unsigned char volatile pdata *) 0)
#define XBYTE ((unsigned char volatile xdata *) 0)
#define CWORD ((unsigned int volatile code *) 0)
#define DWORD ((unsigned int volatile data *) 0)
#define PWORD ((unsigned int volatile pdata *) 0)
#define XWORD ((unsigned int volatile xdata *) 0)

Hidden initialization program

The first program module executed by 80C51 after power reset (Power On Reset) is not the user's main program
main(), but a program module called startup.a51 hidden in the KEIL-C51 standard link library.
The main task of startup.a51 is to clear the memory blocks including idata, xdata, and pdata to 0, and
initialize the recursive pointer. Then startup.a51 is still executed by a
program module called init.a51 hidden in the KEIL-C51 standard link library. The main task of init.a51 is to initialize
variables with non-zero initial values.

After completing the above initialization program, the control of 80C51 will be handed over to main() to start executing the user's program.


#define XBYTE ((unsigned char volatile xdata *) 0)
defines XBYTE as a pointer to the unsigned char data type in the xdata address space, and the pointer value is 0.
In this way, you can directly use XBYTE[0xnnnn] or *(XBYTE+0xnnnn) to access external RAM

[1] [2]
Keywords:data  bdata  idata  pdata  xdata  code Reference address:data,bdata,idata,pdata,xdata,code storage types and storage areas

Previous article:51 MCU serial communication principle explanation
Next article:CS5532 C51 Driver

Latest Microcontroller Articles
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号