C51 memory optimization (data/idata/xdata)

Publisher:huanhuiLatest update time:2021-05-28 Source: eefocusKeywords:C51 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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


① If 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 by special registers and cannot be used by programs.

Different from PC, 51 MCU does not use linear addressing, special registers and RAM use repeated addresses, but different instructions are used when accessing, so it does 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 default 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, I wrote an example


#define LEN 120

data UCHAR tt1[LEN];

idata UCHAR tt2[127];


void main()

{

FLY 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 result of keil compilation is as follows:

Program Size: data=256.0 xdata=0 code=30

creating hex file from ".DebugTest"...

".DebugTest" - 0 Error(s), 0 Warning(s).

(Test environment is XP + Keil C 7.5)


This code has reached the memory allocation limit. If you define any global variables or increase the size of the array, the compilation 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. Then change the code to


FLY i;

FLY 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 put the defined variables of idata after the data variables.


For this definition



fly c1;

idata uchar c2;

uchar c3;

The variable c2 will definitely be addressed indirectly, but it may fall into the data area, wasting 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, a character array with a length of 119

Because the total length exceeds 120 bytes, it is impossible to define it all in the data area

According to this principle, the definition is as follows:



data FLIGHT tab[119];

data UCAHR c1;

idata UCaR c2;

But it is not absolute. If c1 and c2 need to be accessed very frequently, but tab is accessed less frequently

Then you should use direct addressing for variables with high access volume:


data UCAHR c1;

data UCaR c2;

idata UCHAR tab[119];

This is determined based on specific project requirements.


② Improve memory reuse

That is to use local variables as much as possible. Another advantage of local variables is that they are accessed faster.

As can be seen from the previous example, local variables i and j do not occupy memory separately.

Variables that use a small amount of memory in a subroutine should be defined as local variables as much as possible.


③For the definition of pointer array, specify the storage type as much as possible

Try to use unsigned type variables


Generally, pointers require an extra byte to specify the storage type.

The 8051 series does not support signed numbers, and requires an external library to handle signed numbers. This greatly reduces program efficiency and requires additional memory.



④Avoid memory holes


You can view it by looking at the compiler output symbol table file (.M51)

For the previous code, the memory section in the M51 file is as follows:



* * * * * * * D A T A M E M O R Y * * * * * * *

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 bank 0 starts at 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 IDATA area variables start from 0080H and occupy 007F bytes

The fourth line shows that the stack starts at 00FFH and occupies 0001H bytes.


Since the variable definition in the previous code is 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 consecutive bytes from 0010H to 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:C51 Reference address:C51 memory optimization (data/idata/xdata)

Previous article:Very simple 8×8LED dot matrix c51 source code
Next article:Drivers for 93C46/93C06/93C46/93C56/93C66/93C86 (C51)

Recommended ReadingLatest update time:2024-11-16 17:53

C51 keil v4 simple code writing of water lamp
#include reg52.h #include "intrins.h" typedef unsigned char u8;/*char is 1 byte, 8 bits */ typedef unsigned int u16; /*Usually, int is used because the value range of unsigned char is 0~255; while the value of int is 65535; Use u16, u8 to make the code more portable */ #define led P0 //sbit led=P0^0; //Two ways of ex
[Microcontroller]
How to embed assembly language in C51 language
Keil C language embeds assembly language for mixed programming, the method is as follows: 1. To embed the assembly code snippet in the C file, add the assembly code as follows #pragma ASM ; Assembler Code Here #pragma ENDASM 2. Right click on the C file containing the assembly code in the Project window and select "Op
[Microcontroller]
How to embed assembly language in C51 language
AT89C2051+LCD1602+DS1302 Real-time Clock Design (c51)
#include #include intrins.h #define uchar unsigned char sbit rs=P3^0;//LCD1602控制脚 sbit rw=P3^1; sbit e=P3^2; sbit io=P3^4; //DS1302 PCI bus pin sbit rst=P3^5; sbit sclk=P3^3; uchar hour,minute,second,year,months,date,day; //Display time register uchar whour,wminute,wsecond,wyear,wmonths,wdate,wday; //Set i
[Microcontroller]
The trend of high quality and low price is obvious. Analysis of product performance and technical routes of mainstream collaborative robot manufacturers | MIR DATABANK
Collaborative robots are robots that can physically interact with humans in a shared working environment . They are designed to be flexible, safe and easy to use. They can improve production efficiency while maintaining collaborative interaction between humans and machines, changing the fixed operation
[robot]
Summary of four ways of working of C51 MCU serial port
Mode 0: Synchronous shift register input and output mode 1. Use shift registers to achieve serial/parallel conversion (function) 2. Baud rate: fosc/12 3. RXD (P3.0) ---- used for serial data input and output TXD (P3.1) ---- acts as the shift clock for output 4. Data size: 8 bits 5. Mode 0 sending: ○ Serial port inter
[Microcontroller]
Summary of four ways of working of C51 MCU serial port
Single chip microcomputer drives 16*16 dot matrix LED Chinese character display C51 program
//========================================= //******* MCU drives 16*16 dot matrix LED Chinese character display c51 program ******* //******* Author: http://www.51hei.com ******* //========================================== //Crystal oscillator 12MHz //P1.0~P1.3 connect to 74154 row scan //P3
[Microcontroller]
Single chip microcomputer--electronic clock (C51)
//C program code for a simple electronic clock, no blanking, no key function //author:helloword #include  #define uint unsigned int #define uchar unsigned char sbit segoe=P1^3; //Enable control terminal of digital tube, low level is effective sbit duanxuan=P1^4; //Segment selection control of digital tube, 7
[Microcontroller]
LCD1602_8 data
         Programs should be written in their own style ****************************************************** ** This is a 1602 program written when learning msp430g2553 microcontroller ** ** Time is accurate to us, basically no garbled characters ** ** P1 is the data output port ** ** rs is connected to p2.1 ** ** rw
[Microcontroller]
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号