硬知识
摘自《STC89C52系列单片机器件手册》
STC89C5x系列单片机内部集成了的EEPROM是与程序空间是分开的,利用ISP/IAP技术可将内部Data Flash当EEPROM,擦写次数在10万次以上。EEPROM可分为若干个扇区,每个扇区包含512字节。使用时,建议同一次修改的数据放在同一个扇区,不是同一次修改的数据放在不同的扇区,不一定要用满。数据存储器的擦除操作是按扇区进行的。
EEPROM可用于保存一些需要在应用过程中修改并且掉电不丢失的参数数据。在用户程序中,可以对EEPROM进行字节读/字节编程/扇区擦除操作。在工作电压Vcc偏低时,建议不要进行EEPROM/IAP操作。
IAP及EEPROM新增特殊功能寄存器介绍
ISP/IAP数据寄存器ISP_DATA
ISP_DATA : ISP/IAP操作时的数据寄存器。
ISP/IAP 从Flash读出的数据放在此处,向Flash写的数据也需放在此处
ISP/IAP地址寄存器ISP_ADDRH和ISP_ADDRL
ISP_ADDRH : ISP/IAP 操作时的地址寄存器高八位。 该寄存器地址为E3H,复位后值为00H.
ISP_ADDRL : ISP/IAP 操作时的地址寄存器低八位。 该寄存器地址为E4H,复位后值为00H.
ISP/IAP命令寄存器ISP_CMD
ISP/IAP命令寄存器IAP_CMD格式如下:
程序在系统ISP程序区时可以对用户应用程序区/数据Flash区(EEPROM)进行字节读/字节编程/扇区擦除;程序在用户应用程序区时,仅可以对数据Flash 区(EEPROM)进行字节读/字节编程/扇区擦除。已经固化有ISP引导码,并设置为上电复位进入ISP
ISP/IA命令触发寄存器ISP_TRIG
ISP_TRIG: ISP/IAP 操作时的命令触发寄存器。 在ISPEN(ISP_CONTR.7) = 1 时,对ISP_TRIG先写入46h,再写入B9h,ISP/IAP 命令才会生效。
ISP/IAP操作完成后,ISP地址高八位寄存器ISP_ADDRH、ISP地址低八位寄存器ISP_ADDRL和ISP命令寄存器ISP_CMD的内容不变。如果接下来要对下一个地址的数据进行ISP/IAP操作,需手动将该地址的高8位和低8位分别写入ISP_ADDRH和ISP_ADDRL寄存器。
每次ISP操作时,都要对ISP_TRIG先写入46H,再写入B9H,ISP/IAP命令才会生效。
ISP/IAP命令寄存器ISP_CONTR
ISP/IAP控制寄存器IAP_CONTR格式如下:
ISPEN: ISP/IAP功能允许位。
0:禁止IAP/ISP读/写/擦除Data Flash/EEPROM
1: 允许IAP/ISP读/写/擦除Data Flash/EEPROM
SWBS: 软件选择从用户应用程序区启动(送0),还是从系统 ISP监控程序区启动(送1)。要与SWRST直接配合才可以实现
SWRST:
0: 不操作;
1: 产生软件系统复位,硬件自动复位。
;在用户应用程序区(AP区)软件复位并从系统ISP监控程序区开始执行程序
MOV ISP_CONTR, #01100000B ;SWBS = 1(选择ISP区), SWRST = 1(软复位)
;在系统ISP监控程序区软件复位并从用户应用程序区(AP 区)开始执行程序
MOV ISP_CONTR, #00100000B ;SWBS = 0(选择AP 区), SWRST = 1(软复位)
EEPROM空间大小及地址
内部可用EEPROM的地址与程序空间是分开的:程序在用户应用程序区时,可以对EEPROM 进行IAP/ISP操作。
小常识
3个基本命令——字节读,字节编程,扇区擦除
字节编程:将"1"写成"1"或"0",将"0"写成"0"。如果某字节是FFH,才可对其进行字节编程。如果该字节不是FFH,则须先将整个扇区擦除,因为只有“扇区擦除”才可以将"0"变为"1"。
扇区擦除:只有“扇区擦除”才可能将"0"擦除为"1"。
大建议
同一次修改的数据放在同一扇区中,不是同一次修改的数据放在另外的扇区,就不需读出保护。
如果一个扇区只用一个字节,那就是真正的EEPROM,STC单片机的Data Flash比外部EPROM要快很多,读一个字节/编程一个字节大概是10us/60us/10ms
如果在一个扇区中存放了大量的数据,某次只需要修改其中的一个字节或一部分字节时,则另外的不需要修改的数据须先读出放在STC单片机的RAM中,然后擦除整个扇区,再将需要保留的数据和需修改的数据按字节逐字节写回该扇区中(只有字节写命令,无连续字节写命令)。这时每个扇区使用的字节数是使用的越少越方便(不需读出一大堆需保留数据)。
常见问题
IAP指令完成后,地址是否会自动“加1”或“减1”? 答:不会。
送46和B9触发后,下一次IAP命令是否还需要送46和B9触发?答:是,一定要。
示例程序
改自官方例程。
EEPROM.c
/*------------------------------------------------------------------*/
/* --- STC MCU Limited ---------------------------------------------*/
/* --- STC89-90xx Series MCU ISP/IAP/EEPROM Demo -------------------*/
/* --- Mobile: (86)13922805190 -------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ---------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966----------------------*/
/* --- Web: www.STCMCU.com -----------------------------------------*/
/* --- Web: www.GXWMCU.com -----------------------------------------*/
/* If you want to use the program or the program referenced in the */
/* article, please specify in which data and procedures from STC */
/*------------------------------------------------------------------*/
#include #include "EEPROM.h" #include "intrins.h" /*Declare SFR associated with the IAP */ sfr IAP_DATA = 0xE2; //Flash data register sfr IAP_ADDRH = 0xE3; //Flash address HIGH sfr IAP_ADDRL = 0xE4; //Flash address LOW sfr IAP_CMD = 0xE5; //Flash command register sfr IAP_TRIG = 0xE6; //Flash command trigger sfr IAP_CONTR = 0xE7; //Flash control register /*Define ISP/IAP/EEPROM command*/ #define CMD_IDLE 0 //Stand-By #define CMD_READ 1 //Byte-Read #define CMD_PROGRAM 2 //Byte-Program #define CMD_ERASE 3 //Sector-Erase void Delay(unsigned char n); void IapIdle(); /*---------------------------- Disable ISP/IAP/EEPROM function Make MCU in a safe state ----------------------------*/ void IapIdle() { IAP_CONTR = 0; //Close IAP function IAP_CMD = 0; //Clear command to standby IAP_TRIG = 0; //Clear trigger register IAP_ADDRH = 0x80; //Data ptr point to non-EEPROM area IAP_ADDRL = 0; //Clear IAP address to prevent misuse } /*---------------------------- Read one byte from ISP/IAP/EEPROM area Input: addr (ISP/IAP/EEPROM address) Output:Flash data ----------------------------*/ unsigned char IapReadByte(unsigned short addr) { unsigned char dat; //Data buffer IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time IAP_CMD = CMD_READ; //Set ISP/IAP/EEPROM READ command IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high IAP_TRIG = 0x46; //Send trigger command1 (0x46) IAP_TRIG = 0xb9; //Send trigger command2 (0xb9) _nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete dat = IAP_DATA; //Read ISP/IAP/EEPROM data IapIdle(); //Close ISP/IAP/EEPROM function return dat; //Return Flash data } /*---------------------------- Program one byte to ISP/IAP/EEPROM area Input: addr (ISP/IAP/EEPROM address) dat (ISP/IAP/EEPROM data) Output:- ----------------------------*/ void IapProgramByte(unsigned short addr, unsigned char dat) { IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time IAP_CMD = CMD_PROGRAM; //Set ISP/IAP/EEPROM PROGRAM command IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high IAP_DATA = dat; //Write ISP/IAP/EEPROM data IAP_TRIG = 0x46; //Send trigger command1 (0x46) IAP_TRIG = 0xb9; //Send trigger command2 (0xb9) _nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete IapIdle(); } /*---------------------------- Erase one sector area Input: addr (ISP/IAP/EEPROM address) Output:- ----------------------------*/ void IapEraseSector(unsigned short addr) { IAP_CONTR = ENABLE_IAP; //Open IAP function, and set wait time IAP_CMD = CMD_ERASE; //Set ISP/IAP/EEPROM ERASE command IAP_ADDRL = addr; //Set ISP/IAP/EEPROM address low IAP_ADDRH = addr >> 8; //Set ISP/IAP/EEPROM address high IAP_TRIG = 0x46; //Send trigger command1 (0x46) IAP_TRIG = 0xb9; //Send trigger command2 (0xb9) _nop_(); //MCU will hold here until ISP/IAP/EEPROM operation complete IapIdle(); } unsigned char IapWriteBytes(unsigned short addr, unsigned char * pData, unsigned short len) { unsigned char temp[512], Addr = addr; unsigned short i; Addr >>= 9; Addr <<= 9; addr %= 512; for(i = 0; i < 512; ++i) { temp[i] = IapReadByte(Addr + i); } for(i = 0; i < len; ++i) { temp[addr + i] = *(pData + i); } IapEraseSector(Addr); //Erase current sector for (i = 0; i < 512; ++i) //Program 512 bytes data into data flash
上一篇:【51单片机快速入门指南】8:看门狗定时器(WDT)
下一篇:【51单片机快速入门指南】6.4:DHT11、DHT22单总线温湿度传感器
推荐阅读最新更新时间:2024-11-13 10:20
设计资源 培训 开发板 精华推荐
- LT3692AIFE 电源双输入单路 3.3V/4A 输出降压转换器的典型应用电路
- DER-622 - 两线(无中性线)、宽范围、非隔离反激式、蓝牙墙壁开关
- 使用 Microchip Technology 的 MIC4744YML 的参考设计
- 使用 Semtech 的 SC1592 的参考设计
- 3.6V DC 至 DC 单路输出电源,适用于广播电视和广播
- 具有 12V VDD 输入的 LTC2945CMS 3.3V 输入电源监视器的典型应用
- 使用 Sanken Electric Co., Ltd 的 SPF5017 的参考设计
- OP495GSZ 单电源差分扬声器驱动器的典型应用
- MCP1603L 500mA 同步降压稳压器的典型应用
- LTC3119EFE 5V、1MHz 宽输入稳压器的典型应用电路