13 July 2010

Tutorial 04: Stuck in a Loop

We now have enough to be able to write programs for the MSP430, so before we go into the peripherals that make the microcontroller useful, let's get started programming and debugging.  We'll start using the MSP430G2211 that comes with the LaunchPad.  If you're not using LaunchPad, it's easy to change this first program for whatever device you're using.  All it needs is an LED connected to one of the GPIO (General Purpose I/O) pins.  (Connect it with a resistor to prevent too much current draw out of the MSP.  A couple hundred ohms should be sufficient.)

In the previous tutorial, we mentioned the useful BITx definitions in the device-specific header file.  These were at one time variation specific (eg. msp430x2x01 as opposed to msp430g2001), but with the most recent version of Code Composer Studio, TI appears to be moving to device specific header files.  Whenever you write software for your MSP device, be sure to include the appropriate header file.  For this tutorial, if you're not using a LaunchPad or the G2211, change the header file to whatever device you're using.

So the start of any MSP430 program will have a line similar to this:
#include <msp430g2211.h>

For simple programs, this is often all that is needed before coding the main function, and that is certainly the case for the "Hello, world!" program of microcontrollers, blinky.  Blinky is a simple program that toggles an LED at a given period.  It's best to use timers, interrupts, and such to do this type of function, but you'll have to wait until we look at those types of peripherals and functions before we can do that.  The simplest way to get the program to work is with some type of delay loop.  The LaunchPad has a green LED connected to P1.0 and a red LED connected to P1.6.  We'll use the green LED for now.  Let's get started!

The beginning of our code looks like this:

#include <msp430g2211.h>


void main(void) {


} // main

Unfortunately, we do need one step that we can't explain completely yet before we do anything else.  The MSP430 includes a special timer called the Watchdog Timer (WDT).  Its function is to reset the CPU if it gets stuck (ie. the watchdog timer runs out).  This timer is on by default when the chip powers up.  Though we could use this timer to give us our delay, for now we don't want our program to reset on us, so we need to first turn this timer off.  (We'll look at using the WDT later.)

The WDT has a 16 bit register called WDTCTL, but only the first 8 bits have any control.  The upper byte is used as a security measure; to prevent your code from accidentally changing the WDT, you must provide a password.  The password turns out to be 0x5a (in the upper byte, so actually 0x5a00), but the header file helps you out by defining that value as the much easier to remember WDTPW.  Add this value to the 1-byte configuration value you want to assign to WDTCTL.  To turn off the WDT, we can use the header-defined value WDTHOLD:
WDTCTL = WDTPW + WDTHOLD;

You'll get into the habit of starting all of your first programs with this line, but keep in mind the WDT has a lot of useful functions.  We'll discuss those when we talk about the WDT in depth.

Ok, now that we've disabled the watchdog, we can continue writing the code.  We want to light an LED on P1.0, so we can use the last tutorial to set that up:
P1OUT = 0;
P1DIR = BIT0;

Now we want to toggle the LED and delay for some given amount of time.  I'm using a for loop, though a while or do-while loop would be just as effective.  We'll need a counter for the loop, so remember to define it at the start of the code:

#include <msp430g2211.h>


void main(void) {
    unsigned int count;
    WDTCTL = WDTPW + WDTHOLD;


    P1OUT = 0;
    P1DIR = BIT0;


    P1OUT |= BIT0;
    for (count = 0; count < 60000; count++);
    P1OUT &= ~BIT0;
    for (count = 0; count < 60000; count++);
} // main

What happens when we get to the end of the code?  In a computer, it would just exit.  In a microcontroller, however, it would just move on to the next address to read its next "instruction".  There could be just about anything in there, from random noise to leftover code from older (larger) programs.  In any case, it would just continue stepping merrily through the address space until it gets to the end and then... well, I don't know what happens.  It's not what is intended to happen in any case, so we need to prevent the processor from ever moving beyond the actual code.  We'll do this now by putting the code into an infinite loop.  That's usually a bad idea in computer code, but essential here.


#include <msp430g2211.h>

void main(void) {
    unsigned int count;
    WDTCTL = WDTPW + WDTHOLD;


    P1OUT = 0;
    P1DIR = BIT0;

    for (;;) {
        P1OUT |= BIT0;
        for (count = 0; count < 60000; count++);
        P1OUT &= ~BIT0;
        for (count = 0; count < 60000; count++);
    }
} // main


Again, you could easily do the same thing with a while(1) loop or something similar instead.

So there's blinky.  The light turns on, it waits, turns off the light, waits again, then goes back to the beginning to do it all over ad nauseum.

Note there's a cleaner way to accomplish this task:

#include <msp430g2211.h>

void main(void) {
    unsigned int count;        // loop counter
    WDTCTL = WDTPW + WDTHOLD;  // disable watchdog


    P1OUT = 0;                 // initialize LED off
    P1DIR = BIT0;              // P1.0 output

    for (;;) {
        P1OUT ^= BIT0;         // toggle LED on P1.0
        for (count = 0; count < 60000; count++);  //delay
    }
} // main

Now you only have to change one loop length to adjust the frequency of the blink.  (Though if you want to play with different duty cycles, the first method works well.)  I've also added some comments to the code. Programming teachers seem to always stress the importance of good commenting habits; it'll save your hairline in microcontrollers.  Comments don't add to the code size at all, so be sure to document everything you do well.

Next time we'll put this into our G2211 and learn how to use CCS to load programs onto the LaunchPad.


Reader Exercise:  Write a program like blinky that alternates the green and red LEDs on the LaunchPad (the red LED is on P1.6).  Then modify the program so that it alternates flashing the green LED, then the red LED, with short pulses and a delay between the individual flashes.

Disclaimer:  I don't have my LaunchPad yet, so I haven't technically tested this code.  After doing similar programs for three or four other MSP430's, I'm confident it works, but until I can get a video posted of my LaunchPad blinking its LED with this code, I reserve the right to have made mistakes.  =)


Disclaimer 2:  When I first typed up this post, I declared the count variable as just int count;.  In the MSP430 compiler, a 16-bit plain int cannot count up as high as 60,000; it reaches its highest value then wraps around to a negative value.  Using a plain int for this code will never leave the delay loop.  An unsigned int, rather, is non-negative.  Using an unsigned int allows us to count up higher.  Longer delays may require an unsigned long.  An alternative would be to use a hex notation; 0xFFFF is the highest value an int can count to.  In plain int decimal, this corresponds to 32,767.  In unsigned int decimal, it's 65,535.

12 July 2010

Tutorial 03: Flipping Bits

Now that we have access to the registers, how do we actually flip the switches (change the bits)?  We'll examine the ways to do this using the following example: we'll use a G2001 with an LED connected from P1.4 to ground.  If P1.4 is at 0 V, nothing happens, but if P1.4 is at Vcc, the LED will turn on.  Since we've connected to P1.4, we should be able to control it by fiddling with bit 4 in the P1 registers.  (Keep in mind that we're not changing the 4th bit, at least not in the way we normally think of it.  The 1st bit is bit 0, so bit 4 is technically the 5th bit, but who's counting?)

Before we look at setting bit values, we should take a look at the ways we can represent the values in 8-bit registers.  We could always use regular decimal notation, but unfortunately it has little advantage to counter the confusion caused by having to use 8-bit numbers in a non-multiple base (the decimal base is, of course, 10).  

The clearest way to represent the value is in binary notation, or base 2.  The register has 8 digits, each is a 0 or 1, corresponding to the value in each bit.  To make a binary 2 clear from a decimal 10, we can preface the number with the notation 0b (first character is a zero), such as 0b10.

Another common notation used is hexadecimal (base 16).  This notation is convenient because each 8-bit value is represented by exactly two digits, each a value from 0-9 or a-f.  The preface for hexadecimal is 0x, so the number 2 in hex is 0x02.  The number 12 would be 0x0c, since the digits a-f correspond to the numbers 10-15.  16-bit numbers are represented with 4 digits, such as 0x14da.  Many values in the MSP430 are 16-bit, so hexadecimal is very convenient here.  (I apologize for the change in notation from the previous tutorial; in the TI documentation they use the notation 14DAh for hex values, but here we're using 0x14da instead.  The 0x notation is used in the programming, and I will stick to that notation unless I'm citing from a TI document directly that uses the h notation.)

We could also use an octal notation (base 8), with the preface 0o.  I've not seen this in practice, however.

We'll start using some actual code in this post, so I want to establish a convention.  Anything written in the Courier font is a code snippet or example.  The coloring in the code matches the color scheme I usually see when I look at a .c file in a text editor, and for now doesn't make a difference.  You may have other color schemes that you see.  I'll try to use the colors that are used in CCS as best I can.

Binary notation is obviously the one that makes it clear what bits we're using and what they're set to.  Unfortunately, it also takes lots of characters to write them out.  When we write C programs for the MSP430, we can include a header file with information and shortcuts specific to the device we're using (such as #include <msp430g2001.h>).  These header files include some shortcut names for the binary values where each digit is 0 except for a specific bit; the header file allows us to use the name BIT2 to represent 0b00000100.  There is a BIT0 through BIT7 included in each header file, which makes for a nice shortcut and less typing.  In the discussion below, however, I'll try to keep it to the full 8 digit binary values to make it clear what is happening in the operations described.  Now, on to the fiddling!

For our LED example, we'll need to first make P1.4 an output so that we can control the voltage above the LED.  We do this by changing bit 4 in P1DIR to 1, for output mode.

1. Direct Assignment
If we know exactly what the binary (or hex, or even decimal) value corresponding to the configuration we need is, we can just set it directly:  P1DIR = 0b00010000; would set all of the bits in P1DIR to 0 except bit 4.  This method works pretty well for initializing the processor, but later in the program can be problematic when we might not know for certain what state bits we don't want to change are in.  Turning off the bit is easy, just set it to the value with bit 4 set at 0: P1DIR = 0b00000000, or just as easily for this particular case, P1DIR = 0.  (Using the BITx notation, we would write P1DIR = BIT4.)

2. Addition and Subtraction
If we don't know exactly the value needed for the configuration, or if we're just trying to turn on one bit, we could just add the bit's value to P1DIR (I'm using the colon character : to represent unknown digit values):  0b:::0:::: + 0b:::1:::: = 0b:::1::::, so we could turn on bit 4 by doing P1DIR += 0b00010000.  *(Confused by the +=?  See the footnote below!)  The problem with this method is if we accidentally turn it on twice: 0b:::1:::: + 0b00010000 is going to cause a carry over into the next bits, changing I/O directions where we don't want to!  This method should be used with caution.  Note that the equivalent to turn the bit off would be to subtract the value, of course.  (BITx notation: P1DIR += BIT4 or P1DIR -= BIT4.)

3. Logic Operators & and |
To avoid the problems with addition and subtraction, we can use logic operations.  Let's say we have a bit with the value x.  (x could be 0 or 1, we'll just look at this generally.)  The operations and (&) and or (|) can be used to change the value of the bit to be specifically 1 or 0.  Note that x & 0 = 0 no matter what value x is.  Similarly, x | 1 = 1 regardless of the value of x.  Also, x & 1 = x and x | 0 = x, so the value of x is unchanged. for these operations.  So what would be the result of the operation P1DIR | 0b00010000?  Bits 0-3 and 5-7 would be unchanged (remember, | 0 doesn't change the value) while bit 4 is set to 1.  (It may have been 1 before, but is definitely 1 after the operation!)  On the other hand, P1DIR &= 0b11101111 would have the effect of setting bit 4 to zero and leaving the others unchanged.  Note that 0b11101111 is the not operation (~) applied to the original 0b00010000, so we could write this as P1DIR &= ~0b00010000.  (In BITx notation: P1DIR |= BIT4 turns bit 4 on, and P1DIR &= ~BIT4 turns it off.)

Reader Exercise:  Sometimes you'll see example code that uses the notation a + b; and sometimes a | b; to do the same thing.  Convince yourself that these are equivalent in particular circumstances; when would you not want to use one or the other?

4.  Toggling with ^
Ok, I said there were three choices, and there really are only three.  This fourth option is similar to the third choice, but is an effective way if we just want to toggle the value, not set it to be specifically 0 or 1.  The exclusive or operator (^) has this effect:  x^0 = 1 if x is 1, and 0 if x is 0.  x^1 = 1 if x is 0, and 0 if x is 1.  So x^0 leaves the bit unchanged, and x^1 changes the value of x to its opposite.  P1DIR ^= 0b00010000 flips bit 4 (to 1 if it was 0, to 0 if it was 1) just like toggling a switch.  (In BITx notation: P1DIR ^= BIT4.)

Now, in our program we need to initialize the pin to be an output:
P1DIR = BIT4;  
(An equivalent way to do this is to use a logic operator rather than an assignment:  P1DIR |= BIT4;)
The value in P1OUT could be either 0 or 1, so if we care what state the LED starts in we should set that:
P1OUT = 0;
(A better practice is to initialize the output state before we change the pin to an output.)
Now we have an output pin set at 0, keeping the LED off.  To turn it on, we give the command:
P1OUT |= BIT4;
To turn it off, we give:
P1OUT &= ~BIT4;
To toggle its state (off if on, on if off):
P1OUT ^= BIT4;

As a final example, demonstrating some power in the other assignment methods, let's put another LED on P1.6.

First, let's configure the two pins as outputs with an initial state off:
P1OUT = 0;
P1DIR = BIT4 + BIT6;
(adding the two values together is easily verified to be 0b01010000).
We can turn each one on and off individually:
P1OUT |= BIT4;    // P1.4 on
P1OUT &= ~BIT4;   // P1.4 off
P1OUT |= BIT6;    // P1.6 on
P1OUT &= ~BIT6;   // P1.6 off
Or we can turn them on and off together:
P1OUT |= BIT4 + BIT6;     // both on
P1OUT &= ~(BIT4 + BIT6);  // both off
And finally, toggle them simultaneously:
P1OUT ^= BIT4 + BIT6;     // toggle both

Reader Exercise:  Write down the necessary code to use LEDs on pins 3 and 7 of port 1, with pin 3 initially off and pin 7 initially on.  Then toggle the LEDs so that 3 is on and 7 is off.


*  += is a shorthand operator in C.  If I say x += 1;, the command adds one to x and reassigns the result to x.  In other words, it's the same as saying x = x + 1;.  While algebraically that statement makes no sense, in programming it's very common.  Don't think of = as meaning the two sides are equal, read it as "x is now equal to the value currently in x plus 1".

Tutorial 02: The MSP430 Township and Registers

Most places I've found to learn how an MSP430 actually works inevitably start talking about architecture, addressing, buses, and varied other technical ideas.  Unfortunately, they all seem to require some electrical engineering experience as well.  Today we're going to attempt to explain what's needed to be able to use the MSP430 without having to understand the physical properties of bipolar junctions or anything else like that.  The technical knowledge is very helpful in fine-tuning a design or in programming in assembly, but a rudimentary knowledge is sufficient to start working in C.

One of the distinguishing characteristics of the MSP430 over other microcontrollers is its von Neumann architecture; all of the memory and information available to the processor is available in one place.  Other mcu's will treat different types of memory separately, which makes for some nice efficiencies, but complicates the design somewhat.  A simple way to view this is to picture an mcu as a town (or in the case of the Harvard architecture, a collection of towns).  For von Neumann systems like the MSP430, everybody lives together in the same town, each with their own unique address.  For Harvard systems, addresses may be duplicated, and so the particular town must also be specified.

Memory
The memory space in an MSP430 includes room for the program, room to store data, memory (RAM), and other important information that we'll get to later.  Today our primary interest is in a particular collection of addresses called registers.  These addresses essentially are the community services in our MSP430 town; things like the post office, power company, and so forth.  For the MSP430, the registers control the functions of various parts of the processor and its peripherals.  You can think of them as houses with switches and circuit breakers in them.  The setting of the switches determines if a particular event happens, what job a particular pin takes, how a particular peripheral behaves, and so on.  The registers are grouped into three sections: the special function registers (SFR), 8-bit peripherals (parts that need only 8-bits to read instructions), and 16-bit peripherals (obviously those needing a full 16-bits to read instructions).  As an example, lets look at the smallest of the MSP430's: the MSP430G2001.  Open up copies of the x2xx family guide and the G2x01 datasheet.


Please note that the above links may break on occasion, if TI updates either of these documents to a new revision.  The easiest way to find these is to go to TI's website, and use the "Search by Part Number" box.  For a G2x01 device, search for anything that falls in that category, such as the msp430g2001.  The family guide can be found on the pages for any of the x2xx family of devices.

Page 1-4 of the family guide shows a map of the x2xx family "towns".  You can see that the addresses for the SFRs are anywhere from 0h to Fh (the h denotes the value is in hexadecimal; in decimal you'd see these addresses as 0 to 15).  Next come the 8-bit peripherals; from 10h to FFh (16 to 255).  Note there is a large gap in the addresses between the RAM and the Flash memory.  The family guide shows a map for the entire x2xx family-- to see the values for our particular chip, we need to look at the datasheet.

Page 13 in the datasheet gives a table for all of the G2x01 and G2x11 device memory maps.  For the G2001, we have the peripheral registers, then 128B of RAM.  Addresses from 0201h to 10FEh are empty, and then we see a 256 byte portion called "information memory".  (This region stores calibration values and other important numbers that needed to be held when the power is gone.  Usually these won't be available to write to, but could be if necessary; but that's another post.)  Finally, we have the 512B for code, including at the very top of everything the interrupt vectors (again, that's another post).

Registers
Now that we can see what the G2001 town looks like, let's turn to how to use the switch houses we discussed.  The registers of the MSP430 are special sections of memory that configure the device and tell us when something important happens.  Page 12 of the datasheet shows the SFRs available in the G2001.  This device only lists 4 of them, in addresses 0h to 3h: Interrupt Enable 1 (IE1) and 2 (IE2), and Interrupt Flag Register 1 (IFG1) and 2 (IFG2).  Each address points to 1 byte of memory, so there are 8 bits (switches/breakers/etc.) in each register.  Page 12 shows which ones are usable for the G2001.

In this case, IE1 only has bits 0, 1, 4, and 5 available.  Likewise, IFG1 has bits 0-4.  The datasheet tells you the name of each of those bits and describes what they do.  For example, bit 0 in IE1 is named WDTIE, or the Watchdog Timer Interrupt Enable.  This bit is normally a 0, but if we configure the device to use the watchdog timer as an interval timer, then setting this bit to 1 allows the watchdog timer to raise a flag (IFG1 bit 0 to be precise) causing an interrupt (we'll get to that later too) under particular circumstances.  Essentially, this bit tells the MSP430 if the watchdog timer can signal the processor to do something special or not when it's used in a particular mode.

Now turn to page 17 of the datasheet.  This table gives the peripheral file map, or the addresses and names of the registers that affect the various peripherals in the device.  Note at the bottom it lists the SFRs we just discussed.  Any time you need to use a peripheral, this page will give you a starting point for knowing which switch houses you need to visit to be certain everything is configured properly.  We'll look at the registers for each peripheral specifically in their own posts.  Today, let's look at the registers for Port P1 and Port P2, as these are the most straight-forward.

The ports are the general input/output pins available on the device.  The pinout diagram on page 3 shows that the G2001 has all 8 pins for P1 (P1.0 through P1.7), and 2 pins for P2 (P2.6 and P2.7).  Each register for a port has bits that correspond to each of the pins; for example, P1.4 is controlled by bit 4 in each of the registers.  Let's go through each of the registers available for a port now.

PxIN
The input register for a port is a read-only value.  When a pin is selected to be an input, reading the value of the bit tells you the voltage currently on that pin.  The entire byte PxIN reads the value of all of the inputs on that port at once.  Keep in mind this is a digital system, so there are only two values that can be read; a 0 or a 1.  These values correspond to the voltages on Vss (0) and Vcc (1), which are generaly 0 V and between 1.8 and 3.6 V respectively.  There is a particular threshold built into the device such that any voltage over that value is read as a 1 and any voltage read below is read as a 0.  To prevent any damage to the chip, you should certainly never try to read any voltages outside the range between Vss and Vcc directly.

PxOUT
The output register for a port is writeable.  When a pin is selected to be an output, we can change the voltage on that pin by writing a 0 or a 1 to its corresponding bit in PxOUT.  Like the input, a 0 corresponds to the voltage on Vss, and a 1 corresponds to the voltage on Vcc.

PxDIR
The direction register determines whether a pin is an input (bit is low, or 0) or an output (bit is high, or 1).  At the beginning of your program, you should configure the port pins to their values as inputs or outputs.  That's not to say you can't change a pin's behavior in the middle of your program, of course.

PxIE, PxIES, and PxIFG
These three registers are the interrupt enable, interrupt edge select, and interrupt flag registers for the ports.  We'll look at these three registers together, as they work together.  You can use the port pins as a way to flag special circumstances to the processor and trigger an interrupt.  For now, think of an interrupt as a message to the CPU to hold on what it's currently doing and take care of the special circumstance.  Once the interrupt has been satisfied, the CPU returns to where it was before.  You enable this behavior by setting the PxIE bit for the pin being used to 1.  PxIES bits determine if the flag is triggered by the pin going from 0 to 1 (IES bit set to 0) or from 1 to 0 (IES bit set to 1).  In other words, a flag is triggered when it detects a positively sloped, rising edge or a negatively sloped, falling edge.  When the interrupt is triggered, it sets the corresponding bit in PxIFG.

PxSEL
Looking back at the pinout diagram on page 3, you can see that most of the port pins have multiple functions. The selection register determines what function a pin takes on.  The default function is listed first, so P1 defaults to general I/O pins, whereas the P2 pins default to connections to a crystal oscillator.  Changing the bits in PxSEL changes the behavior of the pins.  We'll look at the particular settings later; for now, plan on using the default values in PxSEL.

PxREN
The resistor enable register is a very useful feature for the ports.  Sometimes it is helpful to pull the voltage up to Vcc or down to Vss, such as when you attach a push button to a pin.  The resistor enable register lets you turn on that ability.  When a PxREN bit is enabled, you can select it as a pull-up or pull-down resistor by setting the corresponding bit in PxOUT, 1 for up, 0 for down.

Now that we've identified some of the switches we have to use, in the next post we'll take a look at how to actually set them in the software we write to the device.

10 July 2010

Quick Explanation

For those viewing the blog now, the recent tutorial post may seem disjointed from the previous posts. I'm in the process of transitioning the format to something more useable and accessible. For now the blog interface won't make that as clear, but in the near future it should make more sense. There will also be a Tutorial 00 that I haven't written yet.

Tutorial 01: Getting Started

Surprisingly, only a few things are needed to start working with microcontrollers.  Using an MSP430 requires a target board with a chip, a programmer, a compiler, and a power source.  Power can be as simple as a couple of AA batteries, or come directly from your computer.  There are different options for the compiler, some free and some not, and target boards can be made by hand if necessary.  Until recently, however, there were few options available for the programmer, and the better ones were fairly expensive.  TI's recent release of the LaunchPad has changed all of that.  Let's take a look at some of the options available for the needed pieces for MSP430 design.

Target Boards
The MSP430 can be programmed while inside its final circuit, if the proper electrical connections are available, or outside of its intended place by using a target board.  These boards are built in a way that the chip can be inserted temporarily, programmed, and then removed and mounted into the circuit in which it's intended to be used.  A well built target board will also make it possible to prototype, or connect to other circuits so that the chip can be used while still in its target board.  TI makes nice target boards for some of the form factors used for their MSP430's, such as the MSP-TS430PW28.  While a little costly, most of the expense comes in the fancy, spring-loaded, zero insertion force (ZIF) socket for holding the chips.  For a little more, you can even get bundles that include a full programmer.  Target boards are not too difficult to design, either; we'll look at how to do just that in a later tutorial.

A fancier type of board is the experimenter's board (also may be called a development board).  This board can be similar to a target board and use a socket to make the chip placement temporary, or it can have the MSP430 soldered in place.  Experimenter's boards come with other parts like LED's, buttons, and perhaps speakers, serial or ethernet ports, and a wide variety of devices or connections that interface with the outside world.  TI makes a few of these, such as the MSP-EXP430F5438.  Other vendors like Olimex also make this type of board, usually at a lower price tag, but sometimes with older families of the MSP430.

If you've looked at the above links and decided the price is way too high, then let's look at the new LaunchPad!  This board is a target board for 14 and 20 pin DIP components that also includes a programmer (see below) built into it.  The best part of this option is that it comes at a price tag of a whopping $4.30!  Though a new product, an online community has already started to develop around this development platform, and this option may be the easiest way to get started using the MSP430, especially for those with no experience in microcontrollers.  The tutorial articles will use the LaunchPad to teach the basic uses and concepts of MSP430's.

Programmers
The MSP430 programmer is officially referred to as a Flash Emulation Tool (FET).  These tools serve a dual purpose; they write programs to the MSP430, and they also can control the chip manually to allow for debugging of the program (see the discussion on debugging in the compiler section).

TI has two types of programming connections.  You can use a 4-wire JTAG connection, which needs four pins of the MSP430 to write the program to the chip's memory, or you can use a 2-wire (Spy-bi-wire, or SBW) connection, which obviously needs only two pins to write the program.  The 4-wire JTAG can be used to program any of the MSP430's, but the SBW only works with some of them.  While you might think the SBW interface only works on some of the smaller, lower end chips, it's not the case; in fact it seems TI is including SBW capability in all of its new designs, including some of the new and powerful MSP430x5xx family.  (A list of compatible parts can be found in slau157n.  Look for Table 2-1.)  The real trade-off for using SBW is the programming speed; SBW runs about ten times slower than JTAG.  However, MSP430 programs tend to be quite small, often less than 2 kb in size.  Unless you're really impatient, programming and debugging speed shouldn't be much of an issue, unless you're working in time critical environments.

The standard TI FET comes in a USB interface, though an older serial-port interface is also available.  This FET can program by either JTAG or SBW through a 14 pin (2x7) header pin connector.  Other companies have made their own equivalents to the TI programmer, often at a lower price.

If you are satisfied with SBW programming, there are some cheaper options available.  The TI eZ430 system has an FET interface in a USB stick form factor (picture here).  Unfortunately, the pins are very close to the computer, so your board must also be close, or you'll need to make your own cable to connect your board to the stick.  (Remember that SBW is a 2-wire interface; you might notice the connection to the USB portion has 4 pins.  The MSP430 also needs power, and most FET's can provide power directly.  Two more pins are needed for Vcc and ground.  The minimum needed for JTAG would be 6 pins.)

The LaunchPad comes with its own SBW FET built in.  The emulation portion of the board can also be used to program MSP430's externally.  A set of 6 pins are available for this, giving power, the SBW interface, and two extra pins for communicating through the USB controller on the board.

Compilers
Two professional compilers for the MSP430 also make free versions available; IAR Systems and Code Composer Studio.  The free versions limit the code size you can create (4 kb for IAR, 16 kb for CCS), but many of the MSP430 variations have less memory than this anyway.  For larger programs, you can either purchase the full compilers, or use the mspgcc open source compiler.  Information on using mspgcc will be given at some point on this blog, but for the purposes of the tutorial we'll use TI's Code Composer Studio.  Those who prefer IAR's compiler should be able to do so without much difficulty from the tutorial here.

One of the most important tools for a development environment is a debugging interface.  IAR and CCS both come with one built in to the IDE, but mspgcc users will need mspdbg to do debugging.  The debugging feature allows you to step through the code and see how it changes the settings and configurations of the MSP430 step by step, helping you to verify that the system is working the way it should and to view the contents of the registers and variables in memory.  Early on in the tutorial posts we'll look at using the debugger effectively.

Power
The LaunchPad is powered through the USB interface, and whenever an FET is used this option is available.  If you want to implement your design in a stand-alone system, however, you'll need to provide power to the circuit in some way.

The MSP430 is an ultra-low power device, and performs very well using standard consumer batteries.  The MSP430 will run with anywhere between 1.8 V and 3.6 V, though at least 2.2 V is needed to do any programming to the chip.  Keep in mind that the speed at which the chip is able to run also depends on the voltage; though it's capable of running up to 16 MHz, at 1.8 V an MSP430F2001 cannot run any faster than 6 MHz.  This image is an excerpt from the MSP430F2001 datasheet, showing how the supply voltage affects the operating frequency.


Check the datasheet for your particular MSP430 device for a similar plot to see what frequencies are available at the voltage you choose to power your design.

Aside from consumer batteries, you can also power your design from the wall if you use a transformer and voltage regulator.  Later on we'll look at the ideas to consider in using a voltage regulator.  You may be interested in looking into using a solar cell to power your design, or other creative ways to get power.

Following the Tutorial
This tutorial will use the TI LaunchPad with its SBW emulator to explain how many of the features of the MSP430 work and how to use them effectively.  Examples will be done using CCS v4 as the development environment.  If you have these two pieces (for a total price of $4.30!), you'll have enough to get started.  If you happen to have another emulation tool or target/experimenter's board, feel free to use what you already have; everything done in the tutorial is easy to modify to whatever MSP430 platform you're using.  When we move on to interfacing outside of the LaunchPad system, we'll provide some good ideas on how to do that cheaply and cleanly.  Once you have the basics down, you should be able to design any system in which you can put in and program an MSP430.

08 June 2010

Crystal Timers

The MSP430 has great internal clocks, but for time-critical applications we need something more stable. Crystals are one of the best oscillators available, and are quite stable if they are handled correctly. While it would make more sense to look at timers starting with the internal clocks, I have an immediate need to work toward USB communication, which requires the use of crystals for timing.

MSP430's can have up to two crystals to set clocks externally. XT1 is typically a low frequency (< 1 MHz), which is why it is usually referred to as LFXT1 (low frequency crystal 1). All of TI's MCU's have pins that can be used with one of these low frequency crystals.  The chips can also be configured to use a high frequency crystal if needed.  Many MCU's also have an XT2 built specifically for HF oscillators.  The exact frequency chosen depends on the application, but a commonly used frequency is 32,768 Hz, often referred to as 32 kHz even though it is not a decimal kHz. It is, however, a binary kHz, which is why it is a convenient frequency for timing applications. In exactly 1 second, the crystal will go through 2**15 oscillations. When 15 bits roll over, the timer is reset to zero, and every reset happens at exactly 1 s intervals.

Connecting a crystal to an MSP430 is a little tricky. Fortunately, TI has provided some excellent documentation to help. Essentially, the crystal should be close to the chip and isolated from other signals in the circuit. Crystals have particular capacitances that need to be matched correctly in order to be accurate. The newer MSP430's (anything but the x1xx series, really) are able to set capacitors to a few values internally. The target board I received included a 32 kHz crystal with 12.5 pF capacitance. 12.5 pF is one of the values that can be set internally, so the crystal can be put on the board without needing external capacitors. It does require, however, setting the MCU software initially to have the right capacitance internally. This is done by setting the appropriate value to the XCAPx bits in BCSCTL3 (Basic Clock System Control 3). The header files include the values XCAP_x to help set the proper bits correctly. For my 12.5 pF crystal, XCAP_3 is the correct selection. Note in the code below rather than setting BCSCTL3 = XCAP_3, |= is used to only change the XCAPx bits in the register.

In the errata for the MSP430F2132, it mentions that the MCU sometimes has issues with crystals with an equivalent series resistance (ESR) less than 40 kΩ. The crystals I purchased have 30 kΩ ESR, but seem to work fine. I don't know if my fumbling soldering technique increased the resistance sufficiently or if it just appears to work and isn't perfectly accurate, but it seems close enough for now. Future workarounds are to pick a crystal with a higher ESR or to add a resistor into the circuit as explained in TI's application note about this particular erratum.

Once the crystal is in place, it should be checked to be certain it is oscillating. This post's program won't be able to prove accuracy of the crystal, but it at least shows that the crystal oscillates and can be used. The crystal's frequency is accessed with the auxiliary clock ACLK.

/* 32kcrystalF2132: quick program to test the functionality of a watch crystal
* soldered to the target board. Flashes an LED on P1.0 at 2 Hz.
*/

#include <msp430f2132.h>

#define LED BIT0

void main(void) {
    int i;                      // internal counter
    WDTCTL = WDTPW + WDTHOLD; // turn WDT off
    P1OUT = 0x00;
    P1DIR = LED;
    BCSCTL3 |= XCAP_3; // xtal has 12.5 pF caps
    TACCR0 = 16383; // f_xtal / 2 - 1 gives 2 Hz
    TACTL = TASSEL_1 + MC_1 + TACLR; // ACLK + Up Mode + Clear timer

    for (;;) {
        while ((TACTL & BIT0) == 0) { // wait for timer to reach TACCR0
    }
    TACTL &= ~BIT0;       // reset TAIFG
    P1OUT |= LED;                 // LED on
    for (i=0; i<0x314; i++) { // short delay
    }
    P1OUT &= ~LED; // LED off
    }

} // main

The comments in the code should help explain how the program works, but it's worth taking some time to explain some of the features of Timer A.
  • Any of the timers in an MSP430 can be configured to run off of any of the clocks (MCLK, SMCLK, ACLK) by setting the TASSELx bits in TACTL. TASSEL_1 in the header file configures the timer to run off the auxiliary clock connected to the crystal.
  • The MCx bits set the mode of the timer. These are initialized to 0 when the MCU is powered, keeping the timers turned off and conserving power. MC_1 in the header file configures the timer in "Up Mode", which counts upward until it reaches a value set in TACCR0. MC_2 sets the timer in "Continuous" mode, which counts upward until the counter rolls over (from 0x0000 to 0xFFFF). This code could use continuous mode, but would then only be able to flash the LED at exactly 1 Hz. Using up mode allows you to set the flash to exact values at frequencies higher than 1 Hz and up to 32 kHz.
  • The TACLR bit clears the timer so that it starts at 0 from wherever the bit is set. This is useful because the timer continues to run even when the code is not using it or looking at it. If an exact time is needed, the timer should be cleared to be certain it counts the right number of times before reaching TACCR0.
  • The TAIFG bit (this is bit 0 in TACTL) is set when the timer rolls over, either at the top in continuous mode or at TACCR0 in up mode. The code watches this bit to know when to flash the LED. Note that the flag must be reset manually. The timer continues to run while the code is turning on the LED, waiting briefly (0x314 is just a random value I picked for a short flash), and turning off the LED, so when the loop starts again, the timer has already been running. This feature is very useful for exact timing applications, because we don't need to be concerned about accounting for the processing time between loops. As long as the program takes less time to run than intervals between TAIFG being set, the program will execute at exactly the time we require.
One final note about the value set to TACCR0--Since the timer starts at 0, and 0xFFFF coresponds to 65,535, the timer can only trigger at integer values between these two.  For this crystal, 32,768 counts would correspond to 1 s, so by setting TACCR0 to 32767 we would trigger every second.  The correct way to get the exact timing is to count to f/n - 1 (using whole fractions of the oscillation frequency, i.e. 1/2 s., 1/3 s., 1/4 s., etc as the period between flashes), so 1/3 s would be TACCR0 = (1/3) / 32,768 - 1 = 10,922. As long as this value is less than 65,536, nothing other than setting this register needs to be done.

07 June 2010

Configuring Inputs & Outputs

The MSP430 becomes especially useful in the laboratory environment when it is used to collect information and send information in conjunction with equipment and measuring instruments. To do this, the chip needs an electrical connection with the transducers, or motors, or whatever other devices are being used. These connections are made through input and output ports.

All MSP430 microcontrollers have general input/output ports. The larger chips, of course, have more ports available, but even the smallest chips have pins for input and output. One of the nice features of these microcontrollers is that the pins can be used as an input or as an output; each port is normally associated with up to 8 pins, and each can individually be an input or an output, and can even change function in the middle of a program. The MSP430F2132 has 3 ports (24 pins) available that can be configured for general I/O.

Keep in mind that,while for low power systems the MSP430 is able to drive devices directly (assuming they run well at 3.3V), many devices will need to be controlled/sampled with transistors and amplifiers, or other intermediate components, to prevent damaging the MSP430 with high voltages or currents.
Part of the memory space in the MSP430 is set aside as specific registers, which are used to store information on how the chip should behave. The behavior of each pin on a port is controlled with the register P#DIR, where the # corresponds to the particular port being used. P#DIR is a 1 byte value with each bit corresponding to one pin for the port. For example, the 3rd bit on P1DIR controls P1.3. (Remember that the bits are numbered 0-7, not 1-8, so the 3rd bit is actually the 4th least significant digit.) When a bit in P#DIR is set to 0, the pin is configured as an input. When it is set to 1, the pin works as an output. As an example, if P3DIR = 0b01100101, then P3.0, P3.2, P3.5, and P3.6 are set to be outputs, while P3.1, P3.3, P3.4, and P3.7 are set to be inputs.

Setting the value on an output is done through the P#OUT register. This register is again a 1 byte value, each bit corresponding to each pin on a port. In the previous post, the LED connected to P1.0 was turned on and off by writing a value to the 0th bit of P1OUT. P1OUT = 0x01 (which corresponds to 0b00000001) turns on the LED by applying Vcc to the pin. P1OUT = 0x00 turns off the LED by grounding the pin. If we had set P1OUT = 0x03 (0b00000011), the LED would have turned on since bit 0 is set to be high. What about P1.1, since the second bit is high? In this case, since P1DIR was configured to have P1.1 an input, no voltage is applied to the pin, but the number is rather stored in a buffer. If we reconfigure P1.1 to be an output after setting P1OUT as above, then it starts with Vcc applied to the pin when switched. It is a good idea to always set P#OUT to the desired initial values before setting P#DIR to be certain the buffer values match what we want the pin behavior to be when the device is turned on. (It wouldn't be so good to turn on the controller and immediately start moving a motor before setting the output to keep the motor from turning.)

Reading inputs is done with the P#IN register. The values in this register correspond to the current voltage level on each pin in the port. Thus, for pins configured as outputs, the bits in P#IN and P#OUT are the same. When an MSP430 of any kind restarts, it defaults to setting the port pins as inputs. (There are exceptions for some pins, such as those intended to connect to a crystal oscillator. See your chips datasheet for details.)








The following program makes use of I/O ideas to turn the LED on P1.0 on and off by using a push-button switch on P3.3. The push button used is connected with a resistor to ground so that when unpressed the output doesn't float, but is tied to ground. When pressed, the output is connected to Vcc. This connection also causes a small current to flow through this "pull-down" resistor. A push button can also reverse this behavior by having the output tied with a "pull-up" resistor to Vcc and grounding the output when pressed. The output of the button can be connected to an input on the MSP430 in either case. For the pull-down setup, the input reads 0 when unpressed and 1 when pressed. I've done this with an external circuit, connecting my push buttons to Vcc and ground with external resistors enclosed in a small box. In the video below, the red button is tied to a pull-up resistor, and the black button to a pull-down resistor. (The black is used in the program below.) The MSP430 actually is built with resistors inside the chip, and each input pin can be set with pull-up or pull-down resistors individually without external pieces. We'll examine how to do that in another post soon.

A quick comment on some parts of the program: the header files include definitions for each individual bit. BIT0 is defined as 0b00000001, BIT1 as 0b00000010, and so on. I've used two definitions to make the program even more clear. I use LED to refer to bit 0 and BTN to refer to bit 3, since those are the bits used in the circuit design for the led and the button. The program also makes a function call. The purpose of the short delay function is to deal with switch bounce. Most mechanical switches will flip on and off a few times when pressed or released. To make certain the led doesn't rapidly turn on and off with the bouncing, a delay is used. The program constantly checks the current state of the button. Each check delays for a brief moment so that any bouncing occurs while the program is in the delay loop.

The method used for switching the output values is also very useful. Any bit and 0 returns 0, while any bit and 1 returns the original bit. ~LED gives the value 0b11111110, in this case, so bits 1-7 remain unchanged while bit 0 is set to 0 when you set P1OUT to P1OUT & ~LED. Any bit or 0 returns the original bit, while any bit or 1 returns 1. Setting P1OUT to P1OUT | LED has the opposite effect of setting bit 0 to 1.


/* buttonF2132: I/O configuration test that lights an LED when a push button is
* pressed. The LED is connected to P1.0, active high. BTN is connected to
* P3.3, active high (ie. when pushed gives a positive voltage, normally gnd.)
*
* Also demonstrates bit manipulation and function calling. The delay function
* accommodates switch bouncing.
*/


#include <msp430f2132.h>


#define LED BIT0 // P1.0
#define BTN BIT3 // P3.3


void delay(void);


void main(void) {

WDTCTL = WDTPW + WDTHOLD;
P1OUT &= ~LED; // initialize output by ensuring bit 0 is 0.
P1DIR = LED; // set bit 0 to output
P3DIR = 0x00; // unnecessary, but explicitly states P3 is all inputs.

for (;;) {

if ((P3IN & BTN) == 8) {
P1OUT |= LED; // set bit 0 to 1, turn on LED
delay(); // delay to prevent switch bounce
}
else {
P1OUT &= ~LED; // set bit 0 to 0, turn off LED
delay();
}
} // infinite loop
} // main


void delay(void) {
int i;
for (i=0; i<0xFF; i++) {
}
} // delay





Reader Exercise: Write a program that controls two LEDs as in the previous exercise. Use two other pins in port 1 as inputs for two buttons, one with a pull-up resistor and one with a pull-down resistor. Have each button control one of the two LEDs. Set one LED to be off unless its button is pressed, and set the other LED to be on unless its button is pressed.