A Brief Analysis of the Meaning of Microcontroller C Language Pointers—Keil-C51

Publisher:石头上种庄稼Latest update time:2020-02-19 Source: 51heiKeywords:MCU Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

It is generally believed that the power and freedom of C language are largely reflected in its flexible use of pointers, and it is even believed that pointers are the soul of C language. Here, "usually" is said in a broad sense, because with the development of programming languages, pointers have also been controversial, and not everyone recognizes the "power" and "advantages" of pointers. In the field of single-chip microcomputers, pointers also have applications. This chapter briefly analyzes the meaning of pointers in the Keil C-51 environment.

1 Pointers and variables
A pointer is a variable. Like other variables, it is an area in RAM and can be assigned values, as shown in program ①.


#include "REG52.H"        
unsigned int j;
unsigned char *p;
void main()
{
         while(1)
         {
                   j=0xabcd;
                   p=0xaa;
         }
}
In Debug Session mode, move the mouse pointer to the position of variable "j" and "p" to display the physical address of the variable, as shown in Figure 1-1 and 1-2. 






The arrow in the figure is the "first address" of the variable in RAM. Why is it the "first address"? Variables can be divided into 8-bit (single byte) and 16-bit (double byte) according to their types. The variable "j" in the program is an unsigned integer and occupies 2 bytes of physical space. In an 8-bit microcontroller, the size of a RAM storage unit is 8 bits, that is, 1 byte, so 2 storage units are required to meet the length of variable "j". So in fact, the physical address of variable "j" is "08H" and "09H". Similarly, "p (D: 0x0A)", that is, the first address of variable "p", is "0AH".


Next, we will observe the data changes in RAM by executing the program step by step. Open two Memory Windows windows, which are displayed as Memory1 and Memory2 under the Keil software. In the two windows, make the settings shown in Figures 2-1 and 2-2 respectively.






The contents of the two Addresses are: D:0x08 and D:0x0A, which are the first addresses of the variables "j" and "p". After entering, press Enter to monitor the data at the address in RAM. After setting, prepare for debugging.

In the Debug Session mode, the arrow points to the statement to be executed. Click the "Step" function button (or press F11) to run the program, as shown in Figure 3.

After clicking the "Step" button for the first time, the data in the Memory1 window is shown in Figure 4.

From the debugging results, we can see that the 08H data changes from 00H to ABH, and the 09H data changes from 00H to CDH. This change occurs because the statement j=0xabcd is executed; 08H is the high eight bits of the variable "j", storing "AB", and 09H is the low eight bits of the variable "j", storing "CD".


Click the "Step" button for the second time to execute the statement: p=0xaa; At this time, you need to observe the data in the Memory2 window, as shown in Figure 5.

From the debugging results, it can be seen that the value at 0CH changes from 00 to "AAH", and the program is consistent. It should be noted here that in the Keil C-51 compilation environment, pointer variables, regardless of whether the length is single-byte or double-byte, occupy 3 bytes. Therefore, "AAH" here is not stored at 0AH but at 0CH (0A+2) address. In
summary, pointers are actually variables, which are mapped to a storage space in RAM. The difference is that pointers occupy 3 bytes, while other variables can be set to occupy 1 byte (char), 2 bytes (int), and 4 bytes (long) of RAM as needed.

2 The role of pointers
What is the role of pointers? Let's look at the following program first:
Program ②
#include "REG52.H"         
unsigned chartab1[8]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
unsigned char codetab2[8]={0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80}; 
unsigned char N1,N2;
void main()
{
            N1=tab1[0];
            N2=tab2[0];
}


Obviously, the result of program execution is N1=0x01, N2=0x10. Here, we are talking about assigning data in arrays to variables, but there is a difference. The tab1 array uses the MCU RAM space, while the tab2 array uses the MCU program storage area (ROM) space. Although the statements are the same when assigning values ​​to variables using C language, the compilation results are different. The result of this program after compilation is shown in Figure 6.
 

From the compilation results, we can see that the statement N1=tab1[0] is actually direct addressing, while N2=tab2[0] is register indexing addressing. Regardless of the addressing method, the data in a physical address is taken out and used: in the tab1 array, the RAM address corresponding to tab[0] is 0x0A, the RAM address corresponding to tab[1] is 0x0B... and so on; in the tab2 array, the ROM address corresponding to tab[0] is 0x00A5, the ROM address corresponding to tab[1] is 0x00A6... and so on. Regardless of the RAM or ROM address of these arrays or variables, what the user ultimately needs is the data of the array or variable, and the pointer is to access the data through the physical address of the variable or array, that is, the array or variable data can also be accessed through the pointer. Now adjust program ② and get program ③ as follows:
#include "REG52.H"         
unsigned chartab1[8]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
unsigned char code tab2[8]={0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80};
unsigned char N1,N2;
unsigned char *p;
void main()
{        
         unsignedchar i;
         p=tab1;
         for(i=0;i<8;i++,p++)
         N1=*p;
         
         p=tab2;
         for(i=0;i<8;i++,p++) 
         N2=*p;
}
Program execution result: The 8 values ​​in the tab1 array are assigned to N1 in turn; the 8 values ​​in the tab2 array are assigned to N2 in turn;
After executing the Debug Session function in program ③, open the Watch Windows window, and add the variables to be monitored in the Watch1 window, here are "p" and "N1", as shown in Figure 7.

Value is the current variable value. Before the program runs, the p value is 0x00. After clicking the Step button function, execute p=tab1; the p value changes to 0x0A, as shown in Figure 8.

What is the value of 0x0A? Move the mouse to the tab1 array position to display the physical address of the array. 0x0A is the first address of the array tab1, as shown in Figure 9.

p=tab1 is to assign the first address of the tab1 array to the variable p, and execute p++ to add 1 to the address value; *p is the specific data in this physical address, so in the for loop, N1=*p is to assign the data in the tab1 array to the variable N1 in turn. It can be seen that the pointer is a variable that points to a certain address.


So how does the pointer "get" the data in a certain address? The following is a demonstration using the N1=*p statement. The assembly code after N1=*p is compiled is shown in Figure 10.

The assembly code from C:0x00A0 to C:0x00A9 is N1=*p in the C program. The program first assigns the value of the variable p to the three general registers R3, R2, and R1. The program is:
MOV R3,p(0x12)
MOV R2,0x13
MOV R1,0x14
Then a sub-function is called: LCALL C?CLDPTR(C:00E4). In the C program, no sub-function is defined or used. So where does this sub-function come from? What is its function? According to the label C:00E4, the subfunction can be found. The program code is as follows:

C:0x00E4 BB0106 CJNE R3,#0x01,C:00ED
C:0x00E7 8982 MOV DPL(0x82),R1
C:0x00E9 8A83 MOV DPH(0x83),R2
C:0x00EB E0 MOVX A,@DPTR
C:0x00EC 22 RET      
C:0x00ED 5002 JNC C:00F1
C:0x00EF E7 MOV A,@R1
C:0x00F0 22 RET      
C:0x00F1 BBFE02 CJNE R3,#0xFE,C:00F6
C:0x00F4 E3 MOVX A,@R1
C:0x00F5 22 RET      
C:0x00F6 8982 MOV DPL(0x82),R1
C:0x00F8 8A83 MOV DPH(0x83),R2
C:0x00FA E4 CLR A
C:0x00FB 93 MOVC A,@A+DPTR
C:0x00FC 22 RET      

The function of this program is: first compare the value of register R3 with 0x01. When the value of R3 is greater than 0x01, compare it with 0xFE. The comparison results are as follows:
(1) When the value of R3 is equal to 0x01, execute the following program:
C:0x00E7 8982 MOV DPL(0x82),R1
C:0x00E9 8A83 MOV DPH(0x83),R2
C:0x00EB E0 MOVX A,@DPTR
C:0x00EC 22 RET      
program function: read the data in the extended RAM and assign it to A, the addressing range is 0 to 65535. When the array is defined as xdata, it will jump here.
(2) When the value of R3 is less than 0x01, that is, equal to 0x00, execute the following program:
C:0x00EF E7 MOV A,@R1
C:0x00F0 22 RET  
program function: read the data in the 256-byte RAM inside the microcontroller and assign it to A, the addressing range is 0 to 255. When the array is defined as data or idata, it will jump here. When the N1=*p statement is executed, it jumps to itself and reads the data in the internal RAM address.    
(3) When the value of R3 is not equal to 0x00 or 0x01, it jumps to C:0x00F1 through the JNC instruction and starts to compare with 0xFE. When the value of R3 is equal to 0xFE, execute the following program:
C:0x00F4 E3 MOVX A,@R1
C:0x00F5 22 RET  
Program function: Read the data in the external RAM of the microcontroller and assign it to A. The addressing range is 0 to 255. When the array is defined with pdata, it will jump here. Usually, the 8051 microcontroller does not use pdata to define variables or arrays.
(4) When the value of R3 is not equal to 0xFE, that is, when the value of R3 is equal to 0xFF, jump to C:0x00F6 and execute the following program:
C:0x00F6 8982 MOV DPL(0x82),R1
C:0x00F8 8A83 MOV DPH(0x83),R2
C:0x00FA E4 CLR A
C:0x00FB 93 MOVC A,@A+DPTR
C:0x00FC 22 RET


Program function: read the data in the MCU's internal ROM and assign it to A, with an addressing range of 0 to 65535. When the array is defined with code, such as in program ③, the tab2 array is defined with code, after executing p=tab2, the value of R3 is assigned to 0xFF, and when the N2=*p statement is executed, it jumps to itself and reads the data in the internal ROM address. 

 
It can be seen that the role of the sub-function "C?CLDPTR" is to read the data at a certain address using different addressing methods according to the storage space where the data is located. R3 is used to determine the addressing method. The corresponding relationship between the value of R3 and the corresponding addressing method is:
1. When the value of R3 is equal to 0x00, the on-chip RAM is indirectly addressed; at this time, the data is defined by dataidata.
2. When the value of R3 is equal to 0x01, the off-chip RAM (extended RAM) is indirectly addressed; at this time, the data is defined by xdata.
3. When the value of R3 is equal to 0xFE, the lower 246 bytes of the off-chip RAM (extended RAM) are indirectly addressed; at this time, the data is defined by pdata
. 4. When the value of R3 is equal to 0xFF, the storage memory (ROM) is indexed and addressed; at this time, the data is defined by code.

3.
The values ​​of the pointer structures R3, R2, and R1 are the values ​​in the addresses 0x12, 0x13, and 0x14 in the RAM, that is, the RAM address mapped by the variable p. In an 8-bit microcontroller, no matter what addressing mode is used, the maximum addressing range is 2 bytes (0 to 65535). Why does the pointer *p occupy 3 bytes of RAM space? The following program ④ explains.

[1] [2]
Keywords:MCU Reference address:A Brief Analysis of the Meaning of Microcontroller C Language Pointers—Keil-C51

Previous article:MCU + DC motor speed control program + Proteus simulation circuit
Next article:Detailed explanation of 51 single chip microcomputer controlling stepper motor

Recommended ReadingLatest update time:2024-11-16 14:24

51 single chip microcomputer key control digital tube 0~9
The lighting of LED lights, digital tubes, and buttons introduced earlier only use the IO resources of the 51 microcontroller. If we only use the microcontroller to light up lights and operate digital tubes, it would be a waste of resources. These are just the tip of the iceberg of the 51 microcontroller's resources.
[Microcontroller]
51 single chip microcomputer key control digital tube 0~9
Single chip high power solar LED street light circuit design and simulation analysis
   1. Introduction    As the fourth generation of lighting sources, LED is being used more and more widely in urban beautification, road lighting, garden lighting, indoor lighting and other fields with its unique advantages. Especially in remote areas without electricity, solar lighting fixtures are rapidly pr
[Power Management]
Single chip high power solar LED street light circuit design and simulation analysis
Basic concepts of microcontroller: instructions, bits, bytes, memory, bus
Microcontroller execution instructions Let's think about a problem. When we write an instruction into the microcontroller in the programmer, and then remove the microcontroller, the microcontroller can execute the instruction. Then this instruction must be stored somewhere in the microcontroller, and this place can s
[Microcontroller]
Anti-interference technology inside the microcontroller
  In electronic circuit design, in order to avoid detours and save time, the requirements of anti-interference should be fully considered and met. For example, cutting off the propagation path of interference and trying to use a single-chip microcomputer with strong anti-interference performance is also a very importan
[Microcontroller]
Keil macro definition and how to know the microcontroller resource name
In Keil's project settings, you need to change the macro definition according to the selected microcontroller. If the macro definition is not changed after the program is transplanted, an error may sometimes be reported. This macro definition represents the type of chip, as follows: Therefore, you need to cha
[Microcontroller]
Keil macro definition and how to know the microcontroller resource name
The self-adaptive implementation method of serial communication baud rate of single chip microcomputer
In serial asynchronous communication, there are many design ideas for realizing automatic baud rate detection and adaptation, but they either require additional hardware support, or the implementation methods are complicated and the software overhead is large. This article introduces a simple and reliable method to
[Microcontroller]
The self-adaptive implementation method of serial communication baud rate of single chip microcomputer
Single-chip microcomputer constant current device for single-phase bridge type semi-controlled electroplating DC power supply
【Abstract】 A single-phase bridge type semi-controlled electroplating DC power supply with a single-chip microcomputer constant current device belongs to the application of single-chip microcomputer control technology in a constant current device for electroplating DC power supply. It includes a thyristor voltage contr
[Analog Electronics]
Application of AVR single chip microcomputer in wireless automatic target reporting system
At present, in the field shooting training assessment, most of them are still through the method of manual target reporting, which has many human factors (such as the subjectivity and emotions of the target reporting personnel, etc.), affecting the results of the target reporting, making the shooter unable to correc
[Industrial Control]
Application of AVR single chip microcomputer in wireless automatic target reporting system
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号