STM8S存储器的读写操作

/*
**********************************************************************************************************************************
* Name    : STM8S存储器的读写操作
* Author  : MingMing
* Release : 2014/1/2
* Update  : 2014/1/2
* E-mail  : [email protected]
**********************************************************************************************************************************
*/
    在芯片中存储器一般分为两种:一种是EEPROM(数据存储器),另一种是FLASH ROM(程序存储器)。它们都是非易失性存储器,但是在特性上有一些差别。EEPROM读写最小单元为字节,在同一个地址重复写入数据时允许不进行擦除操作。FLASH ROM是按照扇区读写的,在同一个地址重复写入数据时需要擦除该地址才能再次写入。
    STM8S的芯片集成了EEPROM和FLASH ROM两种存储器,前者负责存储数据和Option Byte(选项字节),后者负责存储代码。
Stm8s_flash.h文件中代码如下所示:
/*
  ***************************************************************************
  * @file stm8s_flash.h
  * @brief This file is used to configure the Library.
  * @author clint.wang
  * @platform IAR For STM8S 1.31 + STM8S105C6
  * @date 12/27/2013
 ******************************************************************************
*/
#ifndef __STM8S_FLASH_H__
#define __STM8S_FLASH_H__
//
#include 
#include "stm8s_type.h"
//
#define STM8S105
#ifdef STM8S105
  #define FLASH_PROG_PHYSICAL_ADDR_START   0x8000       /* 程序存储区首端地址 */
  #define FLASH_PROG_PHYSICAL_ADDR_END     0xFFFF       /* 程序存储区末端地址 */
  #define FLASH_PROG_BLOCKS_NUMBER         256          /* 程序存储区的块数 */
  #define FLASH_DATA_PHYSICAL_ADDR_START   0x4000       /* 数据存储区首端地址 */
  #define FLASH_DATA_PHYSICAL_ADDR_END     0x43FF       /* 数据存储区末端地址 */
  #define FLASH_DATA_BLOCKS_NUMBER         8            /* 数据存储区的块数 */
  #define OPTION_BYTE_PHYSICAL_ADDR_START  0x4800       /* 选项字节首端地址 */
  #define OPTION_BYTE_PHYSICAL_ADDR_END    0x487F       /* 选项字节末端地址 */
  #define OPTION_BYTE_NUMBER               15           /* 选项字节的长度 */
  #define FLASH_BLOCK_SIZE                 128          /* 每块存储所含的字节 */
#endif /* STM8S105 */
//
#define FLASH_RASS_KEY1     0x56                        /* FLASH解除写保护密钥 */
#define FLASH_RASS_KEY2     0xAE                        /* FLASH解除写保护密钥 */
#define FLASH_CLR_BYTE      0x00
#define FLASH_SET_BYTE      0xFF
//
typedef enum{
  FLASH_PROG = 0,
  FLASH_DATA = 1
}PLASH_TYPE;
//
#define ADDR_FLASH(addr)     *((INT8U*)addr)
#define ADDR_PROG(offset)    ADDR_FLASH(FLASH_PROG_PHYSICAL_ADDR_START + offset)  
#define ADDR_DATA(offset)    ADDR_FLASH(FLASH_DATA_PHYSICAL_ADDR_START + offset)
#define ADDR_OPTION(offset)  ADDR_FLASH(OPTION_BYTE_PHYSICAL_ADDR_START + offset)
//
/* Flash写操作的锁定和解除 */
void FLASH_WirteLock(PLASH_TYPE memoryType);
void FLASH_WirteUnlock(PLASH_TYPE memoryType);
//
/* Flash 程序存储器的读写和擦除 */
void FLASH_ProgWirteByte(INT16U addrOffset, INT8U iuData);
void FLASH_ProgEraseByte(INT16U addrOffset);
INT8U FLASH_ProgReadByte(INT16U addrOffset);
//
/* EEPROM 数据存储器的读写和擦除 */
void FLASH_DataWirteByte(INT16U addrOffset, INT8U iuData);
void FLASH_DataEraseByte(INT16U addrOffset);
INT8U FLASH_DataReadByte(INT16U addrOffset);
//
/* 选项字节的读写 */
void FLASH_OptionWirteByte(INT16U addrOffset, INT8U iuData);
INT8U FLASH_OptionReadByte(INT16U addrOffset);
//
/* Flash在halt状态下进入低功耗模式 */
void FLASH_LowPowerMode(void);
/* 擦除一块存储区 */
void FLASH_EraseBlock(INT8U BlockNum, PLASH_TYPE MemType);
//
#endif

Stm8s_flash.c文件中代码如下所示:

#include "stm8s_flash.h"

/*******************************************************************************
* 函数名:FLASH_WirteLock
* 描  述:Flash写保护使能
* 参  数:memoryType :写保护对象,程序存储器或者数据存储器
* 返回值:无
*******************************************************************************/
void FLASH_WirteLock(PLASH_TYPE memoryType)
{
  if (memoryType == FLASH_DATA)
     FLASH_IAPSR &= ~MASK_FLASH_IAPSR_DUL;
  else
     FLASH_IAPSR &= ~MASK_FLASH_IAPSR_PUL; 
}
/*******************************************************************************
* 函数名:FLASH_WirteUnlock
* 描  述:Flash写保护解锁
* 参  数:memoryType :解保护对象,程序存储器或者数据存储器
* 返回值:无
*******************************************************************************/
void FLASH_WirteUnlock(PLASH_TYPE memoryType)
{
  if(memoryType == FLASH_DATA)
  {
    do{
    FLASH_DUKR = FLASH_RASS_KEY2;                   /* 写入第二个密钥 */
    FLASH_DUKR = FLASH_RASS_KEY1;                   /* 写入第一个密钥 */ 
    }while(!(FLASH_IAPSR & MASK_FLASH_IAPSR_DUL));  /* 判断解锁是否成功 */  
  }
  else
  {
    do{
    FLASH_PUKR = FLASH_RASS_KEY1;                   /* 写入第一个密钥 */
    FLASH_PUKR = FLASH_RASS_KEY2;                   /* 写入第二个密钥 */ 
    }while(!(FLASH_IAPSR & MASK_FLASH_IAPSR_PUL));  /* 判断解锁是否成功 */    
  }
}
/*******************************************************************************
* 函数名:FLASH_ProgWirteByte
* 描  述:写一个字节到程序存储区
* 参  数:addrOffset :相对程序存储区首地址的偏移量,从0开始
          iuData :写入存储区的数据
* 返回值:无
*******************************************************************************/
void FLASH_ProgWirteByte(INT16U addrOffset, INT8U iuData)
{
  if(FLASH_IAPSR & MASK_FLASH_IAPSR_PUL)            /* 是否处于解锁状态 */
  {
    if(addrOffset < ((INT16U)FLASH_PROG_BLOCKS_NUMBER * 128))
    {
      ADDR_PROG(addrOffset) = iuData;
      while(!(FLASH_IAPSR & MASK_FLASH_IAPSR_EOP));
    }    
  }
}
/*******************************************************************************
* 函数名:FLASH_ProgEraseByte
* 描  述:擦除程序存储区指定地址的数据,写入0x00即可
* 参  数:addrOffset :相对程序存储区首地址的偏移量,从0开始
* 返回值:无
*******************************************************************************/
void FLASH_ProgEraseByte(INT16U addrOffset)
{
  
  FLASH_ProgWirteByte(addrOffset,FLASH_CLR_BYTE );//FLASH_CLR_BYTE  
}
/*******************************************************************************
* 函数名:FLASH_ProgReadByte
* 描  述:读取程序存储区指定地址的数据
* 参  数:addrOffset :相对程序存储区首地址的偏移量,从0开始
* 返回值:偏移地址存储的数据
*******************************************************************************/
INT8U FLASH_ProgReadByte(INT16U addrOffset)
{
  if(addrOffset < ((INT16U)FLASH_PROG_BLOCKS_NUMBER * FLASH_BLOCK_SIZE))  
    return (ADDR_PROG(addrOffset));
  return 0;
}
/*******************************************************************************
* 函数名:FLASH_DataWirteByte
* 描  述:写一个字节到数据存储区
* 参  数:addrOffset :相对数据存储区首地址的偏移量,从0开始
          iuData :写入存储区的数据
* 返回值:无
*******************************************************************************/
void FLASH_DataWirteByte(INT16U addrOffset, INT8U iuData)
{
  if(FLASH_IAPSR & MASK_FLASH_IAPSR_DUL)            /* 是否处于解锁状态 */
  {  
    if(addrOffset < (FLASH_DATA_BLOCKS_NUMBER*FLASH_BLOCK_SIZE))
    {
      ADDR_DATA(addrOffset) = iuData;
      while(!(FLASH_IAPSR & MASK_FLASH_IAPSR_EOP));
    }
  }
}
/*******************************************************************************
* 函数名:FLASH_DataEraseByte
* 描  述:擦除数据存储区指定地址的数据,写入0x00即可
* 参  数:addrOffset :相对程序存储区首地址的偏移量,从0开始
* 返回值:无
*******************************************************************************/
void FLASH_DataEraseByte(INT16U addrOffset)
{
  FLASH_DataWirteByte(addrOffset, FLASH_CLR_BYTE);
}
/*******************************************************************************
* 函数名:FLASH_DataReadByte
* 描  述:读取数据存储区指定地址的数据
* 参  数:addrOffset :相对数据存储区首地址的偏移量,从0开始
* 返回值:偏移地址存储的数据
*******************************************************************************/
INT8U FLASH_DataReadByte(INT16U addrOffset)
{
  if(addrOffset < (FLASH_DATA_BLOCKS_NUMBER*FLASH_BLOCK_SIZE))  
  {  return (ADDR_DATA(addrOffset));}
  return 0;
}
/*******************************************************************************
* 函数名:FLASH_OptionWirteByte
* 描  述:写一个字节到选项字节存储区
* 参  数:addrOffset :相对选项字节存储区首地址的偏移量,从0开始
          iuData :写入存储区的数据
* 返回值:无
*******************************************************************************/
void FLASH_OptionWirteByte(INT16U addrOffset, INT8U iuData)
{
  if(addrOffset < OPTION_BYTE_NUMBER)
  {
    FLASH_CR2  |= MASK_FLASH_CR2_OPT;          /* 解除OPT写保护 */ 
    FLASH_NCR2 &=~MASK_FLASH_CR2_OPT;          /* 解除OPT写保护 */
    
    ADDR_OPTION(addrOffset)   |= iuData;       /* 写入选项字节 */
    ADDR_OPTION(addrOffset+1) &=~iuData;       /* 写入选项字节 */
    
    while(!(FLASH_IAPSR & MASK_FLASH_IAPSR_EOP));
    
    FLASH_CR2  &=~MASK_FLASH_CR2_OPT;          /* 锁定OPT写保护 */ 
    FLASH_NCR2 |= MASK_FLASH_CR2_OPT;          /* 锁定OPT写保护 */    
  }
}
/*******************************************************************************
* 函数名:FLASH_OptionReadByte
* 描  述:读取选项字节存储区指定地址的数据
* 参  数:addrOffset :相对选项字节存储区首地址的偏移量,从0开始
* 返回值:偏移地址存储的数据
*******************************************************************************/
INT8U FLASH_OptionReadByte(INT16U addrOffset)
{
  if(addrOffset < OPTION_BYTE_NUMBER)
    return (ADDR_DATA(addrOffset));
  return 0;
}
/*******************************************************************************
* 函数名:FLASH_LowPowerMode
* 描  述:Flash在halt状态下进入低功耗模式
* 参  数:无
* 返回值:无
*******************************************************************************/
void FLASH_LowPowerMode(void)
{
    FLASH_CR1 |= (MASK_FLASH_CR1_AHALT | MASK_FLASH_CR1_HALT);
}
/*******************************************************************************
* 函数名:FLASH_EraseBlock
* 描  述:擦除存储区指定一块存储,写入00 00 00 00即可
* 参  数:BlockNum :块的编号(将要被擦除的块)
          MemType :程序存储器或者数据存储器
* 返回值:无
*******************************************************************************/
void FLASH_EraseBlock(INT8U BlockNum, PLASH_TYPE MemType)
{
    INT16U StartAddress = 0;
    
    if (MemType == FLASH_PROG)
        StartAddress = FLASH_PROG_PHYSICAL_ADDR_START;
    else
        StartAddress = FLASH_DATA_PHYSICAL_ADDR_START;
    
    StartAddress = StartAddress + (BlockNum * FLASH_BLOCK_SIZE);

    FLASH_CR2  |= MASK_FLASH_CR2_ERASE;
    FLASH_NCR2 &=~MASK_FLASH_CR2_ERASE;
  
    ADDR_FLASH(StartAddress + 0) = FLASH_CLR_BYTE;
    ADDR_FLASH(StartAddress + 1) = FLASH_CLR_BYTE;
    ADDR_FLASH(StartAddress + 2) = FLASH_CLR_BYTE;
    ADDR_FLASH(StartAddress + 3) = FLASH_CLR_BYTE;
       
    while ((FLASH_IAPSR & MASK_FLASH_IAPSR_HVOFF)!= 0x00);
}



你可能感兴趣的:(STM8S单片机)