Serial UART Communication on STM8 using Cosmic C and STVD - Print / Read Characters and Strings

Published  July 2, 2020   4
User Avatar Aswinth Raj
Author
STM8S Serial Communication using STVD and Cosmic C

Programming a new microcontroller often takes a longer time due to the new register handling methods and not knowing what bit does exactly what. The same goes for debugging as well without saying. This is why programmers quite often use breakpoints in their code and step through it using a debugger. But using a debugger might need additional hardware (most times expensive) and also additional time. Being an Arduino fan boy, one thing we all can agree is using serial print statements for debugging and understanding our code makes life a lot easier. What is we can replicate the same on STM8s with cosmic C compiler and SPL libraries? Well, it is very much possible, and that is exactly what we are going to do in this third tutorial of our tutorial series. You also check the getting started with STM8S (tutorial 1) and STM8S GPIO control (tutorial 2) if you are completely new here. Also, we have also explored the possibility of Programming STM8S with Arduino for quick starters. All that being said let’s get into the tutorial.

Serial Communication on STM8S103F3P6

From the datasheet of STM8S103F3P6, we can see that our 8-bit controller supports UART communication in many different modes. The controller also has a clock output pin for synchronous UART communication and can also support SmarCard, IrDA, and LIN. But we will be exploring none of that in this tutorial just to stay away from complexity. We will learn how to do simple UART read and write.

The tutorial also provides a header file called stm8s103 serial.h using which you can perform simple UART commands like Serial begin, Serial read, serial print, etc. Basically, you will be able to print char, int, and string to the serial monitor and also read char from the serial monitor. At the end of this tutorial, you will be able to control an LED from the serial monitor and get feedback about the status of the LED. The header file mentioned above depends on the SPL libraries, so make sure you have followed the getting started tutorial.

Serial Communication Pins on STM8S103F3P6

Let’s start from the hardware side. Taking a quick look at the pinouts on the STM8S103F3P6 microcontroller given below, we can see that pins 1, 2, and 3 will be used for UART communication.

STM8S103F3P6 Serial Communication Pins

Among the three, pin 1 is the UART clock pin which will be used only during synchronous UART communication, so we won’t be needing it here. Pin 2 is the UART Transmitter pin and Pin 3 is the UART Receiver pin. Do note that these pins can also double up as an analog pin or normal GPIO pin.

Circuit Diagram for STM8S Serial Communication

The circuit diagram is very simple here, we need to connect our ST-LINK 2 for programming and a USB to TTL converter for reading serial data. Do note that our STM8S controller works in 3.3V logic level, so make sure your USB to TTL converter also supports 3.3V logic. The complete circuit diagram is shown below.

STM8S Serial Communication Circuit Diagram

You have to connect your ST-link in one USB port and USB to TTL converter in another USB port of your laptop, so that you can both program and monitor data at the same time. The UART connection is simple, just connect the ground and Rx/Tx pin of your STM8S microcontroller to the Tx/Rx pins of the USB to TTL converter. Here I have powered the controller with the Vcc pin of ST-Link and have left the vss pin of TTL converter open, you can also do this the other way around. There are many types of USB to TTL converter in the market just make sure it can operate on 3.3V Logic signals and simple look for Tx, Rx, and GND pins and make the connection shown above. My hardware set-up is shown below.

STM8S Serial Communication

To make a serial communication way, we have provided the STM8S_Serial.h header file. Using this header file, you can perform simple Arduino like functions for serial communication.

STM8S Serial Library

You can find all the required files for this project on our STM8S103F3_SPL Github page. If you only need this particular header file, you can download it from the below link.

Download STM8S_Serial.h

Setting up STVD for Serial Communication

To work with serial communication, we will be using many using the STM8S_Serial.h header file function that we discussed earlier. But the library has other dependencies, many the SPL UART and Clock related header and C files. So from this point, it is better to include all the header and C files to our project to avoid a compilation error. My STVD work environment looks like this.

STVD for Serial Communication

Make sure you have included all the SPL source files and Include file like we did in our first tutorial. And also ensure you have added the stm8s103_serial.h header file. There is no C file for this header.

Programming STM8S for Serial Communication

Once the STVD project setup is ready, we can begin writing our code in the main.c file. The complete code for this tutorial can be found at the bottom of this page. The explanation is as follows.

The first step is to include the required header files, here I have added the main header file (stm8s) and the stm8s_103_serial header file that we just downloaded.

//Required Headers
 #include "STM8S.h"
 #include "stm8s103_serial.h" //https://github.com/CircuitDigest/STM8S103F3_SPL/blob/master/stm8s103%20Libraries/stm8s103_Serial.h

Next, we are using the design macros to specify the input and output pins. Here will only be controlling the on-board LED which is connected to pin5 of port B, so we give it a name as test_LED.

#define test_LED GPIOB, GPIO_PIN_5 //test LED is connected to PB5

Moving on inside the main function, we will define the pin as an output. If you are not familiar with basic GPIO functions fall back to the STM8S GPIO tutorial.

//Pin defanitions
//Declare PB5 as push pull Output pin
GPIO_Init (test_LED, GPIO_MODE_OUT_PP_LOW_SLOW);

Then we initialize our serial communication ports at 9600 baud rates. For those who are new, 9600 is the rate of speed at which the data bits will be transferred during communication. If you set 9600 here, you also have to set the same on the monitoring software. Then we also print a string “Enter command” and move on to the next line.

Serial_begin(9600); //Initialize Serial communication at 9600 baud rate
Serial_print_string("Enter command"); //print a string
Serial_newline(); //move to next line

Moving on to the infinite while loop, we use the Serial_available function to check if there is any incoming serial data. If yes, we read and save it in a variable called ch and also print the same using Serial_print. Then if the received value is 0, we will turn off the LED and if it is 1, we will turn on the LED

   if(Serial_available())
     {
Serial_print_string("You have pressed: ");
ch = Serial_read_char();
Serial_print_char(ch);
Serial_newline();                                                                                              
if (ch == '0')
GPIO_WriteHigh(test_LED); //LED OFF                                                                                               
if (ch == '1')
GPIO_WriteLow(test_LED); //LED ON                                                                                               
}

With this, the programming for this tutorial is complete, just upload the code given at the bottom of this page and you should be able to control the LED from the serial monitor.

Controlling LED from Serial monitor

Once you have uploaded the code, you can open any serial monitor at 9600 baud rates. I have used the Arduino serial monitor itself for the ease of using it. Press the reset button and you should see the message “Enter a command”. Then if you enter 1 and press enter, the on-board led should turn on, similarly for 0, it should turn off.

Serial Monitor Commands

Serial Communication on STM8S103F3P6

The complete working can be found in the video linked at the bottom of this page. If you have any questions, please leave them in the comment section. You can also use our forums to post other technical questions.

STM8S Serial Library Deeper Look

For those curious minds who want to know what actually happens inside the STM8S103F3_Serial header file read on….

This header file works well for beginner level programming, but if you are using a different version of the STM8S controller or looking for some advanced options, you might want to tweak this header a bit or directly work with SPL libraries. I wrote this header file just as a ripe off from the UART1 header file, the explanation of my header file is as follows.

Reading a character from Serial Monitor 

This function helps to read a single character that has been sent to the microcontroller from the serial monitor.

char Serial_read_char(void)
 {
                 while (UART1_GetFlagStatus(UART1_FLAG_RXE) == RESET);
                 UART1_ClearFlag(UART1_FLAG_RXNE);
                 return (UART1_ReceiveData8());
 }

We wait till the RXE flag is SET to complete reception and then clear the flag to acknowledge the reception. Finally, we send the received 8-bit data as the result of this function.

Printing a character to Serial Monitor 

This function transmits a single character from a microcontroller to the serial monitor.

void Serial_print_char (char value)
 {
                 UART1_SendData8(value);
                 while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET); //wait for sending
 }

The function simply writes the 8-bit value and waits till the transmission is complete by checking the UART1_FLAG_TXE to SET

Initializing Serial Communication

This function initializes serial communication at the required baud rate.

void Serial_begin(uint32_t baud_rate)
 {
                 GPIO_Init(GPIOD, GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_FAST);
                 GPIO_Init(GPIOD, GPIO_PIN_6, GPIO_MODE_IN_PU_NO_IT);
                 UART1_DeInit(); //Deinitialize UART peripherals                                                              
                               UART1_Init(baud_rate,
                UART1_WORDLENGTH_8D,
                UART1_STOPBITS_1,
                UART1_PARITY_NO,
                UART1_SYNCMODE_CLOCK_DISABLE,
                UART1_MODE_TXRX_ENABLE); //(BaudRate, Wordlegth, StopBits, Parity, SyncMode, Mode)               
                                UART1_Cmd(ENABLE);
 }

Apart from the baud rate, there are other parameters that have to be set for serial communication, like the number of data bits, number of stop bits, parity, etc. The most common one (similar to Arduino) is the 8-bit data with one stop bit and no parity and hence that will be the default setting. You can change it if required.

Printing an Integer to Serial Monitor 

Most time, if we are using a serial monitor for debugging or monitoring, we might want to print a variable of type int to the serial monitor. This function does exactly that

void Serial_print_int (int number) //Funtion to print int value to serial monitor
 {
                 char count = 0;
                 char digit[5] = "";         
                 while (number != 0) //split the int to char array
                 {
                                 digit[count] = number%10;
                                 count++;
                                 number = number/10;
                 }
                 while (count !=0) //print char array in correct direction
                 {
                                UART1_SendData8(digit[count-1] + 0x30);
                                while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET); //wait for sending
                                count--;
                 }
 }

It takes in an integer value and converts it to character array in the first while loop, then in the second while loop, we will sending each of the characters similar to our print char function.

Printing a new line

This is a simple function to print a new line. The hexvalue to do that is “0x0a”, we are just sending it across using the 8-bit transmit command.

void Serial_newline(void)
 {
                 UART1_SendData8(0x0a);
                while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET); //wait for sending
 }

Printing a string to serial monitor

Another useful function is to actually print strings on the serial monitor.

void Serial_print_string (char string[])
 {.
                 char i=0;
                 while (string[i] != 0x00)
                 {
                                UART1_SendData8(string[i]);
                                while (UART1_GetFlagStatus(UART1_FLAG_TXE) == RESET);
                                i++;
                }
 }

Again, this function also converts the string to char array and sends each character. As we know all strings end will null. So we just have to keep traversing and transmitting the characters till we reach the null 0x00.

Checking if serial data is available to read

This function checks if there is any serial data in the buffer ready to read.

bool Serial_available()
 {
                 if(UART1_GetFlagStatus(UART1_FLAG_RXNE) == TRUE)
                 return TRUE;
                 else
                 return FALSE;
 }

It checks for the flag UART1_FLAG_RXNE, if it is true, it returns true and if it is not, it returns false.

Code
 /*Tutorial Number:3
 * Website: https://circuitdigest.com/search/node/STM8S
 * Code by: Aswinth Raj
 */
 /*Control on-board LED through USART
 * PD5 - UART1-Tx
 * PD6 - UART1-Rx
 */
 //Required Headers
 #include "STM8S.h"
 #include "stm8s103_serial.h" //https://github.com/CircuitDigest/STM8S103F3_SPL/blob/master/stm8s103%20Libraries/stm8s103_Serial.h
 #define test_LED GPIOB, GPIO_PIN_5
 //Main Code 
 void main(void)
 {

//Variable declarations

char ch;

//Pin defanitions
//Declare PB5 as push pull Output pin

GPIO_Init (test_LED, GPIO_MODE_OUT_PP_LOW_SLOW);
Serial_begin(9600);
Serial_print_string("Enter command");
Serial_newline();
while (1) //Loop function 
{
   if(Serial_available())
   {
Serial_print_string("You have pressed: ");
ch = Serial_read_char();
Serial_print_char(ch);
Serial_newline();

if (ch == '0')
GPIO_WriteHigh(test_LED); //LED OFF

if (ch == '1')
GPIO_WriteLow(test_LED); //LED ON 
}
}
}
Video

Have any question realated to this Article?

Ask Our Community Members

Comments