0% found this document useful (0 votes)
46 views35 pages

01 - UARTs - v020

Uploaded by

singh vijay
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
46 views35 pages

01 - UARTs - v020

Uploaded by

singh vijay
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 35

How Do I Use a UART to Talk to Other Microcontrollers?

1. Universal Asynchronous Receiver Transmitters (UARTs) are one of the most common serial
communication interface used by microcontrollers to exchange information.

Let's take a look at what a UART is one word at a time

First, UARTs are universal. That is, the UART serial communication peripheral is a universal
standard that everyone uses. This would be analogous to a common language that everyone in
the world understands. It sure would make communication a lot easier!

Next, UART peripherals are asynchronous in nature. That is, the peripheral does not use a
common clock signal to synchronize two microcontrollers that are communicating with each
other. To share information between two microcontrollers, we only need two wires.

Finally, the UART peripheral can be used for both transmitting information to the outside world
and receiving messages from the outside world.

Page 1 of 35
2. In this lab manual, we will show you how to configure you MSP430FR6989 microcontroller
UART peripheral to communicate with almost any other microcontroller in the world.

We recognize that many students will have only one Launchpad board while taking this class.
Therefore, all of the code examples we show you will be setup to actually have your Launchpad
send a message to itself. This will look like the following diagram:

Page 2 of 35
3. Below is the main() function that we will use for our first UART program to transmit a byte of
data.

The program begins by disabling the watchdog and enabling the microcontroller pins.

Next, we have three functions (that we will detail in a few steps) whose names are (hopefully)
relatively self-explanatory.

Finally, we actually transmit the byte of data we want to send by storing it in a register called the
Universal serial Communication interface, type A, number 0, transmission (TX) BUFfer.
Thankfully, this is abbreviated as UCA0TXBUF, but it is often just called the “transmission buffer”
register when developers are talking with each other.

Relatively straightforward? We hope so. Next, we will take a look at each of the functions
individually.

main()
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
PM5CTL0 = ENABLE_PINS; // Enable pins

select_clock_signals(); // Assigns correct clock signals to UART


assign_pins_to_uart(); // P4.2 is for TXD, P4.3 is for RXD
use_9600_baud(); // UART operates at 9600 bits/second

UCA0TXBUF = 0x56; // Send the UART message 0x56 out pin P4.2

while(1);

Page 3 of 35
4. Up first is the select_clock_signals function (show below). This function tells the
microcontroller which of the different frequency clock signals it should use to coordinate all the
different parts of the microcontroller.

The first instruction in the function moves a special password code into the Clock System
ConTroL 0 register (CSCTL0). Without this password, we cannot adjust the rest of the clock
signals.

In the next instruction, loading the value 0x0046 into Clock System ConTroL 1 register (CSCTL1)
tells the microcontroller what frequency the Launchpad board was designed for.

This is followed by moving the value 0x0133 into Clock System ConTroL 2 register (CSCTL2).
This specifies the different clock signals in the microcontroller that the various peripherals have
access to.

Finally, by clearing the Clock System ConTroL 3 register (CSCTL3), we ensure that the clock
signals we have specified are all running at their expected frequency. (Optionally, developers
have the option of slowing clocks down. While slowing things down can reduce power
consumption, it can be troublesome for coordinating communication between devices.)

//*********************************************************************************
//* Select Clock Signals *
//*********************************************************************************
void select_clock_signals(void)
{
CSCTL0 = 0xA500; // "Password" to access clock calibration registers
CSCTL1 = 0x0046; // Specifies frequency of main clock
CSCTL2 = 0x0133; // Assigns additional clock signals
CSCTL3 = 0x0000; // Use clocks at intended frequency, do not slow them down
}

Page 4 of 35
5. Some readers may be happy just using the function as we have created it. Others, however, will
want to know more about why the values 0x0046 and 0x0133 are selected.

These values are actually deduced from reading the MSP430FR6989 Family User’s Guide. We
have mentioned this document in a couple BONUS sections, but it is time to officially mention
the Family User’s Guide.

The document is NOT for the timid. It is 805 pages long, and as I tell all my students, Family
User’s Guides are written by experts for experts.

The whole purpose of this class was to bridge the gap between novice MSP430 microcontroller
users and the world of highly expert technical documentation that is available. The next couple
steps will give a brief insight into where the 0x0046 and 0x0133 numbers come from, but just
briefly, and without too much explanation. If you want to skip ahead to step #10. You won’t
miss much, I promise you. : )

6. First, we have CSCTL0. The image below is directly from the Family User’s Guide.

The guide shows us that the register is 16-bits long. The most significant 8-bits (bits 15-8)
correspond to the Clock System KEY (CSKEY). We need to store the value 0xA5 in these upper
eight bits to be able to access the other registers. Therefore, we use the instruction:

CSCTL0 = 0xA500; // "Password" to access clock calibration registers

Page 5 of 35
7. Next, we have CSCTL1. The image below is directly from the Family User’s Guide. In our
function, we have the statement

CSCTL1 = 0x0046; // Specifies frequency of main clock

where 0x0046 has a binary equivalent of 0000 0000 0100 0110 B. We have superimposed
these bit values on the register’s bits.

To get our board to work, we need to make the DCORSEL bit (bit 6) HI and the 3-bits of DCOFSEL
011. The table in the bottom of the image shows us that this is the correct combination to choose
an internal microcontroller frequency (called DCO) of 8MHz.

How did we figure this out? Doing so is not easy without some help. To correctly decode all of
this, you would actually need to read the Clock System Module chapter and the UART chapter of
the Family User’s Guide. To help you out, sometimes, you can get sample code from a
microcontroller manufacturer to get you started. TI makes this available online, too, but again,
most of the sample code was written by experts for experts. However, do not become
disillusioned too quickly. We set up this function so you can “kind of” understand what is going
on, and move on to the next step.

0 0 0 0 0 0 0 0

0 1 0 0 0 1 1 0

Page 6 of 35
8. Those that really are gluttons for punishment at this stage can look at the Texas Instrument’s
MSP430FR6989 Family User Guide and/or the Texas Instruments MSP430FR6989 sample code.
Both of their links are shown below. However, as a rule, we will not be answering questions
about the Family User’s Guide or the sample code for this class. We are just pointing them out to
you. Texas Instruments has a relatively strong technical support staff that can help you on your
microcontroller journey beyond the scope of this class.

MSP430FR6989 Family User’s Guide

MSP430 Sample Code

9. Ok, let us look at one more register assignment within the select_clock_signals function.

CSCTL2 = 0x0133; // Assigns additional clock signals

On the next page is the table from the MSP430FR6989 Family User’s Guide that explains what
the bit assignments mean.

0x0133 has a binary equivalent of 0000 0001 0011 0011 B. We have superimposed these
bit values on the register’s bits.

The 3-bit SELA range specifies what internal frequency will be used for the ACLK signal we have
previously used.

The 3-bit SELS range specifies what internal frequency will be used for the SMCLK signal. This is
actually the clock that will be used in the UART peripheral.

Finally, the 3-bit SELM range specifies what internal frequency will be used for the MCLK signal.

Page 7 of 35
0 0 0 0 0 0 0 1
0 0 1 1 0 0 1 1

Page 8 of 35
10. Just remember, regardless of how well you really, really, really understand the
select_clock_signals function, you can still use it. In practice, more than 90% of the
developers I have met over the years have no understanding of how stuff like this works.
However, that is the beauty of doing something like this in a function. You get it set up once, and
then you never have to look at it again.

11. Next, we have the assign_pins_to_uart function. This function removes control of the
P4.2 and P4.3 pins from the traditional digital inputs and outputs we have been using and gives
them to the UART peripheral to control. The UART peripheral we are using must use pins P4.2
and P4.3, we cannot randomly choose any pins we want.

This assignment is done with the Port 4 SELect 1 register and the Port 4 SELect 0 register.

//*********************************************************************************
//* Used to Give UART Control of Appropriate Pins *
//*********************************************************************************
void assign_pins_to_uart(void)
{
P4SEL1 = 0x00; // 0000 0000
P4SEL0 = BIT3 | BIT2; // 0000 1100
// ^^
// ||
// |+---- 01 assigns P4.2 to UART Transmit (TXD)
// |
// +----- 01 assigns P4.3 to UART Receive (RXD)
}

12. P4.3 maps to bit 3 of P4SEL1 and bit 3 of P4SEL0. When these bits are 0 and 1 respectively,
P4.3 becomes the receive pin for the UART.

P4SEL1 = 0x00; // 0000 0000


P4SEL0 = BIT3 | BIT2; // 0000 1100
// ^
// |
// |
// |
// +----- 01 assigns P4.3 to UART Receive (RXD)

Page 9 of 35
13. P4.2 maps to bit 2 of P4SEL1 and bit 2 of P4SEL0. When these bits are 0 and 1 respectively,
P4.2 becomes the transmit pin for the UART.

P4SEL1 = 0x00; // 0000 0000


P4SEL0 = BIT3 | BIT2; // 0000 1100
// ^
// |
// +---- 01 assigns P4.2 to UART Transmit (TXD)
//
//

The final function we use in our program is use_9600_baud. These instructions are used to
specify how fast we will be transmitting data out of the P4.2 transmit pin. We have selected
9600 baud, or 9600 bits per second. While this may not seem very fast by today’s standards,
9600 baud is one of the most common frequencies for low-level microcontrollers to share
information with each other. In most applications, these microcontrollers are not sending and
receiving large files or images. Instead, they typically send short messages or codes to each other
to notify the system how things are performing, or if they are requesting any additional data or
status updates.

The first instruction puts a SoftWare hold (or ReSeT) on the UART peripheral while we specify its
expected baud rate.

The next instruction maps a specific clock source to the peripheral. As mentioned above, this
instruction actually chooses the SMCLK as the time-base for the UART.

Next, we have two instructions that actually set the baud rate at 9600. There are large look-up
tables for the values to assign to these two registers based upon the desired baud rate and the
selected peripheral clock.

Then, we tell the peripheral to clean-up the clock signal a little bit so it is easier for other UARTs
to understand it.

Finally, we release the SoftWare hold (or ReSeT) on the UART peripheral so it can be used.

//*********************************************************************************
//* Specify UART Baud Rate *
//*********************************************************************************
void use_9600_baud(void)
{
UCA0CTLW0 = UCSWRST; // Put UART into SoftWare ReSeT
UCA0CTLW0 = UCA0CTLW0 | UART_CLK_SEL; // Specifies clock source for UART
UCA0BR0 = BR0_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0BR1 = BR1_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0MCTLW = CLK_MOD; // "Cleans" clock signal
UCA0CTLW0 = UCA0CTLW0 & (~UCSWRST); // Takes UART out of SoftWare ReSeT
}

Page 10 of 35
14. For a moment, compare the select_clock_signals and the use_9600_baud functions.

The first uses numbers (like 0xA500, 0x0046, and 0x0133) that are hard-coded into their
instruction statements.

The second uses labels (like UCSWRST, BR0_FOR_9600, and CLK_MOD) that need to be
#defined elsewhere.

Generally, most developers prefer to use labels like the ones in use_9600_baud. Again, they
provide a hint of what the instruction is doing, and are easier for most people to work with than
raw numbers. For now, it is up to you to choose how to develop your own code, but most
businesses (and even some schools) have standards that will tell you what they expect from your
software.

//*********************************************************************************
//* Select Clock Signals *
//*********************************************************************************
void select_clock_signals(void)
{
CSCTL0 = 0xA500; // "Password" to access clock calibration registers
CSCTL1 = 0x0046; // Specifies frequency of main clock
CSCTL2 = 0x0133; // Assigns additional clock signals
CSCTL3 = 0x0000; // Use clocks at intended frequency, do not slow them down
}

//*********************************************************************************
//* Specify UART Baud Rate *
//*********************************************************************************
void use_9600_baud(void)
{
UCA0CTLW0 = UCSWRST; // Put UART into SoftWare ReSeT
UCA0CTLW0 = UCA0CTLW0 | UART_CLK_SEL; // Specifies clock source for UART
UCA0BR0 = BR0_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0BR1 = BR1_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0MCTLW = CLK_MOD; // "Cleans" clock signal
UCA0CTLW0 = UCA0CTLW0 & (~UCSWRST); // Takes UART out of SoftWare ReSeT
}

15. CAUTION: After using these instructions to setup the UART to operate at 9600 baud, the
MSP430FR6989 microcontroller slows down the ACLK by a factor of 4. This is important
for applications that want to use UARTs and Timers. Instead of an approximate time of
25µs, the ACLK will now increment timers once every 100µs.

Page 11 of 35
16. Below is the final, all-inclusive program for transmitting a byte of data out the MSP430FR6989
P4.2 transmit pin at 9600 baud.

#include <msp430.h>

#define ENABLE_PINS 0xFFFE // Required to use inputs and outputs


#define UART_CLK_SEL 0x0080 // Specifies accurate SMCLK clock for UART
#define BR0_FOR_9600 0x34 // Value required to use 9600 baud
#define BR1_FOR_9600 0x00 // Value required to use 9600 baud
#define CLK_MOD 0x4911 // Microcontroller will "clean-up" clock signal

void select_clock_signals(void); // Assigns microcontroller clock signals


void assign_pins_to_uart(void); // P4.2 is for TXD, P4.3 is for RXD
void use_9600_baud(void); // UART operates at 9600 bits/second

main()
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
PM5CTL0 = ENABLE_PINS; // Enable pins

select_clock_signals(); // Assigns microcontroller clock signals


assign_pins_to_uart(); // P4.2 is for TXD, P4.3 is for RXD
use_9600_baud(); // UART operates at 9600 bits/second

UCA0TXBUF = 0x56; // Send the UART message 0x56 out pin P4.2

while(1);

//*********************************************************************************
//* Select Clock Signals *
//*********************************************************************************
void select_clock_signals(void)
{
CSCTL0 = 0xA500; // "Password" to access clock calibration registers
CSCTL1 = 0x0046; // Specifies frequency of main clock
CSCTL2 = 0x0133; // Assigns additional clock signals
CSCTL3 = 0x0000; // Use clocks at intended frequency, do not slow them down
}

Page 12 of 35
//*********************************************************************************
//* Used to Give UART Control of Appropriate Pins *
//*********************************************************************************
void assign_pins_to_uart(void)
{
P4SEL1 = 0x00; // 0000 0000
P4SEL0 = BIT3 | BIT2; // 0000 1100
// ^^
// ||
// |+---- 01 assigns P4.2 to UART Transmit (TXD)
// |
// +----- 01 assigns P4.3 to UART Receive (RXD)
}

//*********************************************************************************
//* Specify UART Baud Rate *
//*********************************************************************************
void use_9600_baud(void)
{
UCA0CTLW0 = UCSWRST; // Put UART into SoftWare ReSeT
UCA0CTLW0 = UCA0CTLW0 | UART_CLK_SEL; // Specifies clock source for UART
UCA0BR0 = BR0_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0BR1 = BR1_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0MCTLW = CLK_MOD; // "Cleans" clock signal
UCA0CTLW0 = UCA0CTLW0 & (~UCSWRST); // Takes UART out of SoftWare ReSeT
}

Page 13 of 35
17. Create a new CCS project called UART_TX. Copy the program above into your new main.c file.

Save, Build, Debug, and run your project.

18. If your Launchpad is just sitting there by itself, you will not see anything happen. The UART
toggled the P4.2 transmit pin to send the data, but without an oscilloscope or similar device, you
will not actually see the transition.

19. For those of you that do not have an oscilloscope handy, we captured the voltage on the P4.2 pin
vs. time as the data was transmitted.

Page 14 of 35
20. As we mentioned before, UARTs comply with a universal standard. We can see how this standard
is implemented by looking at the data transmission more carefully.

First, the standard requires the transmission pin to remain HI when data is not being transmitted.
If we look closely, we can see that the P4.2 pin is HI before the transmission starts and remains
HI after the transmission is complete.

TX pin is HI after
TX pin is HI before data is transmitted
data is transmitted

Page 15 of 35
21. Next, the UART standard requires the peripheral to send out a “start” bit prior to sending out the
intended data. Since the line will be HI prior to data transmission, the start bit will be LO. This
transition from HI to LO indicates to all the microcontrollers “listening” to your UART that you are
starting to send a new byte of information.

The start bit, like all the rest of the data in this example, is sent out at 9600 baud, or 9600 bits per
second. This results in the start bit, and all the rest of the bits, being 104µs long.

1 / 9600 bits per second = 104µs

In the image below, we have 200µs per division. Therefore, the start bit will be approximately
1/2 of a division (or box) wide.

Start bit sends TX


pin LO for 104µs

Page 16 of 35
22. After the start bit, the UART peripheral sends the data. The universal UART standard sends the
least significant bit first. In our example, we sent the byte 0x56 (or 0101 0110 B). Therefore,
the UART transmits the bits in reverse order: 0-1-1-0-1-0-1-0. Each of these bits is kept on
the line for 104µs before the next bit is transmitted.

1 1 1 1

Bits are sent in


reverse order
0 0 0 0

Page 17 of 35
23. Finally, after the last bit of data is sent, the UART peripheral terminates the message by sending a
stop bit. The stop bit is also 104µs and is always HI.

After the stop bit, the UART ensures the TX pin remains HI until the next message is ready to be
sent out.

After the stop bit,


the TX pin remains
HI until the next
transmission

Stop bit sends TX


pin HI for 104µs

24. When you are ready, click Terminate to return to the CCS Editor.

Page 18 of 35
25. Next, we want to show you a program that is setup to both send and receive data on a UART. This
program you can run and observe on a single Launchpad, so everyone gets to play. : )

Below is the main() function for the new program. Note that the program is identical to what
we saw before when we were simply transmitting with the UART.

#include <msp430.h>

#define ENABLE_PINS 0xFFFE // Required to use inputs and outputs


#define UART_CLK_SEL 0x0080 // Specifies an accurate clock for UART
// peripheral
#define BR0_FOR_9600 0x34 // Value required to use 9600 baud
#define BR1_FOR_9600 0x00 // Value required to use 9600 baud
#define CLK_MOD 0x4911 // Microcontroller will "clean-up" clock signal
Same as last program

void select_clock_signals(void); // Assigns microcontroller clock signals


void assign_pins_to_uart(void); // P4.2 is for TXD, P4.3 is for RXD
void use_9600_baud(void); // UART operates at 9600 bits/second

main()
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
PM5CTL0 = ENABLE_PINS; // Enable pins

P1DIR = BIT0; // Make P1.0 an output for red LED


P1OUT = 0x00; // Red LED initially off

select_clock_signals(); // Assigns microcontroller clock signals


assign_pins_to_uart(); // P4.2 is for TXD, P4.3 is for RXD
use_9600_baud(); // UART operates at 9600 bits/second

UCA0TXBUF = 0x56; // Send the UART message 0x56 out pin P4.2

while(1) // Checking for incoming messages


{
if(UCA0IFG & UCRXIFG) // Received any new messages?
{
Used for UART receiving

if(UCA0RXBUF == 0x56) // If the message is 0x56


{
P1OUT = BIT0; // Then, turn on red LED
}
else // Else, the message is not 0x56
{
P1OUT = 0x00; // Turn off the red LED
}

UCA0IFG = UCA0IFG & (~UCRXIFG); // Reset the UART receive flag


}

}// end while(1)

}// end main()

Page 19 of 35
26. After we have loaded the data 0x56 into the UCA0TXBUF register, the program begins trying to
receive a UART message.

When a UART message has been successfully received, the UART peripheral will set the Universal
Communication receive (RX) Interrupt FlaG bit (UCRXIFG) HI in the Universal Communication
interface, type A, number 0 Interrupt FlaG register (UCA0IFG). Therefore, the program will
continuously poll the UXRXIFG bit in the UCA0IFG register using an if statement.

With the long register names, this relatively simple operation can seem more complex. Here it is
with just the register names:

When a UART message has been successfully received, the UART peripheral will
set the UCRXIFG bit HI in the UCA0IFG register. Therefore, the program will
continuously poll the UXRXIFG bit in the UCA0IFG register using an if statement.

Does that make it easier to understand? For some people that really helps. Part of the
problem we have with microcontrollers these days is that they have so many features that
we get really long and obtuse names like “Universal Communication interface, type A,
number 0 Interrupt FlaG register.” Sometimes this is the price of progress….

while(1) // Checking for incoming messages


{
if(UCA0IFG & UCRXIFG) // Received any new messages?
{

}// end while(1)

Page 20 of 35
27. Finally, in the code below, we reveal what the program will do when a UART message is received
(by having the UCRXIFG bit in the UCA0IFG register).

When a UART byte is successfully received, the peripheral automatically stores the received byte
in the UCA0RXBUF register. The program checks to see what the message is. If the message is
0x056, the program will turn on the red LED. If the message was anything else, the program
turns the red LED off

Finally, the program clears the UCRXIFG bit in the UCA0IFG register so the program can begin
looking for another UART message.

while(1) // Checking for incoming messages


{
if(UCA0IFG & UCRXIFG) // Received any new messages?
{

if(UCA0RXBUF == 0x56) // If the message is 0x56


{
P1OUT = BIT0; // Then, turn on red LED
}
else // Else, the message is not 0x56
{
P1OUT = 0x00; // Turn off the red LED
}

UCA0IFG = UCA0IFG & (~UCRXIFG); // Reset the UART receive flag


}

Page 21 of 35
28. On the next two pages, we have the entire program that will both send and receive a UART
message.

#include <msp430.h>

#define ENABLE_PINS 0xFFFE // Required to use inputs and outputs


#define UART_CLK_SEL 0x0080 // Specifies accurate clock for UART peripheral
#define BR0_FOR_9600 0x34 // Value required to use 9600 baud
#define BR1_FOR_9600 0x00 // Value required to use 9600 baud
#define CLK_MOD 0x4911 // Microcontroller will "clean-up" clock signal

void select_clock_signals(void); // Assigns microcontroller clock signals


void assign_pins_to_uart(void); // P4.2 is for TXD, P4.3 is for RXD
void use_9600_baud(void); // UART operates at 9600 bits/second

main()
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
PM5CTL0 = ENABLE_PINS; // Enable pins

P1DIR = BIT0; // Make P1.0 an output for red LED


P1OUT = 0x00; // Red LED initially off

select_clock_signals(); // Assigns microcontroller clock signals


assign_pins_to_uart(); // P4.2 is for TXD, P4.3 is for RXD
use_9600_baud(); // UART operates at 9600 bits/second

UCA0TXBUF = 0x56; // Send the UART message 0x56 out pin P4.2

while(1) // Checking for incoming messages


{
if(UCA0IFG & UCRXIFG) // Received any new messages?
{

if(UCA0RXBUF == 0x56) // If the message is 0x56


{
P1OUT = BIT0; // Then, turn on red LED
}
else // Else, the message is not 0x56
{
P1OUT = 0x00; // Turn off the red LED
}

UCA0IFG = UCA0IFG & (~UCRXIFG); // Reset the UART receive flag


}

}// end while(1)

}// end main()

Page 22 of 35
//*********************************************************************************
//* Select Clock Signals *
//*********************************************************************************
void select_clock_signals(void)
{
CSCTL0 = 0xA500; // "Password" to access clock calibration registers
CSCTL1 = 0x0046; // Specifies frequency of main clock
CSCTL2 = 0x0133; // Assigns additional clock signals
CSCTL3 = 0x0000; // Use clocks at intended frequency, do not slow them down
}

//*********************************************************************************
//* Used to Give UART Control of Appropriate Pins *
//*********************************************************************************
void assign_pins_to_uart(void)
{
P4SEL1 = 0x00; // 0000 0000
P4SEL0 = BIT3 | BIT2; // 0000 1100
// ^^
// ||
// |+---- 01 assigns P4.2 to UART Transmit (TXD)
// |
// +----- 01 assigns P4.3 to UART Receive (RXD)
}

//*********************************************************************************
//* Specify UART Baud Rate *
//*********************************************************************************
void use_9600_baud(void)
{
UCA0CTLW0 = UCSWRST; // Put UART into SoftWare ReSeT
UCA0CTLW0 = UCA0CTLW0 | UART_CLK_SEL; // Specifies clock sourse for UART
UCA0BR0 = BR0_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0BR1 = BR1_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0MCTLW = CLK_MOD; // "Cleans" clock signal
UCA0CTLW0 = UCA0CTLW0 & (~UCSWRST); // Takes UART out of SoftWare ReSeT
}

Page 23 of 35
29. Create a new CCS project called UART_TX_RX. Copy and paste the above program into your new
main.c file.

30. Save, Build, and Debug your program. Do not run your program yet! We need to add the
wires between the TX and RX pins first!

31. Take a single female-female wire from your kit and plug one end onto the P4.2 (TXD) pin and
the other end onto the P4.3 (RXD) pin. Congratulations! Now you can receive the UART
message!

4.3

4.2
Same wire

Page 24 of 35
32. Run your program. The red LED should come on indicating that you received the 0x56 message
that you sent! : )

While this may seem straightforward, I have known engineers that have worked for a week to get
a new microcontroller’s UART to both send and receive data. Hopefully, we have kept things
simple enough with our functions that everything went smoothly for you.

33. Click Suspend to pause your program. (We do NOT want to click Terminate to leave the CCS
Debugger yet.)

34. Unplug your wire from the P4.2 and P4.3 pins.

35. Click Soft Reset to tell the CCS Debugger you want to start the program over.

36. Click Play to run your program. The red LED will not come on.

37. While the program continues to run, plug the wire back onto the P4.2 and P4.3 pins. Now with
the connection re-established between the TXD and RXD pins, the red LED will still not light. In
this program, we only sent the message one time, therefore, if we missed the first message, we
will not get a second chance.

38. Click the Suspend button to pause your program again.

39. Click Soft Reset to prepare to restart your program.

Page 25 of 35
40. Click Play to run your program again. Now, with the connection between P4.2 and P4.3 re-
established, the UART peripheral successfully receives the 0x56 message and turns on the red
LED.

41. When you are ready, click Terminate to return to the CCS Editor.

42. Now, let us look at how you can use an interrupt service routine with your UART so your program
does not have to keep polling (checking) to see if the UCRXIFG has gone HI.

Below is the main() function that sets up the UART to transmit 0x56 at 9600 baud. The program
also enables and activates the UART interrupt. This only requires two modifications. First, we
need to first enable the UART receive interrupt. Second, we activate the enabled interrupt.

After we send the message, we immediately put the program into an infinite loop to wait for the
interrupt service routine.

main()
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
PM5CTL0 = ENABLE_PINS; // Enable pins

P1DIR = BIT0; // Make P1.0 an output for red LED


P1OUT = 0x00; // Red LED initially off

select_clock_signals(); // Assigns microcontroller clock signals


assign_pins_to_uart(); // P4.2 is for TXD, P4.3 is for RXD
use_9600_baud(); // UART operates at 9600 bits/second

UCA0IE = UCRXIE; // Enable UART RXD interrupt


_BIS_SR(GIE); // Activate enabled UART RXD interrupt

UCA0TXBUF = 0x56; // Send the UART message 0x56 out pin P4.2

while(1); // Wait here unless you get UART interrupt

Page 26 of 35
43. Next, we have the UART ISR. The microcontroller will leave the main() function and jump here
as soon as it has received a new UART message.

The ISR itself should be relatively straightforward at this point. As before, if the message
received is 0x56, the red LED will turn on. Otherwise, the red LED will turn off. Finally, we
clear the UART receive interrupt flag (UCRXIFG)

//*********************************************************************************
//* UART Interrupt Service Routine *
//*********************************************************************************
#pragma vector=USCI_A0_VECTOR
__interrupt void UART_ISR(void)
{
if(UCA0RXBUF == 0x56) // Check to see if the message is 0x56
{
P1OUT = BIT0; // If yes, turn on the red LED
}

else // If no, turn off the red LED


{
P1OUT = 0x00;
}

UCA0IFG = UCA0IFG & (~UCRXIFG); // Clear RX Interrupt FlaG

//*********************************************************************************

Page 27 of 35
44. On the next two pages, we have the entire program that will both send and receive a UART
message with the ISR.

#include <msp430.h>

#define ENABLE_PINS 0xFFFE // Required to use inputs and outputs


#define UART_CLK_SEL 0x0080 // Specifies accurate clock for UART peripheral
#define BR0_FOR_9600 0x34 // Value required to use 9600 baud
#define BR1_FOR_9600 0x00 // Value required to use 9600 baud
#define CLK_MOD 0x4911 // Microcontroller will "clean-up" clock signal

void select_clock_signals(void); // Assigns microcontroller clock signals


void assign_pins_to_uart(void); // P4.2 is for TXD, P4.3 is for RXD
void use_9600_baud(void); // UART operates at 9600 bits/second

int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
PM5CTL0 = ENABLE_PINS; // Enable pins

P1DIR = BIT0; // Make P1.0 an output for red LED


P1OUT = 0x00; // Red LED initially off

select_clock_signals(); // Assigns microcontroller clock signals


assign_pins_to_uart(); // P4.2 is for TXD, P4.3 is for RXD
use_9600_baud(); // UART operates at 9600 bits/second

UCA0IE = UCRXIE; // Enable UART RXD interrupt


_BIS_SR(GIE); // Activate enabled UART RXD interrupt

UCA0TXBUF = 0x56; // Send the UART message 0x56 out pin P4.2

while(1); // Wait here unless you get UART interrupt

//*********************************************************************************
//* UART RX Interrupt *
//*********************************************************************************
#pragma vector=USCI_A0_VECTOR
__interrupt void UART_ISR(void)
{
if(UCA0RXBUF == 0x56) // Check to see if the message is 0x56
{
P1OUT = BIT0; // Turn on the red LED
}
else
{
P1OUT = 0x00;
}
UCA0IFG = UCA0IFG & (~UCRXIFG); // Clear RX Interrupt FlaG
}
//*********************************************************************************

Page 28 of 35
//*********************************************************************************
//* Select Clock Signals *
//*********************************************************************************
void select_clock_signals(void)
{
CSCTL0 = 0xA500; // "Password" to access clock calibration registers
CSCTL1 = 0x0046; // Specifies frequency of main clock
CSCTL2 = 0x0133; // Assigns additional clock signals
CSCTL3 = 0x0000; // Use clocks at intended frequency, do not slow them down
}

//*********************************************************************************
//* Used to Give UART Control of Appropriate Pins *
//*********************************************************************************
void assign_pins_to_uart(void)
{
P4SEL1 = 0x00; // 0000 0000
P4SEL0 = BIT3 | BIT2; // 0000 1100
// ^^
// ||
// |+---- 01 assigns P4.2 to UART Transmit (TXD)
// |
// +----- 01 assigns P4.3 to UART Receive (RXD)
}

//*********************************************************************************
//* Specify UART Baud Rate *
//*********************************************************************************
void use_9600_baud(void)
{
UCA0CTLW0 = UCSWRST; // Put UART into SoftWare ReSeT
UCA0CTLW0 = UCA0CTLW0 | UART_CLK_SEL; // Specifies clock sourse for UART
UCA0BR0 = BR0_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0BR1 = BR1_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0MCTLW = CLK_MOD; // "Cleans" clock signal
UCA0CTLW0 = UCA0CTLW0 & (~UCSWRST); // Takes UART out of SoftWare ReSeT
}

Page 29 of 35
45. Create a new CCS project called UART_TX_RX_ISR. Copy and paste the above program into
your new main.c file.

Save, Build, and Debug your project.

Make sure your wire connecting your P4.2 and P4.3 pins is still in place.

Run your program to verify it works as you expected.

When you are ready, click Terminate to return to the CCS Editor.

Page 30 of 35
46. Almost done now. There is only one more thing we want to show you regarding UARTs. In
addition to setting up an ISR to notify you when you receive a UART message, you can also set up
the peripheral to generate an interrupt after it successfully transmits a message.

The program below modifies the previous programs to generate an interrupt after the 0x56
message has been fully transmitted. In a few steps, we will see that this occurs immediately after
the messages’ stop bit is finished.

#include <msp430.h>

#define ENABLE_PINS 0xFFFE // Required to use inputs and outputs


#define UART_CLK_SEL 0x0080 // Specifies accurate clock for UART peripheral
#define BR0_FOR_9600 0x34 // Value required to use 9600 baud
#define BR1_FOR_9600 0x00 // Value required to use 9600 baud
#define CLK_MOD 0x4911 // Microcontroller will "clean-up" clock signal

void select_clock_signals(void); // Assigns microcontroller clock signals


void assign_pins_to_uart(void); // P4.2 is for TXD, P4.3 is for RXD
void use_9600_baud(void); // UART operates at 9600 bits/second

int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
PM5CTL0 = ENABLE_PINS; // Enable pins

P1DIR = BIT0; // Make P1.0 an output for red LED


P1OUT = 0x00; // Red LED initially off

select_clock_signals(); // Assigns microcontroller clock signals


assign_pins_to_uart(); // P4.2 is for TXD, P4.3 is for RXD
use_9600_baud(); // UART operates at 9600 bits/second

UCA0IE = UCTXCPTIE; // Interrupt when TX stop bit complete

_BIS_SR(GIE); // Activate enabled UART TXD interrupt

UCA0TXBUF = 0x56; // Send the UART message 0x56 out pin P4.2

while(1); // Wait here unless you get UART interrupt

Page 31 of 35
//*********************************************************************************
//* UART Interrupt Service Routine *
//* This is the ISR for both the TX interrupt and the RX interrupt *
//*********************************************************************************
#pragma vector=USCI_A0_VECTOR
__interrupt void UART_ISR(void)
{
P1OUT ^= BIT0; // Turn on the red LED
UCA0IFG = UCA0IFG & (~UCTXCPTIFG); // Clear TX ComPleTe Interrupt FlaG
}

//*********************************************************************************
//* Select Clock Signals *
//*********************************************************************************
void select_clock_signals(void)
{
CSCTL0 = 0xA500; // "Password" to access clock calibration registers
CSCTL1 = 0x0046; // Specifies frequency of main clock
CSCTL2 = 0x0133; // Assigns additional clock signals
CSCTL3 = 0x0000; // Use clocks at intended frequency, do not slow them down
}

//*********************************************************************************
//* Used to Give UART Control of Appropriate Pins *
//*********************************************************************************
void assign_pins_to_uart(void)
{
P4SEL1 = 0x00; // 0000 0000
P4SEL0 = BIT3 | BIT2; // 0000 1100
// ^^
// ||
// |+---- 01 assigns P4.2 to UART Transmit (TXD)
// |
// +----- 01 assigns P4.3 to UART Receive (RXD)
}

//*********************************************************************************
//* Specify UART Baud Rate *
//*********************************************************************************
void use_9600_baud(void)
{
UCA0CTLW0 = UCSWRST; // Put UART into SoftWare ReSeT
UCA0CTLW0 = UCA0CTLW0 | UART_CLK_SEL; // Specifies clock source for UART
UCA0BR0 = BR0_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0BR1 = BR1_FOR_9600; // Specifies bit rate (baud) of 9600
UCA0MCTLW = CLK_MOD; // "Cleans" clock signal
UCA0CTLW0 = UCA0CTLW0 & (~UCSWRST); // Takes UART out of SoftWare ReSeT
}

Page 32 of 35
47. Create a new CCS project called UART_TX_ISR. Copy and paste the above program into your
new main.c file.

Save, Build, and Debug your project.

Run your program to verify the LED is turned on in the ISR after the UART message has been
completely transmitted.

48. Below is another picture taken with an oscilloscope.

The top line is for the UART’s TX line showing you the transmission of the 0x56 data.

The bottom line is for the P1.0 signal. As you can see, the red LED is turned on by the ISR after
the stop bit is complete.
Start Bit

1 1 1 1
Stop Bit

0 0 0 0

P1.0 goes HI
after stop bit

Page 33 of 35
49. When you are ready, click Terminate to return to the CCS Editor.

50. Challenge time! Can you write a program that uses the UART to transmit a rocket countdown at
9600 baud? In your main program, set up the peripheral and enable the transmit interrupt. Then
transmit 0x0A (10 decimal).

In your ISR, continue the countdown by sending 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
0x02, 0x01, and finally 0x00. When the countdown reaches 0x00, you should also light the red
LED. (Sorry, we did not include a rocket in the class lab kit….)

51. Challenge 2: Repeat challenge 1, but have the microcontroller pause for approximately 1 second
between each step in the countdown:

10 (pause), 9 (pause), 8 (pause), 7 (pause), 6 (pause), 5 (pause), 4 (pause), 3 (pause), 2 (pause),


1 (pause), 0 (red LED immediately turns on).

Page 34 of 35
All tutorials and software examples included herewith are intended solely for
educational purposes. The material is provided in an “as is” condition. Any
express or implied warranties, including, but not limited to the implied warranties
of merchantability and fitness for particular purposes are disclaimed.

The software examples are self-contained low-level programs that typically


demonstrate a single peripheral function or device feature in a highly concise
manner. Therefore, the code may rely on the device's power-on default register
values and settings such as the clock configuration and care must be taken when
combining code from several examples to avoid potential side effects.
Additionally, the tutorials and software examples should not be considered for use
in life support devices or systems or mission critical devices or systems.

In no event shall the owner or contributors to the tutorials and software be liable
for any direct, indirect, incidental, special, exemplary, or consequential damages
(including, but not limited to, procurement of substitute goods or services; loss of
use, data, or profits; or business interruption) however caused and on any theory
of liability, whether in contract, strict liability, or tort (including negligence or
otherwise) arising in any way out of the use of this software, even if advised of
the possibility of such damage.

Page 35 of 35

You might also like