Detailed CodeWarrior for MC68HC908GP32CP C language pointer from a small program

xiaoxiao2021-03-06  39

#include #include

/ * After establishing a C language in CodeWarrior, the program automatically introduces the header file MC68HC908GP32.h defines the typedef unsigned char byte; typedef unsigned int Word; typedef unsigned ing dlong [2]; typedef unsigned long dlong [2]; type; If it is enough, it is recommended to use Byte instead of int because it only takes one byte, and the memory is scarce resources in the single-chip microcomputer. Very precious * /

Byte a @ 0x0050; // Define Unsigned Char is placed in 50 units, which can only be used for // global variables.

BYTE * P @ 0x0051; // Define a pointer to 0x0051 unit, pointing to a unsigned char, // does not define any addresses. Note! This is very important here, // While Byte (unsigned char) only one byte, this pointer is // is two bytes, that is, the 0x0051 and 0x0052 stores this // pointer, respectively. High, low byte.

Byte B @ 0x0060; // Define a variable is placed in 60 units

#define c (* (volatile Byte *) 0x0058) // Another way to specify an address for variables: macro definition // Do not feel confused or irritated for this complex way, // It can also decompose into a few Simple part: // (volatile Byte *) is a Type of conversion type in the C language // its role is to convert 0x0058 this pure hexadecimal number / / to an address, where Volatile is not necessary / /, It just tells the compiler, this value is related to the external environment, // Do not optimize it. There is no need to discuss too much of the compiler's // body mechanism [1]. Next, I added an // * number outside, indicating the contents of the 0x0058 memory cell. // After this macro definition, C is operated as a normal // variable, all of which is compiled when C is compiled (* (Volatile Byte *) 0x0058), external /// A group of parenthesis is to ensure that the operation inside will not be changed because the operation // operator priority or other unpredictable reasons can be changed / / cannot be obtained.

Void main (void) {byte i; // Defining a BYTE type changing face i, I don't know which memory unit Byte * p2; // has a pointer, point to a Byte type A = 0x70 ; // a assignment 0x70, remember, a in 50 units is MOV # $ 70, $ 50 c = 0x30; // Mov # $ 30, $ 58 p = (Byte *) 0x60; // P pointing 60 unit, 60 units The P is naturally b, which is naturally pointed to B, which is not omitted (byte *), which is also a mandatory type conversion, which tells the compiler, // 0x60 is no longer a pure hexadecimal number, it has already represented a memory unit. P2 = (byte *) a; // a number stored in the 0x70, now forced it to convert it into the address type, p2-> 0x0070 for (i = 0; i <0x10; i) // 16 times {* P = i a; // put the value of the i 0x70 to the point to the P-point, the cycle begins, p-> 0x60, // increase 1 each time, until P-> 0x70, after the cycle It can be seen that 70, 71, ..., 7f is stored in // 60 to 70 units. * P2 = (Byte) P ; // Save the address value to the P2 in the address pointed to by P2 (starting from 0x60), then // p to 1 for the next loop; P2 increase 1 for saving the next cycle The // address pointing in the middle P. After the cycle is over, it can be clearly seen that the 16 cycles from 60 units to 6f unit / / pointer P all values: 60, 61, ..., 6f. // As with the previous, it is essential, and P is the pointer, saved // is the address value. Now you have to assign the address value as a pure hexadecimal number to assign the value // give P2 The pointed unit must force the type conversion. * (Byte *) 0x0080) = (byte) p; // [2] This method is used to use it when we started. Yes! It is // to define the macro #define c (* (Volatile Byte *) 0x0058) // The title is exactly the same.

This kind of writing can be completely unreasonable to define global variables (the global variable must be defined when using @ keyword), // can also avoid using #define macro definitions such possible becoming // unsafe factor The root call is written, and the variable // placed in any allowable memory unit during the program run. This is very useful, especially when you need to see the value of a certain variable. // __ reset_watchdog (); // temporarily ignoring watchdog. Because the program small loop is not / / it overflows the reset 16 times. But I wrote it, because there is a more mysterious // problem later. } * (Byte *) 0x0081) = (Byte) P; // [3] The cycle ends, put the P pointing address value into the 81 unit. Haha, // can be thought of with a knee, and the value stored in the 81 unit must be 70.

* (INT *) 0x0082) = (int) & i; // End, now what we can do is so much, so * (INT * 0x0084) = (int) & p2; // Who is Can you tolerate unknown things? I don't know if I don't know if I compile the variable I (or pointer P2) after compiling, but if you are now only satisfied, I don't know It is too sad: (. I // I am not a person who wants to be easy to satisfy. I must figure out. So // This mechanism of mandatory type conversion helped us again. I don't explain // These two Sentence, because they have now become so clear. The only description //, here, use int without using byte because I can't guarantee the address of the i and // p2.} / * Well The loop is over, the program is running, and the mysterious problem is to be put forward. If you find [2] and [3], you have done the same thing. Select two adjacent addresses 80 and 81. There is also a place that also saves P pointing at the address, which is 51 units (still remember byte * p @ 0x0051; "I emphasized, Byte is a byte, but Byte * defaults to two bytes, and I convert two bytes of P in two (BYTE) mandatory types in [2] and [3], will generate errors Isn't it. It's very simple, because the P itself here has only one byte, after the type conversion, the 80 and 81 units save P's low bytes, this is enough .0x51,0x80,0x81 Save the value of the address pointing, is there any? 0x51 is the location of the P definition, it can be calculated that its Hometown, 0x81 stores the address of P pointing after the loop, is 0x70, and 0x80? It stores the value of P at the end of each cycle, and is different from the 51 unit and 81 unit. When each cycle, he will change, the change process is 0X after the cycle ends. The values ​​stored in the 60 to 0x6f address. This can be inferred that after the last cycle of the program, the value of the 0x80 and 0x81 unit should be consistent, see your memory, consistent? 0x51 and 0x80 are consistent, and 0x81? Oh, if I didn't If you guess, the value of 51 units and 80 units is 64, while the 81 unit is determined by us, it is a thousand trikin. Why? I found that the problem is more significant than solving the problem. In order to solve this problem, we only have a single step run. Set an endpoint at the entrance of the main () function, then click Continuously, let the program stop to run after the beginning of the initialization, start single-step operation at the main () entry.

Step by step, two steps, three steps, ..., until sixteen cycles, it is found to find that the 51 unit and 80 unit are indeed 70, which is more confused, why is the single-step run to get expected results However, it will not work continuously? Don't worry, the story has not ended, continue to run, 咦, what is the program jumps? Oh, welcome to the end of the world ^ _ ^. This is a place where the procedure is actually, that is, we have set up a breakpoint, and the program returns here. What else can you explain - this general program is performed forever, he will not stop, complete again ,do it again. Hey, the distance to explore the truth is really hard and full of fun :). Ok, now I can answer the mysterious problem: Why is the 51 unit, the pointer address in the 80 unit will be different in the 81 unit. The value in the 81 unit is the last address (6f) plus 1 (70) of the finger P, which is unquestionable, and 51 units and 80 units are second times in the total program, third times, ... constantly During the execution process, it was changed again. During this period, the 81 unit is also rewriting each time, but it is rewritten by the same value 70, so there is no change. The total program will not be in this past, and I have bought a Cat in __reset_watchdog (); this sentence of this sentence, I am now revealing the mystery, because I don't feed the door dog. When the program is repeatedly executed over and over again, it will always make the watchdog counter overflow reset, so that the entire program stops, but the FOR cycle is not necessarily executed for 16 times, it may be When the door is reset, the value of the 51 unit and 80 unit is the address pointing to the current pointer P, which is 0x64, while the 81 unit is still the end of the last FOR cycle. Of course, it will not be the same. The problem is solved, but it is incomplete, if we prohibit the watchdog? Remove __reset_watchdog (); front reference, in the executive, this time you see the CPU Cycles continuously increase, the program has been running, Open the memory window, will open to the value of the 51 unit and 80 units in constant changes (here there is a tip, after the full screen memory window, click the scroll bar in the right, the value inside the window will continue to refresh), of course, you It is also possible to let the program stop in a place, and the value of the 51 and 80 units at this time is uncertain, and the two may be equal, and it may also be different, and the 81 unit must be 70. The problem is finally solved here. * /

/ * Summary points: 1. Byte defaults to a byte, but byte * defaults to two bytes. 2. The C language program in CodeWarrior is a constant loop run. Even if the program itself does not loop, it will automatically start again after execution, until the watchdog counter overflows the reset (if the watchdog is not related if). 3. Three methods are placed on a specified memory unit: 1) macro definition. For example: #define value1 (* (volatile unsigned char *) 0x0040) // Defines variable value1 in 40 units [4]. 2) Use @ keywords, this time variable can only be globally. For example: volatile unsigned char value2 @ 0x0041; 3) Use the forced type conversion to change a hexadecimal number to the address value to store a value, for example: * ((unsigned char *) 0x0042) = value3; // of course, Value3 should be prior to define, and have been assigned. Play the imagination, we can even write: for (i = 0; i <0x10; i) * ((unsigned char *) 0x0043 i) = value4 [i]; // see it? We Put each value in an array to // 43, each memory cell started; the array value4 [] should // before it is. * /// ---------------------------------------------- -------------------------------------------------- --------- / * [1] In fact, the role of volatile byte * is similar to ReinterPret_cast in C , or reference byte * pointer = new (ReinterPret_cast (0x0058)) Byte Different, the Pointer here is a pointer, and the C which is defined in the program is just a BYTE type variable. Can refer to The C Programming Language (Special Edition

10.4.11) [4] Macro definition does not really define variables, it is just a compiled command. It tells the compiler that replace all values ​​in the back program when compiled (* (volatile unsigned char *) 0x0040). * /

转载请注明原文地址:https://www.9cbs.com/read-66886.html

New Post(0)