/*
***************************************************************************
* @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);
}