c programming for MSP430

Constants and variables

When defining constants to make more readable programs or to allow for easy changes of constants used in multiple places use #define, rather than const . The constant declaration forces the compiler to create a variable in RAM at runtime. Define simply creates a code in the program memory this is much more efficient.

Static and Volatile variables are different. A static variable is simply a variable that exists for the lifetime of the application. Static variables can be global: defined outside of a function and accessible everywhere, or local: defined within a function and only accessible from within that function. Local static variables are created on the first invocation of the function and remain in memory for the function to use when next called. The static keyword enforces the compiler to ensure that the RAM for the variable is always reserved and not reused for other variables.

static int state = 0;

So if you need a variable that is only used within a function and only updated by that function and you need the value of that variable to remain for the next time that you call the function then you need to define it as a static variable.

where the value of count needs to be kept for the next time the function is called.

A volatile variable is one the can be changed without the compilers knowledge for example by an interrupt. This means that whenever this variable is accessed by the program it must be reread from the actual memory location in case it has changed, rather than simply read from the cache or registers on the ALU if it has already been used recently by the program.

volatile int state = 0;

A variable can be both static (always present) and volatile (changed from anywhere).

static volatile int state = 0;

Arrays

Arrays allow for the storage and retrieval of multiple values using indexing.

Loops: while, for

Functions

Functions allow you to reuse and encapsulate code. to use functions in c it is first necessary to define the function prototype as the top of your code before the main function. This necessary so that the compiler knows that the functions exist. The function prototype is simply the function declaration terminated with a semicolon.

The function itself can then appear anywhere after your main function. The main function should be the first function that appears in your code and does not require a function prototype. Functions do not need to return any values or have any inputs. the key word void is used. A function can only have one output with is returned using the return keyword.

The ‘int’ type definition when defining a pointer specifies the size of the memory location that the pointer points to in this case the size of myVariable. The size of the pointer itself depends on the size of the address used by the computer or micro controller and is taken care of by the compiler. The ‘*’ indicates that we are defining a pointer variable. We then assign the memory location of the variable myVariable to the pointer myPointer using the & operator.

We can now use the pointer to access the value stored at the memory location it points to.

int x; // Define new variable x
x = *myPointer; //Copy the value stored in the location that the pointer points to into x

Here the ‘*’ indicates that we want the contents stored at the memory location (in this case 1000) not the value of the pointer itself which simply contains the memory address.

These examples seem a little pointless as here we are only dealing with variables that refer to a single memory location. In fact the variable myVariable is really already a pointer to the memory location where the value is stored. However pointers become really useful when you have arrays. Consider an array (myArray) that is able to hold 5 integers.

Now whilst the code above is correct in practice you will never see this because for arrays you can drop the ‘&’ that is required to indicate you want the address of the Variable not its value. Note for variables that are not arrays i.e. only single values you must use the ‘&’ notation. For arrays the simplified code as shown below

Pointers really come into their own when you want to define functions that operate on variables and arrays without requiring the function to first make a local copy of the variable to use within the function. They also allow you to update multiple variables from within a function and make these accessible after the function has completed. You first need to define the variables that you wish to operate on as volatile variables before the main function. You then define the inputs to the function as pointers. In this way the function only creates a local copy of the pointer within the function not the variable itself. You can see that if your function operates on arrays this is going to be much more efficient as the pointer to the array is a single address, whereas to create a local copy of a large array would require the same amount of memory as the original array again. In this way when you pass the variables to the function only the pointer to the variable is passed. Inside the function no new variables are created and the function simply writes or changes the variables in the location pointed to by the pointer. Thus when the function finishes your original variables will have been changed.

As an example consider a function that takes in two char inputs and swaps them.

You can see that the function definition defines the inputs as pointers to chars. Inside the function the value stored at the location pointed to by a is temporarily stored in a variable c that is created within the function. The value stored at the location pointed to by b is then copied into location pointed to by a and finally the value of c is copied into the location pointed to by b. Note also when we call the function from within main it is necessary to use the & notation to ensure we pass the address to the variables not the variables themselves as these variables are not arrays.

The UARTSendArray function below is an example of using pointers to pass an array to a function.

This example also highlights another nice feature of pointers because the UART is only able to transmit 8 bit bytes the type that the TxArray pointer points to is defined as a char. However we can use this function to send the contents of an integer array one byte at a time. This works because when we call the function UARTSendArray(data, 4); the pointer TxArray created by the function simply points to the first address of data. Now when the value of the pointer address pointer is incremented by TxArrray++ it is only incremented to the address of the next byte as the data type that the pointer was defined as pointing to was char, even thought the original data array was defined as an integer. In order to transmit the entire data array as bytes it is therefore necessary to specify the array length as twice that of the integer array.

There is actually no need to declare A and B as volatile as in this code the values of A and B are only changed within the swapChars function. If however the values of A and B could also be changed within an interrupt then they would need to be declared volatile.

I believe that’s not what he meant… instead of declaring
volatile char A;
volatile char B;
you should have declared
volatile char x1;
volatile char x2;
since we dont use any valiable A nor B, but x1 and x2.

Hi, its nice explanation, I am also having a website for sharing my ideas and projects http://www.buildfromzero.com I invite you to take a look at it. I am planning to create a good knowledge base like your, but in initial stage. I have a doubt, how did you post the codes in that format (in wordpress)?