STM8内部EEPROM的使用详解

1 内存映射

STM8S105集成了多达1KEEPROM(掉电数据不会丢失)最高可以支持30万次的擦写次数,用户可以将一些数据保存在EEPROM中,具体的memory map如下图所示;

在这里内存一页的大小为64 bytes1 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);
    }
}

猜你喜欢

转载自blog.csdn.net/u010632165/article/details/107846877
今日推荐