Lab 1: C Variables and Data Types

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 Main_Open_Project.png 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 OpenProjectButton.png.

2

Debug Project

Click on the Debug Project Main_Debug_Project.png 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 Debug_Pause.png 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.

Lab01Code.png

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:

Uart1.png

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.

Vars.png

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).

DataMemory.png

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 Debug_Finish_Debugger_Session.png 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).

© 2024 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.