IAP15系列没有EEPRMOM,用户可直接操作用户程序区
扇区檫除,没有字节檫除
写入:要先檫除,然后在写入
一、相关寄存器
1.1、数据寄存器IAP_DATA
从Flash读出和写入的数据都放在此处
1.2、地址寄存器IAP_ADDRH和IAP_ADDRL
H:地址寄存器高八位
L:地址寄存器低八位
1.3、命令寄存器IAP_CMD
低2位有效:0待机,1字节读,2字节编程,3扇区檫除
1.4、命令触发寄存器IAP_TRIG
对IAP_TRIG先写5a,在写a5,isp/iap命令才会生效。
1.5、命令寄存器IAP_CONTR
IAPEN:isp/iap功能允许位
SWBS:软件选择复位后从用户程序启动(0),还是系统ISP监控程序区启动,要和SWRST配合使用
SWRST:0不操作,1软件控制产生复位。
CMD_FALL:IAP地址无效,且送了5a a5触发失败,则被置位1
WT2....:等待时间
二、c代码实现
include "stc15.h"
include "intrins.h"
/*sfr IAP_DATA = 0xC2;
sfr IAP_ADDRH = 0xC3;
sfr IAP_ADDRL = 0xC4;
sfr IAP_CMD = 0xC5;
sfr IAP_TRIG = 0xC6;
sfr IAP_CONTR = 0xC7;*/
typedef unsigned char u8;
typedef unsigned int u16;
define CMD_IDLE 0 //命令读,写,檫除
define CMD_READ 1
define CMD_PROGRAM 2
define CMD_ERASE 3
define ENABLE_IAP 0x82 // SYSCLK<20MHz 83 SYSCLK<=12Mhz
define IAP_ADDRESS 0xF000 //第121扇区起始地址
void delay(u16 n)
{
do
{
delay_us(900);
}
while(--n);
}
//关闭iap
void IapIdle()
{
IAP_CONTR = 0; //关闭IAP功能
IAP_CMD = 0; //清楚命令寄存器
IAP_TRIG = 0; //清除触发寄存器
IAP_ADDRH = 0x80; //将地址设置到非IAP区
IAP_ADDRL = 0;
}
//扇区檫除
void IapESector(u16 addr)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_ERASE; //设置命令
IAP_ADDRL = addr; //设置地址
IAP_ADDRH = addr>>8;
IAP_TRIG = 0x5a; //触发命令
IAP_TRIG = 0xa5;
_nop_(); //等待完成
IapIdle(); //关闭IAP
}
//写一字节
void IapProgramByte(u16 addr, u8 dat)
{
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_PROGRAM; //设置命令
IAP_ADDRL = addr; //设置地址
IAP_ADDRH = addr>>8;
IAP_DATA = dat; //写数据
IAP_TRIG = 0x5a; //触发
IAP_TRIG = 0xa5;
_nop_();
IapIdle();
}
//读一字节
u8 IapReadByte(u16 addr)
{
u16 dat;
IAP_CONTR = ENABLE_IAP; //使能IAP
IAP_CMD = CMD_READ; //设置命令
IAP_ADDRL = addr; //设置地址
IAP_ADDRH = addr>>8;
IAP_TRIG = 0x5a; //触发
IAP_TRIG = 0xa5;
_nop_();
dat = IAP_DATA; //读数据
IapIdle();
return dat;
}
//写数据
u8 EEPROM_Write()
{
u16 i;
IapESector(IAP_ADDRESS); //檫除
for(i=0; i<512; i++){ //判断是否檫除成功
if(IapReadByte(IAP_ADDRESS+i)!=0xff)
return 0;
}
delay(10);
for(i=0; i<512; i++){
IapProgramByte(IAP_ADDRESS+i, (u8)i );//写入数据
}
delay(10);
return 1;
}
//读
u8 EEPROM_Read()
{
u16 i;
for(i=0; i<512; i++){ //判断是否檫除成功
if(IapReadByte(IAP_ADDRESS+i)!=(u8)i) //读出后校验是否正确
return 0;
}
delay(10);
return 1;
}