Using the UART on the STM8S
We have previously seen how to configure the STM8S using the STD Peripheral Library using both the high level API and the slightly lower level register access. In this post we will use the definitions in the iostm8s103f3.h and we will also have a look at the registers which control the UART ending with a program which uses the UART to send data to a terminal emulator on a desktop computer (in my case a PC). We must remember that while this article looks at low speed communications with a PC, the UARTs on the STM8S have a variety of uses covering other protocols other than those discussed in this article.
The definition of the problem is simple, allow the STM8S to send debug information to a terminal emulator running at 115200,n,8,1 (for all of those who remember DOS MODE commands for serial communication).
It should be noted that UART1 is not available on the STM8S Discovery board and so UART2 is used instead.
The Registers
In order to set up the UART we will need to perform the following tasks:
- set the parity and number of data bits
- set the parity
- set the number of stop bits
- setup the baud rate
- set the clock polarity etc.
It is important to remember that transmission and reception must both be disabled before we start to change these registers.
UART_CR1 – Data Bits and Parity
The number of data bits is selected using the M bit of CR1. This can be set to either 8 or 9 bits. We will be using 8 data bits and so will need to set UART_CR1_M to 0 (setting to 1 would enable 9 data bits).
To set the parity we would set PCEN and PS. In our case we are disabling parity so only need to worry about PCEN (Parity Control Enable). Setting this bit to 0 will disable the parity calculation.
UART_CR3 – Number of Stop Bits and Clock Settings
The number of stop bits can be set to 1, 1.5 or 2. This is controlled by setting UART_CR3_STOP to one of the following values:
Value | Description |
00 | 1 Stop bit |
01 | Reserved |
10 | 2 Stop bits |
11 | 1.5 Stop bits |
Next, we need to consider the clock settings.
UART_CR3_CPOL determines the idle state of the clock, 0 sets the clock low when idle, 1 sets it high when idle.
UART_CR3_CPHA determines if the data should be stable on the rising or falling edge of the signal. Setting this to 0 means the data is set on the rising edge of the clock signal. Setting this to 1 means the data is ready on the falling edge of the clock signal.
UART_CR3_LBCL determines if the clock pulse for the last data bit is set to the clock pin. A 0 means the last clock pulse is not generated while 1 means that the pulse is generated.
UART_BRR1 & UART_BRR2 – Baud Rate Registers
The baud rate of the UART is controlled by dividing fmaster by the baud rate divisor. The result gives the clock speed of the serial port. In our case we have a 16 MHz clock speed for the microcontroller and we want the serial port to run at 115200 baud. So some simple rearranging of the formula and the UART divider is given by:
UART Divider | = fmaster / baud rate |
= 16,000,000 / 115,200 | |
= 138 | |
= 0x008a |
Now we need to rearrange the number 0x008a a little in order to get the right bits into BRR1 and BRR2 (Baud Rate Register 1 & 2). This was written as a 32 bit number to illustrate how this is put into the registers. To do this we split the number (represented by d3d2d1d0) into three parts:
- the first digit (d3) – 0
- the next two digits (d2d1) – 08
- the last digit (d0) – a
And set up the registers as follows:
BRR1 | = d2d1 |
= 0x08 | |
BRR2 | = d3d0 |
= 0x0a |
When setting these registers it is important to remember to set BRR2 before setting BRR2.
UART_CR2 & UART_CR3 – Enabling the UART
The first action we would need to take is to disable the UART and the last thing we should do is enable it. This is controlled by three bits in two different registers, namely registers UART_CR3 and UART_CR2. All three bits use 0 for disable and 1 for enable. The bits we been to set are:
UART_CR2_TEN | Enable/disable transmission |
UART_CR2_REN | Enable/disable reception |
UART_CR3_CKEN | Enable/disable the clock |
In our case we do not need to enable the output of the system clock or reception. The software below will enable these anyway in order to provide a generic serial initialisation method which can be using a variety of circumstances.
Software
Moving on to our software, we will need a standard STM8 project for the microcontroller you are using. I am using the STM8S103F3P3 and the default project I set up in a previous article.
Setting Up the UART
This code makes a fundamental assumption, namely that you have configured the chip and your circuit to run at 16 MHz. I did this by setting the chip to use the internal oscillator as its clock source and using a prescalar of 1 (see the previous article on setting up the system clock for more information). The code for this is in the InitialiseSystemClock method.
The next step is to configure the UART. This is performed in the InitialiseUART method.
//
// Setup the UART to run at 115200 baud, no parity, one stop bit, 8 data bits.
//
// Important: This relies upon the system clock being set to run at 16 MHz.
//
void InitialiseUART()
{
//
// Clear the Idle Line Detected bit in the status register by a read
// to the UART1_SR register followed by a Read to the UART1_DR register.
//
unsigned char tmp = UART1_SR;
tmp = UART1_DR;
//
// Reset the UART registers to the reset values.
//
UART1_CR1 = 0;
UART1_CR2 = 0;
UART1_CR4 = 0;
UART1_CR3 = 0;
UART1_CR5 = 0;
UART1_GTR = 0;
UART1_PSCR = 0;
//
// Now setup the port to 115200,n,8,1.
//
UART1_CR1_M = 0; // 8 Data bits.
UART1_CR1_PCEN = 0; // Disable parity.
UART1_CR3_STOP = 0; // 1 stop bit.
UART1_BRR2 = 0x0a; // Set the baud rate registers to 115200 baud
UART1_BRR1 = 0x08; // based upon a 16 MHz system clock.
//
// Disable the transmitter and receiver.
//
UART1_CR2_TEN = 0; // Disable transmit.
UART1_CR2_REN = 0; // Disable receive.
//
// Set the clock polarity, lock phase and last bit clock pulse.
//
UART1_CR3_CPOL = 1;
UART1_CR3_CPHA = 1;
UART1_CR3_LBCL = 1;
//
// Turn on the UART transmit, receive and the UART clock.
//
UART1_CR2_TEN = 1;
UART1_CR2_REN = 1;
UART1_CR3_CKEN = 1;
}
We will need to provide a method of sending a simple string to the serial port. The algorithm is simple:
- Set a pointer to the start of the string
- If the character pointed to be the pointer is not a null (i.e. 0) character then
- Transfer the character pointed to be the pointer into the UART data register
- Wait until the data register has been sent (Transmission Empty is true)
- Move the pointer on one byte
//
// Send a message to the debug port (UART1).
//
void UARTPrintf(char *message)
{
char *ch = message;
while (*ch)
{
UART1_DR = (unsigned char) *ch; // Put the next character into the data transmission register.
while (UART1_SR_TXE == 0); // Wait for transmission to complete.
ch++; // Grab the next character.
}
}
And finally we need a main program to control the application.
//
// Main program loop.
//
void main()
{
__disable_interrupts();
InitialiseSystemClock()
InitialiseUART()
__enable_interrupts();
while (1)
{
UARTPrintF("Hello from my microcontroller....\n\r");
for (long counter = 0; counter < 250000; counter++);
}
}
The full application code can be downloaded from here. Simply unzip the files and open the project with IAR. The application can be downloaded to the chip by pressing Ctrl-D. Once downloaded to the microcontroller press F5 to run the application.
This application has been tested on my reference platform, the Variable Labs Protomodule and the STM8S Discovery board.
To check the application is working, connect the Tx line of the STM8S (in my case pin 2) to the Rx line on a PC which can accept 3.3V TTL logic signals. This is important, the port must accept 3.3V TTL and NOT standard RS232 signals. To do this I use a 3.3V FTDI cable and connect this to the STM8S and one of the USB ports on my PC. This gives me a COM port which I can connect to devices running at 3.3V. Now open up a terminal emulator (I used PuTTY) and connect to the com port using the correct protocol. You should see the following output:
Conclusion
Adding these methods to you project should allow you to generate debug output from an application running on the STM8S or communicate with devices which are controlled using a serial communication protocol.
Source Code Compatibility
System | Compatible? |
STM8S103F3 (Breadboard) | |
Variable Lab Protomodule | |
STM8S Discovery |
Tags: Electronics, Software Development, STM8, The Way of the Register
Monday, August 27th, 2012 at 10:04 am • Electronics, Software Development, STM8 • RSS 2.0 feed Both comments and pings are currently closed.