The purpose of this lab is to illustrate how variables are declared, and how the data type of a variable affects the way it is stored in memory. It also illustrates how to view the variables within MPLAB® X, both in their high-level context as well as machine-level context. Upon completion of this exercise, you will understand how to view C level variables in MPLAB X and how they are stored in memory based on their data type.
Note that while we will be using the XC16 compiler for these exercises, and that data memory is 16-bits wide, the fundamentals remain the same when used with one of the 8-bit compilers such as MPLAB C18. Only the size of some variables and the width of data memory in the display windows will change.
Software Tools
Tool | About | Installers |
Installation
Instructions |
||
---|---|---|---|---|---|
Windows | Linux | Mac OSX | |||
MPLAB® X
Integrated Development Environment |
| | | | |
MPLAB® XC16
C Compiler |
| | | | |
Exercise Files
File | Download |
Installation
Instructions |
||
---|---|---|---|---|
Windows | Linux | Mac OSX | ||
Project and Source Files
|
| | | |
Procedure
1
Open the Project
Start MPLAB X, then click on the Open Project icon on the main toolbar.Navigate to the folder where you saved the exercise files for this class.
Click on the Lab01.X folder.
Select Open Project .2
Debug Project
Click on the Debug Project button. This will build and send the program to the simulator to begin the simulation.Wait for the UART1 Output window to finish printing.
Click on the Halt button. This will stop execution so that we may examine the variables and their values.3
What just happened?
We took a pre-configured MPLAB X project, which included a complete C program along with the configuration settings for the tools, and compiled the code contained in the project. After compiling the code, we ran it in the simulator that is built into MPLAB X. The simulator is capable of reproducing almost all of the functions of a PIC® microcontroller. The code itself doesn't do very much. We simply create and initialize a set of six variables. We then print out the size of these variables to the UART 1 Output window by using the printf() standard C library function. After stopping the code, we may then observe the contents of the variables and see how they are stored in the device’s memory.
Results
Let’s take a look at what this code did when it was executed in the simulator. Some things might not make complete sense at this point since they will be covered in detail later on. Rest assured, we will cover all of this as we go forward.
Note that in the code below some of the comments and line spacing has been changed from the lab file. This was done in order to save space.
Line 7
Include header file for standard I/O routines. This header file is required because we will be using the printf() standard I/O library function later in this program.
Line 12
Define a constant called CONSTANT1 whose value is 50. Constants will be discussed in another section.
Line 18
This is a function prototype for the main() function. Function prototypes will be discussed later.
Line 28
This is the beginning of the main() function. Every C program must include this function, we will discuss the specifics of this later. The application code will begin executing with the main() function, and the syntax must look something like this:
Lines 33-38
Here we declare six variables of different types. Note that the variables declared as short and long could have also been declared with their full type names of short int and long int, though very few C programmers write code that way.
Lines 43-48
Here we initialize the variables we declared on lines 33-38. They are all initialized to have the same value, which is CONSTANT1 or 50. Remember that a char is just an 8-bit integer, so it is perfectly fine to assign an integer numeric value to it.
Lines 53-58
These lines print out the size of the data types to the UART 1 Output window in MPLAB X. The printf() function’s syntax will be discussed later. It is not commonly used in an embedded environment, but it can be useful for debugging your code. In an actual microcontroller, printf() is often used to send a text string out the on-chip UART. We make use of the size of the operator as a parameter to the printf() function, which will be discussed in the section on operators.
After the code completes execution, we will be able to observe the results in several ways:
The UART 1 Output window should show the text that is output by the program, indicating the sizes of C’s data types in bytes.
The Variables window should show the values which are stored in the variables and make it easier to visualize how much space each one requires in data memory (RAM).
From the Variables window above, we can see the addresses of the variables (will be different on your machine) and we can see how many bytes they occupy by looking at the length of the data in the Value column. Based on this information, we can construct a memory map of our variables.
Note that this example is laid out for a Microchip 16-bit microcontroller. For an 8-bit microcontroller, the data types will typically occupy the same number of bytes (some compilers define int to be only a single byte), but they would not be arranged side-by-side as shown.
4
End Debug Session
Clear the UART 1 window. Put the cursor in the UART 1 window then enter Ctrl + L. This will clear the UART 1 window before your next simulation.
End the Simulation Session by clicking the Finish Debugger Session button. Then close the Project.Conclusions
You have now seen how to declare variables:
type identifier1, identifier2, ... , identifierN;
You have also seen that different data types occupy different amounts of RAM. Since memory resources are relatively scarce in an embedded system, choosing the optimal data type for your variables is very important. This doesn’t mean that you should always use the smallest type possible. Using a char in a 16-bit architecture might allow you to pack two 8-bit variables into a single RAM location, but it may also cause more code to be generated when manipulating those variables. As a general rule, the most highly optimized data type for a given architecture is the one that matches the data word width. For an 8-bit architecture, char is often the best. For a 16-bit architecture, an int is often best. Just keep in mind that not every compiler defines a int as 16-bits.
You have also seen how we can look at the contents of variables using the MPLAB X IDE and that you can look at the value of the variable as the C compiler sees it, as well as the raw value as it is stored in data memory (RAM).