Starting STM8 Microcontrollers

STM8S003K3 Discovery

Beeper (BEEP)

The beeper hardware is a sound generation unit. This is a hardware not found in other micros and is useful in scenarios where we need an audible output. An alarm is a good example. The beeper unit uses LSI to generate 1kHz, 2kHz and 4kHz square wave outputs that can be directly feed to a small piezo tweeter (not buzzer). In most STM8 micros, the beeper module’s I/O pin (PD4) is not accessible unless alternate function configuration bit is altered during code upload. However, there are few exceptional chips like the STM8S003 in which we don’t need to change any configuration bit at all. The beeper module has dependencies with the Auto-Wake-Up (AWU) module.

Hardware Connection

Schematic

Code Example

#include "STM8S.h"
 
 
void clock_setup(void);
void GPIO_setup(void);
void beeper_setup(void);
 
 
void main(void)
{
    clock_setup();
    GPIO_setup();
    beeper_setup();    
                
    while(TRUE)
    {
       GPIO_WriteLow(GPIOD, GPIO_PIN_0);
       BEEP_Cmd(ENABLE);
       delay_ms(200);
                                
       GPIO_WriteHigh(GPIOD, GPIO_PIN_0);
       BEEP_Cmd(DISABLE);
       delay_ms(200);
    };
}
 
 
void clock_setup(void)
{
    CLK_DeInit();
                
    CLK_HSECmd(DISABLE);
    CLK_LSICmd(ENABLE);
    while(CLK_GetFlagStatus(CLK_FLAG_LSIRDY) == FALSE);
    CLK_HSICmd(ENABLE);
    while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);
                
    CLK_ClockSwitchCmd(ENABLE);
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
    CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
                
    CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, 
    DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);
                
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, ENABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, DISABLE);
     CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, DISABLE);
}
 
 
void GPIO_setup(void)
{
     GPIO_DeInit(GPIOD);
     GPIO_Init(GPIOD, GPIO_PIN_0, GPIO_MODE_OUT_OD_LOW_FAST);
     GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);
}
 
 
void beeper_setup(void)
{
    BEEP_DeInit(); 
    BEEP_LSICalibrationConfig(128000);
    BEEP_Init(BEEP_FREQUENCY_2KHZ);
}

 

Explanation

As stated earlier beeper module is dependent on the AWU module and so we need to enable this module’s peripheral clock:

CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, ENABLE);

We need to set the beeper port pin as an output pin:

GPIO_Init(GPIOD, GPIO_PIN_4, GPIO_MODE_OUT_PP_HIGH_FAST);

Configuring the beeper is straight. Just like other peripherals, we deinitialize it first and set both LSI and beep frequency. Optionally we can calibrate the LSI.

void beeper_setup(void)
{
    BEEP_DeInit(); 
    BEEP_LSICalibrationConfig(128000);
    BEEP_Init(BEEP_FREQUENCY_2KHZ);
}

To activate/deactivate the beeper we need to use the following instructions:

BEEP_Cmd(ENABLE);
BEEP_Cmd(DISABLE);

 

Demo

Beeper

Video link: https://www.youtube.com/watch?v=LDPtULsJao8

Alphanumeric LCD

Alphanumeric liquid crystal displays are the most common and basic form of displays after seven segments and LED displays. They are useful for projecting multiple data quickly in ways that are otherwise difficult with other kinds of displays.

To interface a LCD with a STM8 micro, we need LCD library. The STM8 SPL does not have a library for such displays and we need to code it on our own. Interfacing a LCDs are not difficult tasks as no special hardware is required to drive LCDs other than GPIOs. However, there are some tasks needed in the software end. We need to include the library files. The process of library inclusion is discussed in the later part of this article as it needs some special attentions. The example I’m sharing here uses 6 GPIO pins from GPIOC. The read-write (R/W) pin of the LCD is connected to ground. The layout is as shown below.

Hardware Connection

Schematic

Code Example

lcd.h

#include "stm8s.h" 
 
 
#define LCD_PORT                              GPIOD
 
#define LCD_RS                                GPIO_PIN_2     
#define LCD_EN                                GPIO_PIN_3   
#define LCD_DB4                               GPIO_PIN_4       
#define LCD_DB5                               GPIO_PIN_5
#define LCD_DB6                               GPIO_PIN_6 
#define LCD_DB7                               GPIO_PIN_7 
 
#define clear_display                         0x01                
#define goto_home                             0x02
#define cursor_direction_inc                  (0x04 | 0x02)
#define cursor_direction_dec                  (0x04 | 0x00)
#define display_shift                         (0x04 | 0x01) 
#define display_no_shift                      (0x04 | 0x00)
 
#define display_on                            (0x08 | 0x04)
#define display_off                           (0x08 | 0x02) 
#define cursor_on                             (0x08 | 0x02)       
#define cursor_off                            (0x08 | 0x00)   
#define blink_on                              (0x08 | 0x01)   
#define blink_off                             (0x08 | 0x00)   
                                    
#define _8_pin_interface                      (0x20 | 0x10)   
#define _4_pin_interface                      (0x20 | 0x00)      
#define _2_row_display                        (0x20 | 0x08) 
#define _1_row_display                        (0x20 | 0x00)
#define _5x10_dots                            (0x20 | 0x40)      
#define _5x7_dots                             (0x20 | 0x00)
 
#define DAT                                   1
#define CMD                                   0
 
 
void LCD_GPIO_init(void);
void LCD_init(void);  
void LCD_send(unsigned char value, unsigned char mode);
void LCD_4bit_send(unsigned char lcd_data);              
void LCD_putstr(char *lcd_string);               
void LCD_putchar(char char_data);             
void LCD_clear_home(void);            
void LCD_goto(unsigned char  x_pos, unsigned char  y_pos);
void toggle_EN_pin(void);
void toggle_io(unsigned char lcd_data, unsigned char bit_pos, unsigned char pin_num);

 

lcd.c

#include "lcd.h"
 
 
void LCD_GPIO_init(void)
{
    GPIO_Init(LCD_PORT, LCD_RS, GPIO_MODE_OUT_PP_HIGH_FAST);
    GPIO_Init(LCD_PORT, LCD_EN, GPIO_MODE_OUT_PP_HIGH_FAST);
    GPIO_Init(LCD_PORT, LCD_DB4, GPIO_MODE_OUT_PP_HIGH_FAST);
    GPIO_Init(LCD_PORT, LCD_DB5, GPIO_MODE_OUT_PP_HIGH_FAST);
    GPIO_Init(LCD_PORT, LCD_DB6, GPIO_MODE_OUT_PP_HIGH_FAST);
    GPIO_Init(LCD_PORT, LCD_DB7, GPIO_MODE_OUT_PP_HIGH_FAST);
    delay_ms(10);    
}
 
 
void LCD_init(void)
{                                     
     LCD_GPIO_init();    
    toggle_EN_pin();
            
    GPIO_WriteLow(LCD_PORT, LCD_RS);            
    GPIO_WriteLow(LCD_PORT, LCD_DB7);   
    GPIO_WriteLow(LCD_PORT, LCD_DB6);   
    GPIO_WriteHigh(LCD_PORT, LCD_DB5);   
    GPIO_WriteHigh(LCD_PORT, LCD_DB4);                      
    toggle_EN_pin();
             
    GPIO_WriteLow(LCD_PORT, LCD_DB7);   
    GPIO_WriteLow(LCD_PORT, LCD_DB6);   
    GPIO_WriteHigh(LCD_PORT, LCD_DB5);   
    GPIO_WriteHigh(LCD_PORT, LCD_DB4);  
    toggle_EN_pin();
 
    GPIO_WriteLow(LCD_PORT, LCD_DB7);   
    GPIO_WriteLow(LCD_PORT, LCD_DB6);   
    GPIO_WriteHigh(LCD_PORT, LCD_DB5);   
    GPIO_WriteHigh(LCD_PORT, LCD_DB4);  
    toggle_EN_pin();                  
 
    GPIO_WriteLow(LCD_PORT, LCD_DB7);   
    GPIO_WriteLow(LCD_PORT, LCD_DB6);   
    GPIO_WriteHigh(LCD_PORT, LCD_DB5);        
    GPIO_WriteLow(LCD_PORT, LCD_DB4);  
    toggle_EN_pin();
 
    LCD_send((_4_pin_interface | _2_row_display | _5x7_dots), CMD);
    LCD_send((display_on | cursor_off | blink_off), CMD); 
    LCD_send(clear_display, CMD);         
    LCD_send((cursor_direction_inc | display_no_shift), CMD);
}   
 
 
void LCD_send(unsigned char value, unsigned char mode)
{                               
    switch(mode)
    {
          case DAT:
          {
              GPIO_WriteHigh(LCD_PORT, LCD_RS);   
              break;
          }
          case CMD:
          {
              GPIO_WriteLow(LCD_PORT, LCD_RS);   
              break;
           }
       }
      
       LCD_4bit_send(value);
}  
    
 
void LCD_4bit_send(unsigned char lcd_data)       
{
    toggle_io(lcd_data, 7, LCD_DB7);
    toggle_io(lcd_data, 6, LCD_DB6);
    toggle_io(lcd_data, 5, LCD_DB5);
    toggle_io(lcd_data, 4, LCD_DB4);
    toggle_EN_pin();
    toggle_io(lcd_data, 3, LCD_DB7);
    toggle_io(lcd_data, 2, LCD_DB6);
    toggle_io(lcd_data, 1, LCD_DB5);
    toggle_io(lcd_data, 0, LCD_DB4);
    toggle_EN_pin();
 
 
void LCD_putstr(char *lcd_string)
{
    do
    {
        LCD_send(*lcd_string++, DAT);
    }while(*lcd_string != '\0');
}
 
 
void LCD_putchar(char char_data)
{
    LCD_send(char_data, DAT);
}
 
 
void LCD_clear_home(void)
{
    LCD_send(clear_display, CMD);
    LCD_send(goto_home, CMD);
}
 
 
void LCD_goto(unsigned char  x_pos, unsigned char  y_pos)
{                                                   
    if(y_pos == 0)    
    {                              
        LCD_send((0x80 | x_pos), CMD);
    }
    else 
    {                                              
        LCD_send((0x80 | 0x40 | x_pos), CMD); 
    }
}
 
 
void toggle_EN_pin(void)
{
    GPIO_WriteHigh(LCD_PORT, LCD_EN);    
    delay_ms(2);
    GPIO_WriteLow(LCD_PORT,LCD_EN);   
}
 
 
void toggle_io(unsigned char lcd_data, unsigned char bit_pos, unsigned char pin_num)
{
    bool temp = FALSE;
    
    temp = (0x01 & (lcd_data >> bit_pos));  
                                         
    switch(temp)
    {
        case TRUE:
        {
            GPIO_WriteHigh(LCD_PORT, pin_num);   
            break;
        }
 
        default:
        {
            GPIO_WriteLow(LCD_PORT, pin_num);   
            break;
         }
      }
}

 

main.c

#include "STM8S.h"
#include "lcd.h"
 
 
void clock_setup(void);
void GPIO_setup(void);
 
 
void main(void)
{
    const char txt1[] = {"MICROARENA"}; 
    const char txt2[] = {"SShahryiar"}; 
    const char txt3[] = {"STM8S003K"};
    const char txt4[] = {"Discovery"};
                                                                                     
    unsigned char s = 0x00;
                                                                                    
    clock_setup();
    GPIO_setup();
                                                                                     
    LCD_init();  
    LCD_clear_home(); 
 
    LCD_goto(3, 0);                              
    LCD_putstr(txt1); 
    LCD_goto(3, 1);
    LCD_putstr(txt2);
    delay_ms(4000);
                                                                  
    LCD_clear_home();
                                                                
    for(s = 0; s < 9; s++)
    {
        LCD_goto((3 + s), 0);   
        LCD_putchar(txt3[s]);
        delay_ms(90);
    }
   for(s = 0; s < 9; s++)
   {
        LCD_goto((3 + s), 1);   
        LCD_putchar(txt4[s]);
        delay_ms(90);
    }
                                                                               
    while (TRUE);
}
 
 
void clock_setup(void)
{
    CLK_DeInit();
                                                                    
    CLK_HSECmd(DISABLE);
    CLK_LSICmd(DISABLE);
    CLK_HSICmd(ENABLE);
    while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);
                              
    CLK_ClockSwitchCmd(ENABLE);
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8);
    CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
                                         
    CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, 
    DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);
                                          
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, DISABLE);
    CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, DISABLE);
}
 
 
void GPIO_setup(void)
{
    GPIO_DeInit(LCD_PORT);
}

 

Explanation

There’s little to explain this code as it involves GPIOs only. The codes for the LCD are coded using all available info on its datasheet, just initialization and working principle. One thing to note, however, is the CPU clock speed. If the CPU clock is too fast, LCDs may not work. This is because most LCDs have a maximum working frequency of 250kHz. It is best to keep this frequency below 200 kHz.

CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8);
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);

 

Demo

LCD (1) LCD (2)

Video link: https://www.youtube.com/watch?v=TJg2Tuu4QaQ

Continue Reading ...

Related Posts

40 comments

  • Hi please someone tel me where can i find stm8s_delay.h and stm8s_delay.c
    Thanks

  • Hi , please someone tel me . Where can i find stm8s_delay.h and stm8s_delay.c
    Thanks ..

  • i am using stms003f3p6 controller..i have done as u told exactly but tim1 input capture is not displaying any value …according to your article it should display 10…i dont have any errors everything is fine…pulse on tim2 is ok ..it is coming as u said…but capture not working..please help me …thank you…

  • Hi Sir,
    i have just follwed your instruction provied in yout tutorial in main.c

    #include “stm8s.h”

    main()
    {
    while (1);
    }

    This error comes, can you please check why this error come, i am new and learn the controller programming.

    main.c:
    The command: “cxstm8 -i”d:\other datasheet\new folder\lib\stm8s_stdperiph_lib\libraries\stm8s_stdperiph_driver\inc” +debug -pxp -no -l +mods0 -pp -i”C:\Program Files (x86)\COSMIC\FSE_Compilers\CXSTM8\Hstm8″ -clDebug\ -coDebug\ main.c ” has failed, the returned value is: 1
    exit code=1.

    main.o – 2 error(s), 0 warning(s)

    Thanks,

  • Hi there, i solve the previous ADC problem. Anyway, u make some good tutorial on stm8 chips. Nice work

    • What was causing that issue? How did you solve it?

      • because i put all these

        ADC_DeInit(ADC1);
        ADC_SamplingTimeConfig(ADC1, ADC_Group_SlowChannels, ADC_SamplingTime_4Cycles);
        ADC_SchmittTriggerConfig(ADC1, ADC_Channel_7, DISABLE);
        ADC_ChannelCmd(ADC1, ADC_Channel_7, ENABLE);
        ADC_Init(ADC1, ADC_ConversionMode_Continuous, ADC_Resolution_12Bit, ADC_Prescaler_1);
        ADC_Cmd(ADC1, ENABLE);
        ADC_ExternalTrigConfig(ADC1, ADC_ExtEventSelection_None, ADC_ExtTRGSensitivity_All);

        in ‘while(1)’. It keeps looping.

        Once i put it before ‘while (1)’, it becomes normal.

  • Hi there, thanks for sharing. I learn alot thru your example, but I have encounter a problem with adc. Im currently using stm8l151k4t6. I wanna use the pin D7 as to read the voltage from my battery and monitor it (display on LCD). Can u please check where it goes wrong on my code?

    ADC_DeInit(ADC1);
    ADC_SamplingTimeConfig(ADC1, ADC_Group_SlowChannels, ADC_SamplingTime_4Cycles);
    ADC_SchmittTriggerConfig(ADC1, ADC_Channel_7, DISABLE);
    ADC_ChannelCmd(ADC1, ADC_Channel_7, ENABLE);
    ADC_Init(ADC1, ADC_ConversionMode_Continuous, ADC_Resolution_12Bit, ADC_Prescaler_1);
    ADC_Cmd(ADC1, ENABLE);
    ADC_ExternalTrigConfig(ADC1, ADC_ExtEventSelection_None, ADC_ExtTRGSensitivity_All);
    ADC_SoftwareStartConv(ADC1);
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
    battery = ADC_GetConversionValue(ADC1);

  • hi shawon great tutorials it would be nice too if you covered the coide compiler for arm it’s a good free compiler

  • hi shawon thanks for your response and support it turns out that my problem was a license issue I stupidly thought i use one license on multiple pc’s I used the license for a particular computer for mine that’s why I’ve been having compilation issues you have to use the license file stm8 sends you that is generated by your own pc else it won’t compile it’ll jus kip throwing you errors

  • It seems that you didn’t follow my instructions completely…. I found some issues:

    1. You have included header and source files of ADC2, CAN, UART2, etc which are unavailable in STM8S103…. Add only files for the peripherals available in your target MCU…. Exclude the rest….

    2. You have not included stm8s_delay header and source files…. Either disable it from stm8s_conf.h header file if you are not going to use it or add both the header and the source files for it in your project….

    Resolve these and you are good to go….

    Thanks….

  • I haven’t compiled any of the examples yet I just tried to compile the main source file just for test purpose n it just keeps showing me the same errors

  • yes the comic compiler was installed properly i even received a license file from my mail with the instructions to copy the license file to the license folder in the install directory if you fail to do this it will keep popping up for you to put in the license file. iincluded all the source files and header files as instructed i am working with the cheap stm8s103f i uncommented the stm8s103f in the stm8.h header file as you instructed and just to compile the main file it just throws me errors

  • no I just followed your instructions I just compiled it after setup i did not write any code yet just compiled the default main file

    • Need more details….

      1. The version of STVD and Cosmic
      2. Which example is giving this issue?
      3. The chip you are using if it other than STM8S003
      4. Have you tried to compile something else other than my examples?
      5. Are the paths to libraries and other folders properly added?
      6. Is the Cosmic compiler registered properly?

  • it throws this line The command: “cxstm8 -iinc +debug -pxp -no -l +mods0 -pp -i”C:\Program Files (x86)\COSMIC\FSE_Compilers\Hstm8″ -clDebug\ -coDebug\ main.c ” has failed, the returned value is: 1
    exit code=1.

  • hi I’m having compilation issues when I compile it just throws me error about comic compiler located in the program file ialso excluded unwanted header files but my problems still weren’t solved

  • hi thanks for the tutorials but i am having compiler error issues even when I remove unnecessary header files it say comic compiler error

  • I am new to STM8S003k3 Discovery board.I have done UART communication using STM standard peripheral library example. Now I want to define any other GPIO pin for UART communication. Is it possible to use d0 and d1 pin for the UART communication? If yes, then please let me know how?

  • thank you very much for this article!

  • Thank you for your time and effort.

  • Good job bro

  • Thank you for this exceptionally comprehensive article, much appreciated

    Rando!

Leave a Reply

Your email address will not be published. Required fields are marked *