A variable is a quantity whose value can change continuously during the execution of a program. To use a variable in a program, you must first use an identifier as the variable name and indicate the data type and storage mode used, so that the compiler system can allocate the corresponding storage space for the variable. The format for defining a variable is as follows:
[Storage type] Data type [Memory type] Variable name table
In the definition format, except for the data type and variable name table, which are necessary, the others are optional. There are four types of storage: auto, external, static, and register, and the default type is auto. The specific meaning and usage of these storage types will be further studied in Lesson 7 "Variable Storage".
The data type here is the same as the definition of the data type we learned in Lesson 4. After describing the data type of a variable, you can also choose to describe the memory type of the variable. The description of the memory type is to specify the storage area used by the variable in the microcontroller C language hardware system and accurately locate it during compilation. Table 6-1 shows the memory types that KEIL uVision2 can recognize. Note that in the AT89c51 chip, only the lower 128 bits of RAM are available, while the upper 128 bits from 80H to FFH are only useful in the 52 chip and overlap with the special register address.
Memory Type | illustrate |
data | Direct access to internal data memory (128 bytes), fastest access speed |
bdata | Bit-addressable internal data memory (16 bytes), allowing mixed bit and byte access |
the data | Indirect access to internal data memory (256 bytes), allowing access to all internal addresses |
pdata | Paging access to external data memory (256 bytes), accessed using MOVX @Ri instruction |
xdata | External data memory (64KB), accessed using MOVX @DPTR instruction |
code | Program memory (64KB), accessed with MOVC @A+DPTR instruction |
如果省略存储器类型,系统则会按编译模式SMALL、COMPACT或LARGE所规定的默认存储器类型去指定变量的存储区域。无论什么存储模式都能声明变量在任何的8051存储区范围,然而把最常用的命令如循环计数器和队列索引放在内部数据区能显著的提高系统性能。还有要指出的就是变量的存储种类与存储器类型是完全无关的。
Data storage mode
The storage mode determines the default storage area for variables, function parameters, etc. that do not have an explicitly specified storage type. There are three types in total:
Small mode: All default variable parameters are loaded into the internal RAM. The advantage is fast access speed, but the disadvantage is limited space. It is only suitable for small programs.
Compact mode: All default variables are located in a page (256Bytes) of the external RAM area. The specific page can be specified by the P2 port and described in the STARTUP.A51 file. It can also be specified by pdata. The advantage is that the space is more spacious than Small, the speed is slower than Small, and faster than large. It is an intermediate state.
Large mode: All default variables can be placed in an external RAM area of up to 64KB. The advantage is that the space is large and more variables can be stored. The disadvantage is that the speed is slower.
Tip: The storage mode is selected in the microcontroller C language compiler options.
Previously, we briefly mentioned the methods of defining variables using sfr, sfr16, and sbit. Now let's take a closer look. sfr and sfr16 can directly define the special registers of the 51 microcontroller. The definition method is as follows:
sfr special function register name = special function register address constant;
sfr16 special function register name = special function register address constant;
We can define the P1 port of AT89c51 like this
sfr P1 = 0x90; //define P1 I/O port, its address is 90H
The sfr keyword is followed by a name to be defined. You can choose any name, but it must comply with the naming rules of identifiers. It is best if the name has a certain meaning. For example, port P1 can be named P1, which will make the program much easier to read. The equal sign must be followed by a constant. Expressions with operators are not allowed, and the constant must be within the address range of the special function register (80H-FFH). For details, please refer to the relevant table in the appendix. sfr is used to define an 8-bit special function register, while sfr16 is used to define a 16-bit special function register, such as the T2 timer of 8052, which can be defined as:
sfr16 T2 = 0xCC; //Here define 8052 timer 2, address is T2L=CCH, T2H=CDH
When using sfr16 to define a 16-bit special function register, the equal sign is followed by its low-order address, and the high-order address must be above the physical low-order address. Note that it cannot be used to define timers 0 and 1.
sbit can define a bit-addressable object, such as accessing a bit in a special function register. In fact, this application is often used, such as accessing the second pin P1.1 in port P1. We can define it as follows:
(1) sbit bit variable name = bit address
sbit P1_1 = 0x91;
This assigns the absolute address of the bit to the bit variable. Like sfr, the bit address of sbit must be between 80H and FFH.
(2) Sbit bit variable name = special function register name ^ bit position
sfr P1 = 0x90; sbit P1_1 = P1^1; //First define a special function register name and then specify the position of the bit variable name
This method can be used when the addressable bit is located in a special function register
(3) sbit bit variable name = byte address ^ bit position
sbit P1_1 = 0x90^1;
This method is actually the same as 2, except that the address of the special function register is directly represented by a constant.
In the microcontroller C language memory type, there is a bdata memory type, which refers to a bit-addressable data memory located in the bit-addressable area of the microcontroller. The data that requires bit-addressable data can be defined as bdata, such as:
unsigned char bdata ib; //define ucsigned char type variable ibint bdata ab[2]; //define array ab[2] in the bit-addressable area, these are also called addressable bit objects sbit ib7=ib^7 //use keyword sbit to define bit variable to independently access one bit of addressable bit object sbit ab12=ab[1]^12;
The maximum value of the bit position following the operator "^" depends on the specified base address type, char0-7, int0-15, long0-31.
Next, we will use the circuit from the previous lesson to practice the knowledge of this lesson. We will also do a simple marquee experiment, and the project name is RunLED2. The program is as follows:
sfr P1 = 0x90; //No predefined file is used here, sbit P1_0 = P1^0; //Instead, define the special register sbit P1_7 = 0x90^7; //The predefined file we used before actually has this function sbit P1_1 = 0x91; //Here, define the P1 port and P10, P11, and P17 pins respectively void main(void) { unsigned int a; unsigned char b; do{ for (a=0;a<50000;a++) P1_0 = 0; //Light up P1_0 for (a=0;a<50000;a++) P1_7 = 0; //Light up P1_7 for (b=0;b<255;b++) { for (a=0;a<10000;a++) P1 = b; //Use the value of b to make a marquee pattern } P1 = 255; // Turn off the LED on P1 for (b=0;b<255;b++) { for (a=0;a<10000;a++) //P1_1 flashes P1_1 = 0; for (a=0;a<10000;a++) P1_1 = 1; } }while(1); }
Keil c51 pointer variable
microcontroller c language supports general pointer (Generic Pointer) and memory pointer (Memory_Specific Pointer).
1. 1. General pointer
The declaration and use of general pointer are the same as standard C, but it can also indicate the storage type of the pointer, for example:
long * state; // is a pointer to a long integer, and state itself is stored according to the storage mode. char * xdata ptr; // ptr is a pointer to char data, and ptr itself is placed in the external RAM area. The data pointed to by the above long, char and other pointers can be stored in any memory.
Generally, the pointer itself is stored in 3 bytes, which are the memory type, high offset, and low offset.
2. 2. Memory pointers
specify the storage type when describing the memory pointer, for example:
char data * str; //str points to the char type data in the data area int xdata * pow; //pow points to the int type integer in the external RAM.
When storing this type of pointer, only one or two bytes are needed, because only the offset is needed.
3. 3. Pointer conversion
is the conversion of pointers between the above two types:
when a memory-based pointer is passed as an actual parameter to a function that requires a general pointer, the pointer is automatically converted.
If the external function prototype is not declared, the memory-based pointer is automatically converted to a general pointer, resulting in an error, so please use "#include" to declare all function prototypes.
The pointer type can be forcibly changed.
Storage class of variables
1. static (static local) variables.
1. Static local variables will not release memory during the entire program running period.
2. For static local variables, the initial value is assigned at compile time, that is, it is only assigned once. If there is an initial value when the program is running, it will not be reassigned each time it is called.
3. If no value is assigned when defining a local variable, it will be automatically assigned to 0 at compile time. For automatic variables, if no value is assigned when defined, it is an uncertain value.
4. Although static variables still exist after the function call ends, other functions cannot reference them.
2. Use extern to declare external variables.
Using extern to declare external variables is to expand the scope of external variables. For example, a program can be composed of multiple source program files. If a program needs to refer to an external variable that has been defined in another file, it needs to use extern to declare it.
The correct approach is to define the external variable in one file and use extern to declare the variable as an external variable in another file.
In one file: int abc;
In another file: extern abc;
Example: Use extern to extend the scope of external variables to other files:
File 1:
//Use extern to extend the scope of external variables to other files#include #include #include unsigned int array[10];void fillarray();void init_ser() { SCON=0X50; TMOD|=0X20; TH1=0XF3; TR1=1; IF=1; }void main() { unsigned int i; init_be(); fillarray(); for(i=0;i<10;i++) { printf("array[%d]=%d\n",i,array[i]); } for(;;){;} }
File 2:
extern int array[10];void fillarray() { unsigned char i; for(i=0;i<10;i++) { array[i]=i; } }
There are several ways to allocate the space of variables in the C language of single-chip microcomputers.
1. The data area has a small space, so only variables that are frequently used or require high computing speed are placed in the data area, such as the count value in the for loop.
2. It is best to put local variables in the data area. Because the space of local variables can cover the local variable space of a function, it will be released when the function is exited and covered by the local variables of other functions, which can improve memory utilization. Of course, static local variables are excluded, and their memory usage is the same as global variables;
3. Make sure there are no uncalled functions in your program. In Keil C, when an uncalled function is encountered, the compiler will consider it as an interrupt function. The space of local variables used in the function is not released, that is, it is treated the same as global variables. Keil C is stupid in this regard, but there is no way.
4. The logical flag variables encountered in the program can be defined in bdata, which can greatly reduce the memory space occupied. There are 16 bytes of bit addressing area bdata in the 51 series chip, in which 8*16=128 logical variables can be defined. The definition method is: bdata bit LedState; but the bit type cannot be used in arrays and structures.
5. Other variables that are not frequently used and do not require high computing speed are placed in the xdata area.
6. If you want to save data space, you must use the large mode and put all variables with undefined memory locations in the xdata area. Of course, it is best to specify the memory type for all variables.
7. When using pointers, specify the memory type that the pointer points to.
In the microcontroller c51 language, a general pointer that does not define a memory type occupies 3 bytes; a pointer that points to the data area only occupies 1 byte; a pointer that points to the xdata area occupies 2 bytes. If the pointer p points to the data area, it should be defined as: char data *p;. You can also specify the storage memory type of the pointer itself, such as: char data * xdata p;. This means that the pointer p points to the variable in the data area, and it itself is stored in the xdata area.
Previous article:The startup process of C program in keil c51
Next article:The use of pointers in Keil C51
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Circuit Playground Bluefruit NeoPixel Animated Remote Control
- GD32F105RBT6 About FMC internal flash operation issues
- This week's review information is here~
- About 48V input buck type DCDC chip
- Some characteristics of MSP430 interrupts
- Where is the SD card of sensorTile.box
- Some questions about Bluetooth Mesh
- Read the good book "Operational Amplifier Parameter Analysis and LTspice Application Simulation" for free, take notes, and master the knowledge of operational amplifiers thoroughly
- About the problem of inaccurate reading of MAX6675
- Push-pull circuit