Continuing the STM8 Expedition

STM8S105 Discovery

True Data EEPROM

There are several cases where we need to save some very important data in a microcontroller and have them retrieved later. For instance, we would like keep preferences like contrast, colour, etc. of our TV set fixed once set and would like the TV to remember them whenever we turn it on. Usually a micro has three types of memory – RAM, EEPROM and flash memory. EEPROM and flash memory are non-volatile memories, meaning they retain the data stored in them even when powered off. RAM, on the other hand, is a volatile memory. All these memories have different roles. RAM is mainly intended for fast processing and temporary storage. EEPROMs are intended for storing a small set of important data that are often needed to be recalled. Finally, there is flash memory to hold the application code. Thus, it is logical to store settings and calibration data in either EEPROM or flash memory.

STM8s have true data EEPROMs and flash memories. Both share same registers and controls. Shown below is the memory map of STM8S003K3 microcontroller:

 Memory Map

You can find this info in your device’s datasheet. Check the address ranges. This is important because if you try to write or read wrong locations, your application code will crash as it is an illegal operation.

 

Hardware Connection

 Hardware Schematic

 

 

Code Example

#include "STM8S.h"
#include "lcd.h"


#define Button_Port              GPIOB
#define Button_Pin               GPIO_PIN_7


unsigned char bl_state;
unsigned char data_value;


void clock_setup(void);
void GPIO_setup(void);
void Flash_setup(void);
void lcd_print(unsigned char x_pos, unsigned char y_pos, unsigned char value);


void main()
{     
       unsigned char value = 0x00;

       clock_setup();
       GPIO_setup();
       Flash_setup();

       LCD_init(); 
       LCD_clear_home();

       LCD_goto(0, 0);
       LCD_putstr("STM8 EEPROM Test");

       value = FLASH_ReadByte(0x4000);
       delay_ms(20);

       LCD_goto(0, 1);
       LCD_putstr("WR: ---");
       LCD_goto(9, 1);
       LCD_putstr("RD:");
       lcd_print(13, 1, value);
       delay_ms(2000);

       while(TRUE)
       {
              if(GPIO_ReadInputPin(Button_Port, Button_Pin) == FALSE)
              {
                     while(GPIO_ReadInputPin(Button_Port, Button_Pin) == FALSE);
                     FLASH_Unlock(FLASH_MEMTYPE_DATA);
                     FLASH_EraseByte(0x4000);
                     delay_ms(20);
                     FLASH_ProgramByte(0x4000, value);
                     delay_ms(20);
                     FLASH_Lock(FLASH_MEMTYPE_DATA);

                     lcd_print(13, 1, value);
              }

              delay_ms(20);
              lcd_print(4, 1, value);

              value++;
              delay_ms(200);
       };
}


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_HSIDIV4);
                                                                            CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);

       CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI, DISABLE,
                             CLK_CURRENTCLOCKSTATE_ENABLE);

       CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, 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(GPIOB);
       GPIO_Init(Button_Port, Button_Pin, GPIO_MODE_IN_FL_NO_IT);
}


void Flash_setup(void)
{
       FLASH_DeInit();
}


void lcd_print(unsigned char x_pos, unsigned char y_pos, unsigned char value)
{
       char chr = 0x00;

       chr = ((value / 100) + 0x30);
       LCD_goto(x_pos, y_pos);
       LCD_putchar(chr);

       chr = (((value / 10) % 10) + 0x30);
       LCD_goto((x_pos + 1), y_pos);
       LCD_putchar(chr);

       chr = ((value % 10) + 0x30);
       LCD_goto((x_pos + 2), y_pos);
       LCD_putchar(chr);
}

 

Explanation

In this demo, two-wire I2C LCD is used for displaying data. The code works by reading the last data stored in the EEPROM and incrementing a variable named value. Only one location (0x4000) is read and updated when the Discovery board’s button is pressed.

Using the internal EEPROM is very easy. We need to deinitialize it first:

void Flash_setup(void)
{
       FLASH_DeInit();
}

 

Reading a location is as follows:

value = FLASH_ReadByte(0x4000);

We just have to set the location we wish to read.

To erase and to write, we need to unlock the memory type we wish to write using Memory Access Security System (MASS) key, write/erase the desired location and the lock it back. This lock feature ensures safety from data corruption and accidental writes.

FLASH_Unlock(FLASH_MEMTYPE_DATA);
FLASH_EraseByte(0x4000);
delay_ms(20);
FLASH_ProgramByte(0x4000, value);
delay_ms(20);
FLASH_Lock(FLASH_MEMTYPE_DATA);

 

Demo

EEPROM

Continue Reading ...

Related Posts

Leave a Reply

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