ISP和IAP:
ISP(In SystemProgramable):在系统编程,即在已经焊好的板子上,不用取下就可以对其进行编程。
IAP(In ApplicationProgramable):在应用编程。即片子提供一系列机制,当片子在运行程序时,了以提供一种改变Flash数据的方法。
也即:程序可以自己往程序存储器里面写数据或者更改程序,其典型应用就是使用boot或者叫做bootloader的一下段代码来进行跳转,从而进行程序的升级。
ISP/IAP相关寄存器列表:

ISP_DATA---ISP/IAP操作时的数据寄存器,包括:
ISP/IAP从Flash读出的数据放于此处,向Flash写入的数据也放于此处。
ISP_ADDRH---ISP/IAP操作时的地址寄存器高八位
ISP_ADDRL---ISP/IAP操作时的地址寄存器低八位
ISP_CMD---ISP/IAP操作时的命令模式寄存器,须命令触发寄存器触发方可生效,其模式设置如图:

程序在系统ISP程序区时,可以对用户应用程序/数据Flash区(EEPROM)进行字节读/字节编程/扇区擦除,
程序在用户应用程序区时,尽可以对数据Flash区(EEPROM)进行字节读/字节编程/扇区擦除
ST89C51RC/RD+系列MCU出场时已经固化有ISP引导码,并设置为上电复位进入ISP程序去,并且出厂时就已经完全加密。
ISP_TRIG---ISP/IAP操作时的命令触发寄存器。
在ISPEN(ISP_CONTR.7)=1时,对ISP_TRIG 写入46H,在写入B9H,ISP/IAP 命令才会生效。
STC89C52RC,STC89LE52RC内部可用data Flash(EEPROM)地址列表:

每个扇区为5112B,写程序时,将一次修改的数据放在同一个扇区,,因为擦除的时候,一次至少擦除一个扇区的数据。
更新数据前,必须先擦除原来的数据,不能再原来的数据基础上更新内容。
具体实现代码:
-----------------------------------------------------------------------------------------------------------------------
#include
#include
#define uchar unsigned char
#define uint unsigned int
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
#define RDCommand0X01 //定义ISP操作命令
#define PrgCommand 0X02
#define EraseCommand 0X03
#define error 1
#define OK 0
#define WaitTime0x01 //定义CPU的等待时间
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
sfrISP_DATA=0XE2; //寄存器声明
sfr ISP_ADDRH=0XE3;
sfr ISP_SDDRL=0XE4;
sfr ISP_CMD=0XE5;
sfr ISP_TRIG=0XE6;
sfr ISP_CONTR=0XE7;
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
//打开ISP/IAP功能
void ISP_IAP_Enable(void)
{
EA=0; //关中断
ISP_CONTR=ISPCONTR &0X18; //00011000
ISP_CONTR=ISPCONTR | WaitTime; //写入硬件延时
ISP_CONTR=ISPCONTR |0X80; //ISPEN=1
}
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
//关闭ISP/IAP功能
void ISP_IAP_Disable(void)
{
ISP_CONTR=ISP_CONTR &0X7F; //ISPEN=0
ISP_TRIG=0X00;
EA=1; //开中断
}
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
//触发代码
void ISP_Trig(void)
{
ISP_IAP_Enable(); //打开ISP/IAP功能
ISP_TRIG=0X46; //触发ISP/IAP命令字节1
ISP_TRIG=0XB9; //触发ISP/IAP命令字节2
_nop_();
}
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
//指定地址---字节读
uchar Byte_Read(uint byte_addr)
{
ISP_ADDRH=(uchar)(byte_addr>>8); //地址赋值
ISP_ADDRL=(uchar)(byte_addr&0X00FF);
ISP_CMD=ISP_CMD &0XF8; //清除低三位
ISP_CMD=ISP_CMD |RDCommand; //写入读命令
ISP_Trig(); //触发执行
ISP_IAP_Disable(); //关闭ISP/IAP功能
return(ISP_DATA); //返回读到的数据
}
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
//指定地址---扇区擦除
void Sector_Erase(uint sector_addr)
{
uintSector_Addr;
Sector_Addr=sector_addr &0XFE00; //取扇区地址
ISP_ADDRH=(uchar)(Sector_Addr>>8);
ISP_ADDRL=0X00;
ISP_CMD=ISP_CMD &0XF8; //清空低三位
ISP_CMD=ISP_CMD |EraseCommand; //擦出命令3
ISP_Trig(); //触发执行
ISP_IAP_Disable(); //关闭ISP/IAP功能
}
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
//指定地址---字节写
void Byte_Write(uint byte_addr,uchar original_data)
{
ISP_ADDRH=(uchar)(byte_addr>>8); //取地址
ISP_ADDRL=(uchar)(byte_addr & 0X00FF);
ISP_CMD=ISP_CMD &0XF8; //清除低三位
ISP_CMD=ISP_CMD |PrgCommand; //写命令2
ISP_DATA=original_data; //写入数据准备
ISP_Trig(); //触发执行
ISP_IAP_Disable(); //关闭ISP/IAP功能
}
-----------------------------------------------------------------------------------------------------------------------
最后对于代码的一些部分做一定的解释:
ISP_ADDRH= (uchar)(Sector_Addr>>8); //Sector_Addr右移8位,然后赋值给ISP_ADDRH
ISP_ADDRL= (uchar)(byte_addr & 0X00FF);//byte_addr与上0X00FF,赋值给ISP_ADDRL
次处:
dataFlash(EEPROM)的最小扇区的地址为:
2000H=0010 0000 0000 0000B ,
共计16为,而ISP_ADDRH共8位,
且为地址寄存器的高八位,右移8位,相当于舍去低8位,把地址寄存器的高8为赋予给ISP_ADDRH
对于寄存器地址,byte_addr与上0X00FF,取byte_addr的低8位,强制转换成uchar,然后赋值给ISP_ADDRL,且ISP_ADDRL为地址寄存器的低8位.
|