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

5 comments

Leave a Reply

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