In the development and application of single-chip microcomputers, high-level languages have gradually been introduced, and C language is one of them. For those who are used to assembly language, they always feel that high-level languages are not as controllable as assembly language. However, as long as we have a certain knowledge of C language, some things are still easy to do. The following are several problems encountered in the author's actual work, hoping to help beginners of C51.
1. Preparation of C51 hot start code Industrial control computers are often equipped with watchdog circuits. When the watchdog is activated, the computer is reset, which is a hot start. During a hot start, it is generally not allowed to start from the beginning, which will cause the existing measured or calculated values to be reset, resulting in abnormal system operation. Therefore, the program must determine whether it is a hot start or a cold start. The common method is: determine a certain memory unit as a flag bit (such as 0x7f bit and 0x7e bit), and read the content of the memory unit first when starting. If it is equal to a specific value (for example, both memory units are 0xaa), it is considered a hot start, otherwise it is a cold start. The program executes the initialization part and assigns 0xaa to the two memory units. According to the above design ideas, when programming, set a pointer to point to a specific memory unit such as 0x7f, and then judge it in the program. The program is as follows: void main() { char data *HotPoint=(char *)0x7f; if((*HotPoint==0xaa)&&(*(--HotPoint)==0xaa)) { /*hot start processing*/ } else { HotPoint=0x7e; /*cold start processing *HotPoint=0xaa; *(++HotPoint)=0xaa; } /*normal working code*/ } However, in actual debugging, it is found that no matter it is a hot start or a cold start, the values of all memory cells are reset to 0 after startup, and of course the hot start requirement cannot be achieved. Why is this? It turns out that when programming in C language, the code executed at startup does not start from the first statement of the main() function. Before the first statement of the main() function is executed, a section of "startup code" must be executed first. It is this section of code that performs the reset work. The C compiler provides the source program of this section of startup code, named CSTARTUP.A51. Open this file and you can see the following code: . IDATALEN EQU 80H ; the length of IDATA memory in bytes. . STARTUP1: IF IDATALEN <> 0 MOV R0,#IDATALEN - 1 CLR A IDATALOOP: MOV @R0,A DJNZ R0,IDATALOOP ENDIF . It can be seen that before executing the code to determine whether to hot start, the startup code has cleared all memory units. How to solve this problem? Fortunately, the startup code can be changed. The method is: modify the startup.a51 source file, and then use the a51.exe program attached to the compiler to compile startup.a51 to get the startup.obj file, and then use this code to replace the original startup code. The specific steps are (assuming that the C source program is named HOTSTART.C): Modify the startup.a51 source file (this file is in the C51\LIB directory). Execute the following command: A51 startup.a51 to get the startup.obj file. Copy this file to the directory where HOTSTART.C is located. Compile the compiled C source program with C51.EXE to get the target file HOTSTART.OBJ. Use the L51 HOTSTART, STARTUP.OBJ command to connect and get the absolute target file HOTSTART. Use OHS51 HOTSTART to get the HOTSTART.HEX file. Modify startup.a51 according to your own needs. For example, change 80H in IDATALEN EQU 80H to 70H, so that the 16-byte memory from 6F to 7F will not be cleared. 2. Directly call the program solidified in EPROM . The emulator I use is displayed by a 6-digit digital tube. The display subroutine is placed at DE00H in the memory. Just put the number to be displayed into the display buffer, and then call this subroutine to use it. The assembly instruction is: LCALL 0DEOOH . How to implement this function when programming in C language? There is a concept of pointer to function in C language, which can be used to implement calling functions with function pointers. The definition format of the pointer variable pointing to the function is: type identifier (*pointer variable name)(); After defining the pointer, you can assign a value to the pointer variable to point to the starting address of a function, and then use (*pointer variable name)() to call this function. The following example: void main(void) { void (*DispBuffer)(); /*Define a pointer to a function*/ DispBuffer=0xde00; /*Assign a value*/ for(;;) { Key(); DispBuffer(); } } 3. Convert floating point numbers into character arrays When I was compiling an application, I had the following requirement: store the result of the operation (floating point number) in EEPROM. We know that floating point numbers are stored in IEEE format in C language. A floating point number occupies four bytes. For example, the floating point number 34.526 is stored as (160, 26, 10, 66). To store a floating point number in EEPROM, you actually need to store these four numbers. So how do you get the numbers that make up a floating point number in the program? When floating point numbers are stored, they are stored in continuous bytes. As long as you try to find the storage location, you can get these numbers. You can define a void pointer, point this pointer to the floating point number that needs to be stored, and then force this pointer to be converted to char type. In this way, you can use the pointer to get the values of the bytes that make up the floating point number. The specific program is as follows: #define uchar unsigned char#define uint unsigned intvoid FtoC(void) { float a; uchar i,*px uchar x[4]; /*Define a character array to store four bytes of floating point numbers*, void *pf; px=x; /*px pointer points to array x*/ pf=&a; /*void pointer points to the first address of the floating point number*/ a=34.526; for(i=0;i<4;i++) { *(px+i)=*((char *)pf+i); /*Force the void pointer to be converted to char type, because*/ } /*void pointer cannot be operated*/ } If the number has been stored in EEPROM and you want to take it out and merge it, the method is the same. You can refer to the program below. #define uchar unsigned char#define uint unsigned int void CtoF(void) { float a; uchar i,*px uchar x[4]={56,180,150,73}; void *pf; px=x; pf=&a; for(i=0;i<4;i++) { *((char *)pf+i)=*(px+i); }
|