当然如果有外部EEPROM,自然是不会使用到内部的EEPROM的。但小东西也有大用途,例如做无线应用时,减少成本的情况下,还能保存一些特定设置,如:休眠时间,工作频率,输出功率,密码等。
EEPROM的3种编程模式:
l字节编程(没有擦除操作)
可对EEPROM的数据区域进行逐字地编程。应用程序直接向目标地址写入数据。
l字编程
EEPROM允许字编程(一次编程4个字节),从而缩短EEPROM的编程时间。
l块编程(没有擦除操作)
EEPROM块编程操作允许一次对整个块(64个字节)进行编程,整个块在编程前被自动擦除。但块编程操作一定要在RAM中运行。
下面以字节编程进行讲解:
实验平台:stm8s103k3 + stlink
在stm8s_flash.h中:
#if defined (STM8S103) || defined(STM8S903)
#define FLASH_PROG_END_PHYSICAL_ADDRESS((uint32_t)0x9FFF)
#define FLASH_PROG_BLOCKS_NUMBER((uint16_t)128)
#define FLASH_DATA_START_PHYSICAL_ADDRESS ((uint32_t)0x004000)
#define FLASH_DATA_END_PHYSICAL_ADDRESS((uint32_t)0x00427F)
#define FLASH_DATA_BLOCKS_NUMBER((uint16_t)10)
#define FLASH_BLOCK_SIZE((uint8_t)64)
#endif
从这里可以看出,eeprom的地址为0x004000~0x00427F,这段地址分为10个Block,每个Block有64个Byte,总容量为640Byte.
关于2个秘钥在stm8s_flash.h中已经定义:
#define FLASH_RASS_KEY1 ((uint8_t)0x56)
#define FLASH_RASS_KEY2 ((uint8_t)0xAE)
中文数据手册上KEY1和KEY2的定义与代码一致,但是英文数据手册上KEY1为0x56和KEY1为)0XAE.暂且不讨论谁搞反了,以代码为准吧!
首先要初始化EEPROM:
我们在eeprom.h中定义:
typedef enum{
#if defined(STM8S103) || defined(STM8S003) ||defined(STM8S903)
Block_0=0x4000,
Block_1=0x4040,
Block_2=0x4080,
Block_3=0x40C0,
Block_4=0x4100,
Block_5=0x4140,
Block_6=0x4180,
Block_7=0x41C0,
Block_8=0x4200,
Block_9=0x4240
#endif
}BlockStartAddress_TypeDef; //分块存数,方便读写操作!
在eeprom.c中初始化:
初始化操作步骤:
1.设定编程时间。FIX=1为标准编程时间(一般一次编程时间为6ms)。如果EEPROM被擦除过并且FIX=0,那么变成时间为标准编程时间的一半(一般为3ms)。
2.向FLASH_DUKR寄存器连续写入两个MASS密钥值来解除DATA区域的写保护。
第一个硬件密钥:0b0101 0110 (0x56)
第二个硬件密钥:0b1010 1110 (0xAE)
如果第二个秘钥匹配正确,FLASH_IAPSR的DUL位自动置位。
3.等待DATA EEPROM区解锁。
void EEPROM_Init()
{
FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_TPROG);
//注意顺序:FLASH_DUKR = 0xAE为Key2,FLASH_DUKR = 0x56;为Key1
FLASH_Unlock( FLASH_MEMTYPE_DATA);
//如果第二个秘钥正确,FLASH_IAPSR_DUL=1;
//直到FLASH_IAPSR_DUL由硬件置位,才跳出while循环
while((FLASH->IAPSR & FLASH_IAPSR_DUL) == 0);//等待DATA EEPROM区解锁
}
FLASH_Unlock函数原型在stm8s_flash.c中:
void FLASH_Unlock(FLASH_MemType_TypeDef FLASH_MemType)
{
assert_param(IS_MEMORY_TYPE_OK(FLASH_MemType));
if (FLASH_MemType == FLASH_MEMTYPE_PROG)
{
FLASH->PUKR = FLASH_RASS_KEY1;
FLASH->PUKR = FLASH_RASS_KEY2;
}
else
{
FLASH->DUKR = FLASH_RASS_KEY2;
FLASH->DUKR = FLASH_RASS_KEY1;
}
}
在main.c中,你就可以进行擦除,读,写操作了!
FLASH_EraseByte(uint32_t Address);//擦除某地址的一个字节
FLASH_ProgramByte(0x4001,0x08); //写入一个字节
while((FLASH_IAPSR & 0x04) != 0x00);//直到EOP=1,EEPROM编程结束
Rdat= FLASH_ReadByte(0x4000);//读出某地址的一个字节