1 内存映射
STM8S105
集成了多达1K
的EEPROM
(掉电数据不会丢失)最高可以支持30万次的擦写次数,用户可以将一些数据保存在EEPROM
中,具体的memory map
如下图所示;
在这里内存一页的大小为64 bytes
(1 block
), DATA EEPROM
的内存地址映射如下图所示;
可以看到,EEPROM
的起始地址为0x004000
,结束地址为0x00427F
,这个在下面编程时会用到,当然具体的大小会因为型号不同而有所差异;
2 程序实现
下面程序基于stm8
的标准库,进行实现,相应标准库可以在st
官网上下载得到;
eeprom_inner.ch
#ifndef EEPROM_INNER_H
#define EEPROM_INNER_H
#include "stm8s.h"
#define EEPROM_BASE_ADDR 0x4000
#define EEPROM_SIZE 0x07FF
union data32_unit_mod {
uint32_t data32;
uint8_t buf[4];
};
typedef union data32_unit_mod data32_unit_mod_t;
union data16_unit_mod {
uint16_t data16;
uint8_t buf[2];
};
typedef union data16_unit_mod data16_unit_mod_t;
/**
外部函数声明
*/
void eeprom_init(void);
uint8_t eeprom_read_byte(uint16_t addr);
void eeprom_write_byte(uint16_t addr,uint8_t data);
void eeprom_write_data32(uint16_t offset, uint32_t data);
void eeprom_write_data16(uint16_t offset, uint16_t data);
void eeprom_write_data8(uint16_t offset, uint8_t data);
uint32_t eeprom_read_data32(uint16_t offset);
uint16_t eeprom_read_data16(uint16_t offset);
uint8_t eeprom_read_data8(uint16_t offset);
void eeprom_area_clear(void);
#endif
eeprom_inner.c
#include "eeprom_inner.h"
#include "stm8s_clk.h"
#include "stm8s_flash.h"
void eeprom_init(void)
{
FLASH_DeInit();
FLASH_Unlock(FLASH_MEMTYPE_DATA);//EEPROM
FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_TPROG);
}
inline uint8_t eeprom_read_byte(uint16_t addr)
{
return FLASH_ReadByte(addr);
}
inline void eeprom_write_byte(uint16_t addr,uint8_t data)
{
FLASH_Unlock(FLASH_MEMTYPE_DATA);
FLASH_ProgramByte(addr, data);
FLASH_WaitForLastOperation(FLASH_MEMTYPE_DATA);
FLASH_Lock(FLASH_MEMTYPE_DATA);
}
void eeprom_write_data32(uint16_t offset, uint32_t data){
data32_unit_mod_t tmp;
tmp.data32 = data;
if(offset+4 > EEPROM_SIZE){
//error
return;
}
eeprom_write_byte(EEPROM_BASE_ADDR+offset, tmp.buf[0]);
eeprom_write_byte(EEPROM_BASE_ADDR+offset+1,tmp.buf[1]);
eeprom_write_byte(EEPROM_BASE_ADDR+offset+2,tmp.buf[2]);
eeprom_write_byte(EEPROM_BASE_ADDR+offset+3,tmp.buf[3]);
}
void eeprom_write_data16(uint16_t offset, uint16_t data){
data16_unit_mod_t tmp;
tmp.data16 = data;
if(offset+2 > EEPROM_SIZE){
//error
return;
}
eeprom_write_byte(EEPROM_BASE_ADDR+offset, tmp.buf[0]);
eeprom_write_byte(EEPROM_BASE_ADDR+offset+1,tmp.buf[1]);
}
void eeprom_write_data8(uint16_t offset, uint8_t data){
if(offset+1 > EEPROM_SIZE){
//error
return;
}
eeprom_write_byte(EEPROM_BASE_ADDR+offset, data);
}
uint32_t eeprom_read_data32(uint16_t offset){
data32_unit_mod_t tmp;
if(offset+4 > EEPROM_SIZE){
//error
return 0xEEEEEEEE;
}
tmp.buf[0] = eeprom_read_byte(EEPROM_BASE_ADDR+offset);
tmp.buf[1] = eeprom_read_byte(EEPROM_BASE_ADDR+offset+1);
tmp.buf[2] = eeprom_read_byte(EEPROM_BASE_ADDR+offset+2);
tmp.buf[3] = eeprom_read_byte(EEPROM_BASE_ADDR+offset+3);
return tmp.data32;
}
uint16_t eeprom_read_data16(uint16_t offset){
data16_unit_mod_t tmp;
if(offset+2 > EEPROM_SIZE){
//error
return 0xEEEE;
}
tmp.buf[0] = eeprom_read_byte(EEPROM_BASE_ADDR+offset);
tmp.buf[1] = eeprom_read_byte(EEPROM_BASE_ADDR+offset+1);
return tmp.data16;
}
uint8_t eeprom_read_data8(uint16_t offset){
if(offset+1 > EEPROM_SIZE){
//error
return 0xEE;
}
return eeprom_read_byte(EEPROM_BASE_ADDR+offset);
}
void eeprom_area_clear(void){
uint16_t index = 0;
for( ; index < EEPROM_SIZE; index+=2 ){
eeprom_write_data16(index,0xFFFF);
}
}