80C51 storage and C51 memory optimization

Publisher:Blissful5Latest update time:2017-01-19 Source: eefocusKeywords:80C51 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

80C51 has four storage spaces in its physical structure: on-chip program memory, off-chip program memory, on-chip data memory, and off-chip data memory. But logically, from the user's point of view, 80C51 has three storage spaces: 64KB of program memory address space (using 16-bit address) with unified addressing inside and outside the chip, 256B of on-chip data memory address space (using 8-bit address, of which only 21 bytes of the 128B dedicated register address space are meaningful) and 64KB of off-chip memory address space.

1. Program memory

The program memory is used to store compiled programs and table constants. The 80C51 has a 4KB ROM inside the chip, and the 16-bit address line outside the chip can expand up to 64KB ROM, and the two are uniformly addressed. If the EA terminal is kept at a high level, the program counter PC of the 80C51 is in the range of 0000H-0FFFH (that is, the first 4KB address) to execute the program of the on-chip ROM. When the addressing range is 1000H-FFFFH, instructions are fetched from the off-chip memory. When the EA terminal is kept at a low level, all instruction fetching operations of the 80C51 are performed in the off-chip program memory, and the off-chip memory can be addressed starting from 0000H.

In the program memory, the following 6 units have special functions.

0000H: After 80C51 is reset, PC=0000H, that is, the program starts executing instructions from 0000H.

0003H: External interrupt 0 entry.

000BH: Timer 0 overflow interrupt entry.

0013H: External interrupt 1 entry.

001BH: Timer 1 overflow interrupt entry.

0023H: Serial port interrupt entry.

2. Data storage

The data memory is used to store intermediate operation results, data temporary storage and buffering, flags, etc. The 80C51 chip has 256B RAM, and up to 64KB RAM can be expanded outside the chip, forming two address spaces.

The on-chip data memory has an 8-bit address and can address up to 256 units. The lower 128B (00H~7FH) address area is the on-chip RAM, which can be accessed by direct addressing and indirect addressing. The higher 128B address area (80H~FFH) is a dedicated register area and can only be accessed by direct addressing.

In the lower 128B RAM area, the addresses 00H~1FH are the general working register area, which is divided into 4 groups, each group consists of 8 working registers (R0~R7), occupying a total of 32 units. The following table is the address table of the working registers. Each group of registers can be selected as the current working register of the CPU. The setting of RS1 and RS0 in the program status word PSW determines which group the CPU is currently using. If the program does not need 4 groups, the rest can be used as general data buffers. After the CPU is reset, the 0th group of working registers is selected.

 

Group

RS1

RS0

R0

R1

R2

R3

R4

R5

R6

R7

0

0

0

00H

01H

02H

03H

04H

05H

06H

07H

1

0

1

08H

09H

0AH

0BH

0CH

0D

0E

0FH

2

1

0

10H

11H

12H

13H

14H

15H

16H

17H

3

1

1

18H

19H

1AH

1BH

1CH

1DH

1EH

1FH

 

The 16B after the working register area (i.e. 20H~2FH) can be accessed by bit addressing. The bit addresses of these 128 bits (bit address refers to the address of a binary bit) are 00H~7FH. They can be used as software flags or for 1-bit (Boolean) processing.

3. Special register SFR

80C51 has 21 special registers SFR, also known as special function registers. They are discretely distributed in the high 128 B addresses 80H~FFH of the on-chip data memory. Access to these special registers is only allowed by direct addressing. Special registers do not occupy the entire address space of 80H~FFH. Operations on idle addresses are meaningless. If an idle address is accessed, random numbers are read out.

Among the 21 special registers, 11 special registers have bit addressing capability and their byte addresses are exactly divisible by 8.

Note: Since SFRs are discretely distributed in the high 128 B addresses 80H~FFH of the on-chip data memory, when the defined data length is greater than 128 B bytes, it may conflict with the addresses of some SFRs, leading to unexpected results. Therefore, the data should be controlled within 128 B as much as possible, especially for arrays. If the data volume is large, xdata can be used to define it in external RAM.

like:

unsigned char xdata gTagId[2500*11] _at_ 0x0000; //Define the array gTagId. This data is stored in the external RAM and its starting address is specified as 0x0000.

unsigned short xdata gTagIdNum; //define data gTagIdNum.

Note the difference between the following definitions:

unsigned char * xdata pWriteTagId; //Define a pointer, which is stored in external RAM. The data type pointed to by this pointer is unsigned char.

unsigned char xdata *pWriteTagId; //Define a pointer, which is stored in the internal RAM. The data pointed to by this pointer is stored in the external RAM and its type is unsigned char.

unsigned char xdata * xdata pWriteTagId; //Define a pointer, which is stored in the external RAM. The data pointed to by this pointer is also stored in the external RAM, and its type is unsigned char.

For the use of external RAM, as long as the hardware connects the corresponding pins, the software does not need to make any settings and can directly use xdata to access it.

 

 

Understanding of 51 MCU memory

Many people have misunderstandings about the memory of 51 MCU. The most common ones are the following two:

① When the number of variables exceeds 128, the compact mode must be used for compilation.

The actual situation is that as long as the memory usage does not exceed 256.0, you can compile in small mode.

② Some addresses above 128 are used as special registers and cannot be used by programs.

Unlike PCs, 51 microcontrollers do not use linear addressing. Special registers and RAM use repeated addresses, but different instructions are used when accessing them, so they do not occupy RAM space.

Since the memory is relatively small, memory optimization is generally required to maximize memory usage efficiency.

Taking Keil C compiler as an example, in small mode, variables without storage type specified are defaulted to data type, that is, direct addressing, and can only access the lower 128 bytes. However, these 128 bytes are not all used by our program. Registers R0-R7 must be mapped to low RAM, which takes up 8 bytes. If register group switching is used, it will take up more.

Therefore, the maximum size of the data area that can be used is 120 bytes. If it exceeds 120 bytes, idata must be used to explicitly specify indirect addressing. In addition, the stack must occupy at least one byte, so the variables that can be defined can occupy 247 bytes in the extreme case. Of course, a one-byte stack is definitely not enough in actual applications, but if the number of nested call levels is not deep, more than a dozen bytes are enough.

 

In order to verify the above point of view, an example was written (the test environment is XP + Keil C 7.5).

#define LEN 120
data unsigned char tt1[LEN];
idata unsigned char tt2[127];

void main()
{
unsigned char i, j;

for(i = 0; i < LEN; ++i )
{
j = i;
tt1[j] = 0x55;
}
}

We can calculate R0-7(8) + tt1(120) + tt2(127) + SP(1) for a total of 256 bytes

The results of keil compilation are as follows:
Program Size: data=256.0 xdata=0 code=30
creating hex file from "./Debug/Test"...
"./Debug/Test" - 0 Error(s), 0 Warning(s).

This code has reached the memory allocation limit. If any global variables are defined or the array is increased, the compiler will report error 107. This raises a question: Why are variables i and j not included? This is because i and j are local variables, and the compiler will try to optimize them to register Rx or the stack. This is the problem. If there are too many local variables or local arrays are defined, the compiler cannot optimize them and must use RAM space. Although the allocation of global variables has been carefully calculated and does not exceed the usage range, memory overflow errors will still occur! Whether the compiler can successfully optimize the variables depends on the code.
In the above code, the loop is bloated and the variable j is completely unnecessary, so change the code to

unsigned char i;
unsigned char j;

for(i = 0; i < LEN; ++i )
{
tt1[i] = 0x55;
}

Compile again and see if there is an error! Because the compiler does not know how to use j, it cannot optimize. j must occupy RAM space, and RAM overflows. (A smarter compiler will automatically remove this useless variable, but this is not discussed here).

In addition, it is best to place the defined variables of idata after the data variables.

For this definition:

unsigned char c1;
idata unsigned char c2;
unsigned char c3;
The variable c2 will definitely be addressed indirectly, but it may fall in the data area, which wastes a directly addressable space.

 

There are a few things to note when optimizing variables:

① Let as many variables as possible use direct addressing to improve speed.
If there are two single-byte variables and a character array with a length of 119, it is impossible to define them all in the data area because the total length exceeds 120 bytes.
According to this principle, the definition method is as follows:

data unsigned char tab[119];
data unsigned char c1;
idata unsigned char c2;
But this is not absolute. If c1 and c2 need to be accessed very frequently, and tab access is not so frequent,
the variables with high access volume should use direct addressing:

data unsigned char c1;
data unsigned char c2;
idata UCHAR tab[119];
This should be determined according to the specific project requirements

 ② To improve the reuse rate of memory
is to use local variables as much as possible. Another advantage of local variables is that the access speed is relatively fast. From the previous example, it can be seen that local variables i and j do not occupy memory separately. Variables that do not use a large amount of memory in subroutines should be defined as local variables as much as possible.

 ③ For the definition of pointer array, specify the storage type as much as possible and try to use unsigned type variables. Generally, pointers require an extra byte to indicate the storage type. The 8051 series itself does not support signed numbers and requires an external library to process signed numbers. This greatly reduces the program running efficiency and requires additional memory.

④Avoid memory holes


You can view the previous code by looking at the compiler output symbol table file (.M51). The section about memory in the M51 file is as follows:

* * * * * * * DATA MEMORY * * * * * * *
REG 0000H 0008H ABSOLUTE "REG BANK 0"
DATA 0008H 0078H UNIT ?DT?TEST
IDATA 0080H 007FH UNIT ?ID?TEST
IDATA 00FFH 0001H UNIT ?STACK

The first line shows that register group 0 starts from address 0000H and occupies 0008H bytes.
The second line shows that the variables in the DATA area start from 0008H and occupy 0078H bytes.
The third line shows that the variables in the IDATA area start from 0080H and occupy 007F bytes.
The fourth line shows that the stack starts from 00FFH and occupies 0001H bytes.

Since the variable definitions in the previous code are relatively simple and all the space is used up continuously, the display here is relatively simple. When there are many variable definitions, there will be many lines here. If the allocation of global variables and local variables is unreasonable, lines like the following may appear:

0010H 0012H *** GAP ***
This line indicates that the bytes starting from 0010H for 0012H are not fully utilized or not used at all. The most common reasons for this situation are too many local variables, the number of local variables in multiple subroutines is too different, and register switching is used but not fully utilized.


Keywords:80C51 Reference address:80C51 storage and C51 memory optimization

Previous article:Microcontroller Learning Notes (IV) - Interrupts
Next article:How to adjust the baud rate in 51 single chip microcomputer serial port experiment

Recommended ReadingLatest update time:2024-11-15 07:23

Implementation of running water lamp in "Beginner's C51 Self-study Notes" (Shift Operation 2)
#include reg52.h #include intrins.h   #define uchar unsigned char  #define uint unsigned int void delay(void) { uchar a,b; for(a=0;a 200;a++) for(b=0;b 200;b++); }   void main() { uchar k; k=0xfe; //11111110 while(1) { P0=k; delay(); k=_crol_(k,1);//Shift K by one bit 11111101 11111011 11110111..
[Microcontroller]
C51 Compiler - Advanced Programming Techniques (6) - Absolute Memory Access
Accessing Absolute Memory Locations Absolute memory access The C programming language does not support explicitly referring to the storage location of a static or global variable. There are three ways to explicitly refer to a memory location: (1) Absolute memory access macros (2) Connector position control (3)
[Microcontroller]
Program memory allocation
Answer: The memory occupied by a program compiled by C/C++ is divided into the following parts: 1. Stack area (stack) - automatically allocated and released by the compiler, storing function parameter values, local variable values, etc. Its operation is similar to the stack in the data structure. 2. Heap area (heap)
[Microcontroller]
Generation and use of static library in Keil C51
1. Create a new project, such as LibExample, with the code to generate the library file, and then add the code to it. Select Create Library in Output in Option for target, and compile to generate the library file. 2. Copy the generated library file (LibExample.lib) to the new project (Hello) folder, add it to the
[Microcontroller]
Generation and use of static library in Keil C51
s3c2440 bare metal-memory controller (3-3, operating norflash in uboot of norflash programming)
Prerequisite: norflash is initialized normally and can be executed normally from nor. The CPU always reads instructions from address 0 to execute the program. When the CPU is set to nor to start, address 0 corresponds to nor. When the cpu starts from nand, address 0 corresponds to sram. 1. Read norFlash We set the b
[Microcontroller]
s3c2440 bare metal-memory controller (3-3, operating norflash in uboot of norflash programming)
C51 Programming 18-Interrupt (Serial Communication 2)
There are two independent receiving and sending SBUFs inside the MCS-51 microcontroller. The receiving SBUF cannot send, and the sending SBUF cannot receive. They share the same address (99H). The internal logic structure is shown in the figure below: In the internal logic structure of the serial, we can see that se
[Microcontroller]
C51 Programming 18-Interrupt (Serial Communication 2)
The use of 51 MCU RAM
Today I am still working overtime alone, so I will sort out some small questions that I have been confused about before. Take a 51-core STC89C52 microcontroller as an example. STC89C52 has 8K bytes of Flash, 512 bytes of RAM, watchdog timer, etc. Other resources are not within the scope of today's discussion, so I will
[Microcontroller]
Use the MCU's RAM virtual USB disk (file system: Fat16)
Operating system: rt-thread File system: Fat16 Hardware platform: stm32f103c8 Description: Use the MCU's RAM to virtualize a USB disk to store real-time small data, which can be read by the host computer through USB.   1. Hard disk 1. Hard disk physical structure:     Platter: A hard disk is made up of man
[Microcontroller]
Use the MCU's RAM virtual USB disk (file system: Fat16)
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号