GPIO Functions on STM8S using Cosmic C and SPL – Blinking and Controlling LED with Push Button

Published  June 19, 2020   3
Aswinth Raj
Author
STM8S103F GPIO Functions using Cosmic C and SPL

For microcontrollers, an LED blinking program is equivalent to the “hello world” program. In our previous tutorial, we learned how to get started with STM8S103F3 Development Board and how to set up the IDE and compiler to program our STM8S controllers. We have also learned how to use the standard peripheral libraries, and how to compile and upload the code into our microcontroller. With all the basics covered, lets actually start writing code. In this tutorial, we will learn how to perform general GPIO functions on STM8S controllers. The board already has an onboard LED connected to pin 5 of port B, we will learn how to blink this LED and also add an external LED and control it with a push-button. If you are completely new, it is highly recommended to read the previous tutorial before you proceed any further.

Getting the Hardware Ready

Before we dive into the program, let get the hardware connections ready. As mentioned early, we will be using two LEDs here, one is an onboard LED which will blink continuous and the other is an external LED which will be toggled with a push button. The idea is to learn all the GPIO functionality in a simple set up. The on-board Led is already connected to PB5 (pin5 of PORTB), so I have just connected an LED to PA3 and a push-button to PA2, as you can see in the diagram below.

STM8S103F3 Internal Circuit

But, of all the output pins available on our controlled why did I select PA3 for output and PA2 for input? The questions are valid and I will explain that later in this article. My hardware set-up for this tutorial is shown below. As you can see, I have also connected my ST-link programmer to programming pins which will not only program our board but will also act as a power source. 

STM8S103F3 Development Board

Understanding GPIO Pinouts on STM8S103F

Now coming back to the question, why PA2 for input and why PA3 for output? To understand that, let's take a closer look at the pinout of the microcontroller which is shown below.

STM8S103F Pinout

As per the pinout diagram, we have four ports on our microcontroller, namely, PORT A, B, C, and D denoted by PA, PB, PC, and PD respectively. Each GPIO pin is also clubbed with some other special functionality. For example, the PB5 (pin 5 of PORT B) can not only work as a GPIO pin but also as an SDA pin for I2C communication and as a Timer 1 output pin. So, if we use this pin for simple GPIO purposes like connecting an LED, then we won’t be able to use I2C and the LED at the same time. Sadly, the on-board LED is connected to this pin, so we don’t have much of a choice here, and in this program, we are not going to use I2C, so it's not much of a problem.

Pinout Description and Tips for STM8S103F GPIO Selection

Truly speaking, it would not hurt to use PA1 an input pin and it would just work pin. But I deliberately brought this up to provide me an opportunity to show you some common traps that you might fall into when selecting GPIO pins on a new microcontroller. The best to avoid the traps is to read the pin details and pin description provided in the STM8S103F3P6 datasheet. For the STM8S103F3P6 microcontroller pin description details that are mentioned in the datasheet are shown below images.

STM8S103F3P6 Microcontroller Pin Description

The input pins on our microcontroller can either be floating or weak pull-up and the output pins can either be Open Drain or Push-pull. The difference between Open Drain and Push-Pull Output pins is already discussed, hence we won’t get into details of that. To put it simple, an Open Drain output pin can make the output only as low not as high, while a push-pull output pin can make the output both as high as well as high.

Apart from that from the above table, you can also notice that an output pin can either be Fast output (10 Mhz) or Slow Output (2 MHz). This determines the GPIO Speed, if you want to switch your GPIO pins between high and low very fast, then we can choose Fast output.

STM8S103F Pin Description

Some GPIO pins on our controller support True Open Drain (T) and High Sink Current (HS) as mentioned in the above image. A considerable difference between Open Drain and True Open Drain is that the output connected to open drain cannot be pulled high more than the operating voltage of microcontroller (Vdd) while a true open-drain output pin can be pulled higher than Vdd. Pins with High Sink Capability means that it can sink more current. The source and sink current of any GPIO HS pin is 20mA, while the power line can consume up to 100 mA.

Taking a closer look on the above image, you will notice that almost all GPIO pins are High Sink Current (HS) type except for PB4 and PB5 which are True Open Drain Type(T). This means that these pins cannot be made high, they will not be able to provide 3.3V even when the pin is made high. This is why the onboard led is connected to a 3.3V and grounded through PB5 instead of powering it directly from the GPIO pin. 

STM8S103F GPIO Selection

Refer to page 28 on the datasheet for the detailed pin description. As mentioned in the above image, PA1 is automatically configured as a weak pull-up and is not recommended to be used as an output pin. Anyways it can be used as an input pin along with a push-button, but I decided to use PA2 just to try enabling pull up from the program. These are just a few basic things which will be useful when we write much more complicated programs. For now, it’s okay if many things bounced off your head, we will get into it layer in other tutorials.

Programming STM8S for GPIO Input and Output using SPL

Create a workspace and new project as we discussed in our first tutorial. You can either add all the header and source files or only add the gpio, config, and stm8s files. Open the main.c file and start writing your program.

Programming STM8S

Make sure you have included the header files as shown in the image above. Open the main.c file and starting the code. The complete main.c code can be found at the bottom of this page and you will also be able to download the project file from there. The explanation of the code is as follows, you can also refer to the SPL User manual or the video linked at the bottom of this page if you are confused about the coding part.  

De-Initializing the Required Port 

We begin our program by De-Initializing the required ports. As we discussed earlier, each GPIO pin will have many other functions associated with it other than just working like a normal Input and Output. If these pins have been previously used for some other applications, then it should be De-Initialized before we use them. It is not mandatory, however, it is a good practice. The following two lines of code are used to De-Initialize Port A and Port  B. Just use syntax GPIO_DeInit (GPIOx); and mention the port name in place of x.

GPIO_DeInit(GPIOA); //prepare Port A for working
GPIO_DeInit(GPIOB); // prepare Port B for working

Input and Output GPIO Declaration

Next, we have to declare which pins will be used as input and which as output. In our case, pin PA2 will be used as input, we will also declare this pin with internal Pull-up so that we don’t have to use one externally. The syntax is GPIO_Init (GPIOx, GPIO_PIN_y, GPIO_PIN_MODE_z);. Where x is the port name, y is the pin number, and z is the GPIO Pin mode.

//Declare PA2  as input pull up pin
                GPIO_Init (GPIOA, GPIO_PIN_2, GPIO_MODE_IN_PU_IT);

Next, we have to declare the pins PA3 and PB5 as output. Again many types of output declaration are possible but we will be using “GPIO_MODE_OUT_PP_LOW_SLOW” which means that we will declare it as an output pin of push-pull type with slow speed. And by default, the value will be low. The syntax will be the same.

GPIO_Init (GPIOA, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW);
                //Declare PB5 as push pull Output pin
                GPIO_Init (GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_SLOW);

The below snapshot from the SPL user manual mentions all possible GPIO modes (z).

STM8S103F GPIO Modes

Infinite while loop

After the pin declaration, we need to create an infinite loop inside which we will keep blinking the LED forever and monitor the status of the push button to toggle the LED. The infinite loop can either create with a while(1) or with a for (;;). Here I have used while (1).

while (1)
                {
                }

Checking the status of the Input pin 

We have to check the status of the input pin, the syntax to do that is GPIO_ReadInputPin(GPIOx, GPIO_PIN_y); where x is the port name and y is the pin number. If the pin is high, we will get ‘1’ and if the pin is low, we will get a ‘0’. We have used to inside an if loop to check if the pin is high or low.

if (GPIO_ReadInputPin(GPIOA, GPIO_PIN_2)) //if button pressed                               

Making a GPIO Pin High or Low

To make a GPIO pin High or Low, we can use GPIO_WriteHigh(GPIOx,GPIO_PIN_y); and GPIO_WriteLow(GPIOx,GPIO_PIN_y); respectively. Here we have made the LED to turn on if the button is pressed and turn off if the button is not pressed.

if (GPIO_ReadInputPin(GPIOA, GPIO_PIN_2)) //if button pressed
GPIO_WriteLow(GPIOA,GPIO_PIN_3); //LED ON
else
GPIO_WriteHigh(GPIOA,GPIO_PIN_3); //LED OFF

Toggling a GPIO Pin 

To toggle a GPIO pin, we have GPIO_WriteReverse(GPIOx,GPIO_PIN_y); calling this function will change the status of the output pin. If the pin is high, it will be changed to low, and if it is low, it will be changed to high. We are using this function to blink the onboard LED on PB5.

GPIO_WriteReverse(GPIOB,GPIO_PIN_5);

Delay Function

Unlike Arduino, the cosmic compiler does not have a pre-defined delay function. So we have to create one on our own. My delay function is given below. The value doe the delay will be received in the variable ms and we will use two for loop to hold or program execution. Like _asm(“nop”) is an assembly instruction which stands for no operation. This means that the controller will be looping into the for loop without performing any operation, thus creating a delay.

void delay (int ms) //Function Definition
 {
                 int i =0 ;
                 int j=0;
                 for (i=0; i<=ms; i++)
                 {
                                 for (j=0; j<120; j++) // Nop = Fosc/4
                                 _asm("nop"); //Perform no operation //assembly code              
                 }
 }

Uploading and Testing the Program

Now that our program is ready, we can upload it and test it. Once uploaded, my hardware was working as expected. The on-board red LED was blinking for every 500 milliseconds and the external green LED turned on every time I pressed the switch.

GPIO Functions on STM8s

The complete working can be found in the video linked below. Once you have reached this point, you can try to connect the switch and LED to different pins and re-write the code to understand the concept. You can also play with the delay timing to check if you have understood the concepts clearly.

If you have any questions, please leave them in the comment section below and for other technical questions, you can use our forums. Thanks for following by, see you in the next tutorial.

Code
/* MAIN.C file
 * 
 * Copyright (c) 2002-2005 STMicroelectronics
 */

 #define Green_LED GPIOA, GPIO_PIN_3
 #include "STM8S.h"

void delay (int ms) //Function Definition 
{
int i =0 ;
int j=0;
for (i=0; i<=ms; i++)
{
for (j=0; j<120; j++) // Nop = Fosc/4
_asm("nop"); //Perform no operation //assembly code  
}
}

main()
{
GPIO_DeInit(GPIOA); //prepare Port A for working 
GPIO_DeInit(GPIOB); // prepare Port B for working 

//Declare PA2  as input pull up pin
GPIO_Init (GPIOA, GPIO_PIN_2, GPIO_MODE_IN_PU_IT); 

//Declare PA3 as Push Pull Output pin
GPIO_Init (Green_LED, GPIO_MODE_OUT_PP_LOW_SLOW);

//Declare PB5 as push pull Output pin
GPIO_Init (GPIOB, GPIO_PIN_5, GPIO_MODE_OUT_PP_LOW_SLOW);

while (1)
{
if (GPIO_ReadInputPin(GPIOA, GPIO_PIN_2)) //if button pressed
GPIO_WriteLow(Green_LED); //LED ON
else
GPIO_WriteHigh(Green_LED); //LED OFF
GPIO_WriteReverse(GPIOB,GPIO_PIN_5);
delay (100);
}
}
Video

Have any question realated to this Article?

Ask Our Community Members

Comments

Hi, Thought I would mention, I got a batch of these from hiletgo and found the ground pin on the programming pins was not really ground on the board, so the ST-Link's ground had to go to the board ground instead.  Also out of the box, either the chip or the ST-Visual programmer said the chip was protected.  found this:  https://electronics.stackexchange.com/questions/128931/how-to-flash-protected-stm8-mcu which tells how to undo this.

Do you have a list of all your projects with this board like you did with the PIC16F877A?

 

Joe

Hi,

Bought a batch of these from Hiletgo and had this issue:

1. The ground programming pin was not ground.

2. The Programmer said "Device is protected"

For issue #1, connect the ST-Link to the board's ground pin

For issue #2 I found this: 

 https://electronics.stackexchange.com/questions/128931/how-to-flash-protected-stm8-mcu

Hope this helps someone. 

Are you going to do a series on this board as you did with the PIC16F877A?  Hope you do.

Joe