LPC812 MAX Experiment: UART

Experiment: Work with a Serial Bus - UART

So far the microcontroller has had limited possibilities to communicate with the user. Technically it would have been possible to communicate information via an LED or a buzzer but it is not a very user friendly method and it would take time to communicate longer messages.

The mbed Microcontroller can communicate with a host PC through a "USB Virtual Serial Port" over the same USB cable that is used for programming. In this lab you will experiment with that serial port.

Information

Note that the mbed microcontroller is not aware that it appears as a virtual serial port on the Host PC. That is handled by the onboard interface as shown in this image from the mbed-HDK page:

mbed-HDK

The LPC812 has three UART interfaces:

Peripheral NameRX PinTX PinArduino Shield AliasEA Serial HeaderDescription
UART1PIO0_0PIO0_4D0 / D1Pin 8 / 7Used for communication
UART2PIO0_1 / USBRXPIO0_6 / USBTXN/AN/AUSB Virtual Serial Port
UART3PIO0_10PIO0_11SDA / SCLPin 10 / 9Pins shared with I2C

In most cases you will only use UART2 and only for printing. UART1 can be use for communication with external peripherals. UART3 is rarely used as it shares pins with the I2C bus and can only be used if the I2C bus is unused.

Background

In this experiment you will learn how to work with the Universal Asynchronous Receiver/Transmitter, or UART for short. The term asynchronous refers to the fact that no explicit clock signal is transmitted. The transmitter and receiver must agree beforehand on the bit rate, i.e., how long time a transmitted bit shall take. The idle state (no transmission) is a high signal. Transmission begins with a start bit, which is low. The negative edge is detected by the receiver and 1.5 bit periods after this, bit sampling begins. Eight data bits are sampled. The least significant bit (LSB) is typically transmitted first. An optional parity bit is then transmitted (for error checking of the data bits). Often this bit is omitted if the transmission channel is assumed to be noise free or if there are error checking higher up in the protocol layers. The transmission is ended by a stop bit. Typically one bit, but 1.5 and 2 bits are sometimes also used. Most common for inter-board communication is 8N1, meaning 8 data bits, no parity and one stop bit.

/media/uploads/embeddedartists/max_exp_uart.png

On a side note, there are methods to determine the bit rate of a received signal but that is out of scope for this experiment.

An UART channel consists of two signals (besides ground):

  • TXD: transmit data, direction from transmitter to receiver. This is an output.
  • RXD: receive data, direction from transmitter to receiver. This is an input.

TXD and RXD are crossed between transmitter and receiver, i.e., TXD is connected to RXD and vice versa. For more information about asynchronous serial communication, see http://en.wikipedia.org/wiki/Universal_asynchronous_receiver/transmitter and http://en.wikipedia.org/wiki/Asynchronous_serial_communication.

Note and understand the difference between the signaling method (asynchronous serial communication) and standards of voltage signaling. The signal drawn in the image above illustrates the signal to/from the UART peripheral inside the LPC800. It is a 3.3V logic signal. This is common for communication between units on the same board, or closely mounted boards. RS232 is a common signaling standard with large voltage swings (+- 3-15V) that is used between units that are physically apart. RS422 and RS485 are other commonly used signaling standards.

Communication is normally point-to-point, meaning that a transmitter sends data to one receiver. There are signaling standards that also supports network topologies (for example RS422 and RS485). Higher protocol layers must then be involved in implementing addressing schemes between the nodes.

Hardware

In these labs you will only need the LPC812 MAX board but it must be modified to allow you to use the mbed interface's Virtual COM port.

Hardware Modification Needed

If you want to use the mbed interface Virtual COM port you need to modify your LPC812 MAX board. The instructions can be found in the mbed-NXP-LPC800-MAX-Getting-Started.

Software

Your mbed Microcontroller can appear on your computer as a serial port. On Mac and Linux, this will happen by default. For Windows, you need to install a driver:

Windows

See Windows-serial-configuration for full details about setting up Windows for serial communication with your mbed Microcontroller

On the PC side, a terminal application is needed. A terminal application connects to a COM port and displays everything received and also allows sending data from the application (via keyboard and sending a file). These are examples of a few good terminal applications:

Download and install the selected terminal application. The next step is to configure the application. Typical configuration settings are selecting COM port, setting bit rate (for example 9600 bps), set if parity is used and number of stop bits. Flow control is another setting that is common. Select None for this setting. Other settings require either additional hardware or software support.

For TeraTerm, select New Connection in the File menu. Select the COM port that appears when the FTDI UART-to-USB cable is connected to the PC. Click OK. The screenshot below illustrates the dialog window for setting up a new serial connection.

/media/uploads/embeddedartists/max_exp_com.png

To set the bit rate and other relevant settings for the serial channel, go to Setup menu and select Serial Port. A dialog, like illustrated in the screenshot below, opens. Make sure Flow control is set to none.

/media/uploads/embeddedartists/max_exp_com2.png

There are many different settings for how the terminal program shall behave (i.e., interpret received characters). Some adjustments might be needed, for example when to start displaying received characters on a new line. Under menu Setup, sub-menu Terminal setup it is possible to control these things. The screenshot below illustrates the settings possible for when a new-line shall be performed on received characters. A common setting is LF, but it also depends on which character the LPC800 application outputs.

/media/uploads/embeddedartists/max_exp_com3.png

Information

Some terminal programs (e.g. TeraTerm) list the available serial ports by name. However, if you do need to know the identity of the serial port so that you can attach a terminal or an application to it:

  • Windows - Look under the "Ports" section in "Device Manager" (''Start -> Control Panel -> System -> Hardware -> Device Manager''). The name will be ''mbed Serial Port (COMx)'', where ''x'' is the number of the COM port allocated.
  • Mac OS X - Use the command ls /dev/tty.usbmodem*
  • Linux - Use the command ls /dev/ttyACM*

1) printf

Communication over the USB Serial port simply uses the standard Serial Interface, specifying the internal (USBTX, USBRX) pins to connect to the Serial Port routed over USB.

The Serial Interface defaults to a 9600 baud standard serial connection (8 bits, 1 stop bit, no parity), so your host program should be set to the same settings. If you want to communicate at a different standard baud rate, ensure you modify the settings of both the Serial Interface and the Host PC application!

The program below uses the Serial interface available in the mbed library.

Import library

Public Member Functions

Serial (PinName tx, PinName rx, const char *name=NULL)
Create a Serial port, connected to the specified transmit and receive pins.
void baud (int baudrate)
Set the baud rate of the serial port.
void format (int bits=8, Parity parity=SerialBase::None, int stop_bits=1)
Set the transmission format used by the serial port.
int readable ()
Determine if there is a character available to read.
int writeable ()
Determine if there is space available to write a character.
void attach (void(*fptr)(void), IrqType type=RxIrq)
Attach a function to call whenever a serial interrupt is generated.
template<typename T >
void attach (T *tptr, void(T::*mptr)(void), IrqType type=RxIrq)
Attach a member function to call whenever a serial interrupt is generated.
void send_break ()
Generate a break condition on the serial line.

Use the following program to verify that everything works. You should see the "Hello World!" message in your terminal program on the Host PC.

Hello

#include "mbed.h"              
 
Serial pc(USBTX, USBRX); // tx, rx
 
int main() {
    pc.printf("Hello World!\n");
}


Troubleshoot

If you modify your program and download it on the microcontroller you might need to disconnect and connect the terminal program on the Host PC to see the printouts from your modified program.

Create a program that determines the Endianness of the microcontroller and prints the result. Assume we have a 32-bit number: 0x0AC0FFEE in hexadecimal notation. The table below illustrates how the bytes are stored differently between a big and little Endian system.

Memory addressnn+1n+2n+3
Big-endian0x0A0xC00xFF0xEE
Little-endian0xEE0xFF0xC00x0A

Now think of a solution how to test this.

Tip: Create an unsigned int-pointer and an unsigned char-pointer. Let these pointers point to the same unsigned int-variable. Write a value in the unsigned int-variable with the unsigned int-pointer. Then read out the four parts via the unsigned char-pointer.

What Endian does the LPC812 have (little or big endian)?

The printf() function works like normal. It is possible to output strings and general expressions. Verify that this works.

2) Printing events

In this experiment you shall create a program that writes in the console every time a push-button is pressed. For simplicity, use the breadboard setup in the Digital Input Experiment.

3) Reading from the Console

In this experiment we will learn how the microcontroller can read input from the terminal program on the Host PC. The Serial class supplies functions to read and write one character (getc and putc) at a time. The calls are blocking, meaning that the microcontroller will stay in the library function call until the user (on the Host PC side) has entered the characters and hit the enter key.

Test the code below.

Test

#include "mbed.h"              
 
Serial pc(USBTX, USBRX); // tx, rx
 
int main() {
    pc.printf("This is a test of getc...\n");
    
    while(1) {
        int rxChar;
        rxChar = pc.getc();
        pc.printf("%c", rxChar);
    }
}

Run the program and enter five characters and then hit enter. What happens?

The reason for this is that there is a queue on the Host PC side. Each time getc() is called on the microcontroller side, a character is removed from the queue.

As an extra experiment, create a program that reads input from the console and converts it to a number. Check that only digits are entered and that the final number is within the range of a 32-bit number.

4) Performance test

In this experiment we will investigate the performance of the printing functionality. The default speed for the Serial class is 9600 baud which is enough for printing startup messages and warnings but when printing large amounts of data it becomes a limiting factor. The program below uses the Timer class from the mbed library to measure how much time passes when printing.

Import library

Public Member Functions

void start ()
Start the timer.
void stop ()
Stop the timer.
void reset ()
Reset the timer to 0.
float read ()
Get the time passed in seconds.
int read_ms ()
Get the time passed in mili-seconds.
int read_us ()
Get the time passed in micro-seconds.

Complete the program below and then run it to see the limitation of the 9600 baud default setting.

#include "mbed.h"              
 
Serial pc(USBTX, USBRX); // tx, rx
Timer timer;
 
int main() {
    pc.printf("This is a performance test...\n");
    
    char buff[513];

    // initialize the buffer with some characters to print
    ...

    // puts expects the string to be null terminated
    buff[512] = '\0';
    
    timer.start();
    int begin = timer.read_ms();
    for (int num = 0; num < 10; num++) {        
        pc.puts(buff);
    }
    int end = timer.read_ms();
    timer.stop();

    // print information about how much time passed and the bitrate
    ...
}

Now use the baud function in the Serial class to set a higher baud rate, for example 115200, and run the program again. Don't forget to change the baud rate in the terminal program on the Host PC as well.

Solution(s)

Import programlpc812_exp_solution_uart

Solutions for the UART experiments for LPC812 MAX


Please log in to post comments.