/*;STC12C5A60S2系列单片机EEPROM/IAP功能测试程序演示 */
/*..................................................*/
#include"STC_NEW_8051.H"
#include"intrins.h"
typedef unsigned char BYTE; //定义BYTE代表的是无符号的字符型
typedef unsigned int WORD; //定义WORD代表的是无符号整型
/*申明与IAP相关的特殊功能寄存器,在相应的头文件中已经定义,可以在此省略*/
/* sfr IAP_DATA =0xC2; //Flash数据寄存器
sfr IAP_ADDRH =0xC3; //Flash数据高地址寄存器
sfr IAP_DATA =0xC4; //Flash数据低地址寄存器
**************************************************/
/*定义ISP/IAP/EEPROM命令*/
#define CMD_IDLE 0 //预备,待命
#define CMD_READ 1 //以字节读
#define CMD_PROGRAM 2 //以字节编程
#define CMD_ERASE 3 //擦除扇区
/*定义ISP/IAP/EEPROM操作常数用于IAP_CONTR*/
//#define ENABLE_IAP 0x80 //如果SYSCLK<30MHZ
#define ENABLE_IAP 0x82 //如果SYSCLK<20MHZ
//STC12C5A60S2系列EEPROM的起始地址
#define IAP_ADDRESS 0x0000
void Delay(BYTE n);
void IapIdle();
BYTE IapReadByte(WORD addr);
void IapProgramByte(WORD addr,BYTE dat);
void IapEraseSector(WORD addr);
void main()
{
WORD i;
P1=0xfe;
Delay(10);
IapEraseSector(IAP_ADDRESS);
for(i=0;i<512;i++)
{
if(IapReadByte(IAP_ADDRESS+i)!=0xff)
goto Error; //如果出错,跳出
}
P1=0xfc; //1111,1100擦除成功
Delay(10);
P1=0xf4;
P0=0xfc; //1111,1100,擦除成功则点亮板子上两个LED
Delay(10);
for(i=0;i<512;i++)
{
IapProgramByte(IAP_ADDRESS+i,(BYTE)i);
}
P1=0xf8; //1111,1000编程成功
Delay(10);
P1=0xf0;
P0=0xf8; //装载成功则点亮三个LED
Delay(10);
for(i=0;i<512;i++)
{
if(IapReadByte(IAP_ADDRESS+i)!=(BYTE)i)
goto Error;
}
P1=0xf0; //1111,0000确认成功
Delay(10);
P0=0x00; //读取数据成功,则点亮所有led
while(1);
Error:
P1&=0x7f; //0xxx,xxxx IAP操作失败
while(1);
}
/*--------------------------------------
延时功能函数Delay()
--------------------------------------*/
void Delay(BYTE n)
{
WORD x;
while(n--)
{
x=0;
while(++x);
}
}
/*--------------------------------------
关闭ISP/IAP/EEPROM函数。使得MCU在一个安全状态
--------------------------------------*/
void IapIdle()
{
IAP_CONTR=0; //关闭IAP功能
IAP_CMD=0; //清除命令,等待
IAP_TRIG=0; //清除出发寄存器
IAP_ADDRH=0x80; //数据指针指向不是EEPROM的区域
IAP_ADDRL=0; //清除IAP地址,以防错用
}
/*----------------------------------------
从ISP/IAP/EEPROM区域读取一个字节的内容
输入:地址(IAP/ISP/EEPROM地址)
输出:Flash 数据
-------------------------------------*/
BYTE IapReadByte(WORD addr)
{
BYTE dat; //数据缓存
IAP_CONTR=ENABLE_IAP; //打开IAP功能,同时设置等待时间
IAP_CMD=CMD_READ; //设置读命令
IAP_ADDRL=addr; //设置低地址
IAP_ADDRH=addr>>8;
IAP_TRIG=0x5a; //设置触发命令
IAP_TRIG=0xa5;
_nop_(); //MCU将会停留在这儿一直到IAP/ISP/EEPROM操作完成
dat=IAP_DATA;
IapIdle();
return dat;
}
/*---------------------------------------
下载程序一字节到ISP/IAP/EEPROM区域
输入:地址
数据
输出:无
----------------------------------------*/
void IapProgramByte(WORD addr,BYTE dat)
{
IAP_CONTR=ENABLE_IAP;
IAP_CMD=CMD_PROGRAM;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_DATA=dat;
IAP_TRIG=0x5a;
IAP_TRIG=0xa5;
_nop_();
IapIdle();
}
/*---------------------------------------
擦除一块扇区
输入:地址(IAP/ISP/EEPROM地址)
输出:无
---------------------------------------*/
void IapEraseSector(WORD addr)
{
IAP_CONTR=ENABLE_IAP;
IAP_CMD=CMD_ERASE;
IAP_ADDRL=addr;
IAP_ADDRH=addr>>8;
IAP_TRIG=0x5a;
IAP_TRIG=0xa5;
_nop_();
IapIdle();
}