MSP430 UART Configuration

I’m currently am working on a project that requires USART communication between two MSP430’s via an inexpensive RF “link”. I have no experience in developing on the MSP430 and have recognized the importance of documentation from past projects of those first beginning to use a certain platform. The experience from “newbies” is invaluable to those trying to enhance a product and for providing instruction to those who are also just learning. While the results of these notes may not be the best way or the proper way they should be on the level of a reader just starting in the MSP430F169 development.

Equipment

I will be using Code Composer Essentials v. 3.x on an MSP-TS430PM64 target board outfitted with an MSP430F169.

Assumptions/Experience

This document assumes that the reader has successfully run the fet14_uartxx_<baud_rate>.c example codes in Code Composer Essentials v3.x or higher. If you have not run one of these programs you may obtain a link to the download along with links to other documentation from my first post, “Getting Started With The TI MSP430 (Non eZ).” Alternatively you may just download the files directly with this link, MSP430F16x C Examples (IAR and CCE) (Rev. M)(ZIP 144 KB ). Though if you haven’t already downloaded multiple pages of documentation for your MSP430Fx1x series microcontroller I strongly urge you to take a peak at my first post. I’m personally using fet140_uart01_02400.c because my target RF link system will be operating at 2400 Baud.

Additionally you will probably want to install an external clock oscillator for your MSP430 or at least know how to alter the example code and my code so that the programs can work. Keep in mind the internal Digitally Controlled Oscillator (DCO) DCOCLK has RC-type characteristics. In other words, your clock my “drift” with variations in temperature and power supply. These drifts can cause issues when working with time dependent applications such as serial communications in which a dedicated clock line is not used and controlled by the master unit (your microcontroller).

If you are running fet140_uart01_02400.c as is, you must have a 32768Hz external oscillator connected to LFXT1CLK.

For more information about the MSP430F169’s various clocks you should refer to Chapter 4.1 Basic Clock Module of the MSP430x1xx Family User’s Guide. At the time of this publication it is TI Document SLAU049F.

Getting Started

Introduction

The first thing I did with fet140_uart01_02400.c was to go through line by line and look up in the documentation what was going on. While this did take some time I learned a lot. Not all the code I’m currently writing conforms to all the conditions and exceptions that I could code for but now I have a general idea of them.

For example the PxSEL registers are “Reset with PUC.” So there might should be some check in our code to determine when a Power-Up Clear (PUC) occurred.  Wait, how did I know that? If you look in Chapter 9.3 Digital I/O Registers of the MSP430x1xx Family User’s Guide then Table 9-1. Digital I/O Registers, there is a table that explicitly tells us. How did I know what PUC stands for? If you look in Preface->Read This First->Glossary of the MSP430x1xx Family User’s Guide there is a brief one page glossary that explicitly states the commonly used accronyms throughout the User’s Guide.

Now that we are starting to get a hang of the documentation let’s start looking at some code so that we can get away from simple manipulations of the example code we were provided with.

Initialization

General

Our first line of code in our program should be to include the processor specific header file. This header file will make our life easier during development. One of the most immediate and obvious benefits of using it is that we can use the “name” of registers as stated in the documentation rather than by addressing them by their memory address. If your developing on a platform other than the MSP430F169, don’t fret, just look the Includes folder in your project browser in CCE and find the header file for your processor.

#include <msp430x16x.h>

If we look through Chapter 2.1.3: Device Initial Condititions After Reset then proceed to the section on Software Initialization there is a list of steps required to initialize the MSP430.

2.1.3 Device Initial Conditions After System Reset

Software Initialization

After a system reset, user software must initialize the MSP430 for the application requirements. The following must occur:

  • Initialize the SP, typically to the top of RAM.
  • Initialize the watchdog to the requirements of the application.
  • Configure peripheral modules to the requirements of the application.

Additionally, the watchdog timer, oscillator fault, and flash memory flags can be evaluated to determine the source of the reset.

If your using Code Composer Essentials v. 3.x then there is something called the “Linker.” When I view the files of my active C/C++ Projects in CCE I see a file called Lnk_msp430f169.cmd. Several of the initialization tasks and underpinnings required to make the MSP430 operate actually occur here rather than in your code. Well maybe I should clarify… The linker options in this file are for command line linking only. For IDE linking (CCE) you should set your linker options in the Project Properties within the “menus” of CCE.

Initialize the SP

For example, the first step in the above excerpt, “Initialize the SP, typically to the top of Ram,” is telling us that we need to set the Stack Pointer. Well this is actually done by the “Linker” either by command line linker commands or by CCE project properties. In other words, we don’t need to place this in our code.

Initialize the Watchdog Timer

The watchdog timer is a good utility to use in final deployment. It is basically a method to reset your processor in the event that it gets stuck. If you read the documentation for the watchdog timer it has additional possible uses. If using in what I consider to be the standard watchdog mode it works like this. In various portions of your application you set a register. If you don’t set that register in a specific time or other requirement then the processor know that something went wrong and resets its self. So in a way it’s like a parent taking some action in the event their child doesn’t “check-in” with in the expected interval.

Most of the examples I have looked at disable the watchdog timer and for the time being I will do the same. Though this is one of those sections of code that I would like to revisit before calling my project “complete”

If you refer to Chapter 10: Watchdog Timer of the MSP430 User Manual you can learn a lot more about the Watchdog timer and its configuration. The important thing is that you must always write the watchdog password WDTPW when writing to the register. By reading the WDTCTL, Watchdog Timer Register guide in Chapter 10.3 Watchdog Timer Registers we can see that writing the following to the register will stop the watchdog timer and as an added benefit it will also conserve power.

// Turn off watchdog timer, don't forget the password...
WDTCTL = WDTPW + WDTHOLD;

Configuring USART1

We will be using USART1 because we are saving USART0 for later when we do an I2C implementation for communication with a Wii Nunchuck ;-)

Function Select Registers PxSEL

Since port pins on the MSP430 can be used for various purposes and for various peripherals we need a way to instruct them for certain task. In addition to function select registers, there are direction registers, input registers and output registers. We will get to the others a little bit later but for now we’ll just focus on the Select Registers.

If we look at the MSP430F169 Data Sheet and then find the Pin Designation map we can see that pins 34 and 35 are “multi-purpose.” That is they are both P3.x/UxXD1 ports meaning that they are either a digital I/O port or a USART port but we have to tell the microcontroller how we want those pins to behave. You could also think of the Function Select registers as a way to “multiplex” the pins. That is for part of our application we need them to function as I/O ports but then later we need them to behave as USARTs. For now though we are only going to use them as USARTs and more specifically UARTs since we are not doing “synchronous” communication. Even though I used the example of pin 34 and 35 we will only be concerned with pin 34 (TX) at this time.

The selection registers are something that I’ve had difficulty finding the documentation for or so I thought. It turns out I’ve read the documentation on them multiple times before I ever made the connection. If you read Chapter 9.2.4 Function Select Registers PxSEL of the MSP430 User’s Guide, it explicitly states the following.

  • Bit = 0: I/O Function is selected for the pin
  • Bit = 1: Peripheral module function is selected for the pin

Referring to the Pin Designation map in the data sheet then finding pin 34 we can see it’s dual function. Its first function is as an “I/O” function.  We can see the second function, separated by a  forward slash, is the “Peripheral” module function.

There are many ways to determine how each bit of the PxSEL registers are organized but just in case your wanting a table to reference take a peak at the Terminal Functions table of the MSP430F169 Data Sheet. We can find the P3.x/Peripheral section and see that P3.6/UTXD1  is the second to most significant bit (MSB) of the P3 register. We can then proceed with the following code.

// Set P3.6 (UTXD1) to "peripheral" module function
P3SEL |= 0x40;

Notice that we are ORing (bitwise operator) our pin selection with |= rather than just assigning the value of the right hand side of the = to the left hand side. We do this so that we don’t unintentionally change the function of the other pins. We are trying to keep our code modular and to prevent as many bugs as possible down the road. This makes each code section responsible for maintaining the function it needs, this becomes rather important when we start piecing together multiple pieces of code to complete a system.

Another thing that may be worth mentioning… This is the first time that we have seen hexadecimal code, at least in these tutorials. That is…

0x40 = b'0100 0000

Notice how the second to MSB is a one? That one correspond directly to P3.6 ! Now you may also see the reason more clearly for ORing the selection.

We are now done with assigning I/Os for the moment, but there is a note at the end of Chapter 9.2.4 that basically says if you want to use a pin that you selected for a peripheral module after you transition the function selection from 1->0 you will need to then again set its I/O direction, register and depending on use make additional changes as it will retain the status at the time of transferring back to an I/O pin.

USART Registers

Module Enable Register 2

Now that we have set the Function Select registers to configure the physical pins of the MSP430 for UART communication we need to actually enable the peripheral its self. This can be achieved by properly setting the Module Enable Register (ME). In our our particular case we will be configuring the Module Enable Register 2 (ME2) which is documented in Chapter 13.3 USART Registers: UART Mode Section ME2, Module Enable Register 2.

According to the documentation setting bit 5 of ME2 “enables the transmitter for USART1.” That’s perfect, exactly what we want.

We could set the according bit pattern explicitly but the include file, msp430x14x.h, already has a definition “defined” for us so we will use that to enhance the “readability” of our code.

// UTXE1 = 0x20 (Bit-5) "USART1 transmit enable"
ME2 |= UTXE1

Control Register

Once again we need to refer to Table 13-4.USART1 Control and Status Registers to see what the condition is of this register is after reset. According to this table UCTL1 = 0x01, which means that Software reset (SWRST) is “set”.

13.2.1 USART Initialization and Reset

“The USART is reset by a PUC or by setting the SWRST bit. After a PUC, the SWRST bit is automatically set, keeping the USART in a reset condition. When set, the SWRST bit resets the URXIE1, UTXIE1, URXIFG1, RXWAKE, TXWAKE, RXERR, BRK, PE, OE, and FE bits and sets the UTXIFG1 and TXEPT bits.  Clearing SWRST releases the USART for operation.”

Ok, so that sounds like a lot… But really, it is just the “reset” as the name and the other documentation says. Nothing to be afraid of. For the time being I think it is safe to leave the SWRST bit set until later in our program execution. For the most part this also sounds like it is more relevant on the receiving side of things and for the time being we are primarily concerned with the transmission end of things.

The only thing we are going to define here is the 8-bit data length.

// Set Character length to 8-bit data
U1CTL |= CHAR;

Transmit Control Register

I admittedly don’t know enough about some of these specific settings for the Transmit Control Register register. If I recall from my previous reading that a lot of these settings are useful if configuring asynchronous serial communication with an addressing scheme between say two MSP430’s.

What I do know is that we need to set the internal Baud Rate Clock BRCLK to our desired clock source. Personally I’m using LFXT1CLK as my external clock oscillator. The ACLK is the buffered LFXT1CLK clock source. By referencing ACLK we can obtain the clock of LFXT1CLK. I’m using a 32768-Hz watch oscillator on LFXT1CLK which will be rather convenient when we configure our baud rate. See Table 13-2. Commonly Used Baud Rates, Baud Rate Data, and Errors.

// Set BRCLK to ACLK
U1TCTL |= SSEL0;

Baud Rate and Modulation Control Registers

I kind of all ready hinted at the next three lines of code that we need to configure. If you didn’t do so earlier, move over to Chapter 13.2.6 UART Baud Rate Generation and refer to Table 13-2. Commonly Used Baud Rates, Baud Rate Data, and Errors. If your not using a 32768-Hz Real Time Clock (RTC) then you are going to need to back up to the beginning of Chapter 3.2.6 and do a little reading. If you are using a 32768-Hz crystal we can just set up the values straight from the table!

I’m going to use 2400 baud for my values but you pick what you need.

// Set baud rate control register 0
U1BR0 = 0x0D;

//Set baud rate control register 1
U1BR1 = 0x00;

// Set modulation control register
U1MCTL = 0x6B;


Releasing USART For Operation

Instead of sending you back to the user guide, I need you to think back or literally look at the block quote from the “Control Register” section above. The block quote has been reproduced here for convienience.

13.2.1 USART Initialization and Reset

“The USART is reset by a PUC or by setting the SWRST bit. After a PUC, the SWRST bit is automatically set, keeping the USART in a reset condition. When set, the SWRST bit resets the URXIE1, UTXIE1, URXIFG1, RXWAKE, TXWAKE, RXERR, BRK, PE, OE, and FE bits and sets the UTXIFG1 and TXEPT bits.  Clearing SWRST releases the USART for operation.”

The last line of that statement is essential to your program running. To be honest I forgot all about it and my program wouldn’t even do the simplest of tasks over UART. With that set, clear SWRST.

// Clear SWRST, releasing USART for operation
UCTL1 &= ~SWRST

If anything in that last code block looks foreign, try taking a read over “bitwise operators” again.

Transmitting Data

Congradulations, you have now mastered the code and procedure necessary to initialize the transmit portion of UART1! Now let’s tell the world that we are here!

Transmit Buffer

You may or may not recall reading at least something about the transmit buffer. Don’t worry, I couldn’t recall enough right off the top of my head to write the needed code to take care of it myself. I tried reading the information in Chapter 13.3 USART Registers: UART MODE – UxTXBUF, USART Transmit Buffer Register but it really wasn’t all that helpful. I mean other than telling you the name of the registers and that writing to U1TXBUF clears UTXIFG1. The information I was really after was found in Chapter 13.2.5 USART Transmit Enable, particularly the second the last paragraph.

When the transmitter is enabled (UTXE1 = 1), data should not be written to U1TXBUF unless it is ready for new data indicated by UTXIFG1 = 1. Violation can result in an erroneous transmission if data in U1TXBUF is modified as it is being moved into the TX shift register.

So basically we need a mechanism that will stall our routine until these conditions are met. My initial thought was just to add an “if” statement but almost all the example/sample programs I looked at have used a negated “while” loop. I would imagine there is some reason for this. Maybe something about counters, return to sub-routines, and other translations in assembly. So here is the way I ended up doing it in the end…

// Do repeatedly, "infinite loop"
for(;;) {
  // Don't go past this point until conditions are satisfied. "This is a hold-up" :P
  while(!(UTXE1 & UTXIFG1));

  // Ok, now we can put stuff in the transmit buffer. 'x' is just a single, 8-bit character.
  U1TXBUF = 'x'
}

Notice the ‘;;’ in the “for” loop? It is basically an empty condition with a terminating character and invokes a infinite loop. There are many other methods I’ve seen in examples for the same thing but I had never seen this method before.

Conclusion!

You have actually gone through every step of initializing the USART1 module. Of course there are additional options but now you have the tools to investigate those a big more. Post a comment with how you implemented this in your project. Obviously you can put together the above code in a number of ways. Regardless of how you do it, debug and go! I know I said I wasn’t just going to post the code? Well I would feel a little bad for not giving you a birds eye view of things. I broke up some portions of my code. Don’t worry I didn’t give a mention of that above, so you didn’t miss anything.

My Tested and Confirmed Working Code

/*************************************************************************
 *                                                                       *
 * Copyright 2009 Matthew B. Pare                                        *
 *    Matthew B. Pare, mpare@paretech.com                                *
 *                                                                       *
 *  This program is free software: you can redistribute it and/or modify *
 *  it under the terms of the GNU General Public License as published by *
 *  the Free Software Foundation, either version 3 of the License, or    *
 *  (at your option) any later version.                                  *
 *                                                                       *
 *  This program is distributed in the hope that it will be useful,      *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of       *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
 *  GNU General Public License for more details.                         *
 *                                                                       *
 *  You should have received a copy of the GNU General Public License    *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.*
 *                                                                       *
 *************************************************************************/

 #include <msp430x16x.h>

 static char transchar = 'x';

 void main(void);
 void sys_init(void);
 void uart_init(void);

 void main() {
 sys_init();                       // Initialize processor
 uart_init();

 for(;;) {                         // Do continuously
 while(!(UTXE1 & UTXIFG1));      // Wait for transmit to be enabled and
 // wait for the transmit buffer to clear

 U1TXBUF = transchar;            // Load the transmit buffer
 }
 }

void sys_init() {
 WDTCTL = WDTPW + WDTHOLD;         // Stop watchdog
}

void uart_init(void) {
 P3SEL   |= 0x40;                  // Function select P3.6 (UART1 transmission)

 ME2     |= UTXE1;                 // USART1 transmit enable

 U1CTL   |= CHAR;                  // Parity disabled, one stop bit, 8-bit
                                   // data, listen disabled, synchronous,
                                   // idle-line

 U1TCTL  |= SSEL0;                 // Set baudrate clock to ACLK

 // Baud rate control registers and modulation values from Table 13.2
 U1BR0    = 0x0D;                  // Set baud rate control register 0
 U1BR1    = 0x00;                  // Set baud rate control register 1
 U1MCTL   = 0x6B;                  // Set modulation control register

 UCTL1 &= ~SWRST;                  // Clear SWRST
}
Advertisements


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s