ISP和IAP:
ISP(In SystemProgramable):在系統(tǒng)編程,即在已經焊好的板子上,不用取下就可以對其進行編程。
IAP(In ApplicationProgramable):在應用編程。即片子提供一系列機制,當片子在運行程序時,了以提供一種改變Flash數(shù)據(jù)的方法。
也即:程序可以自己往程序存儲器里面寫數(shù)據(jù)或者更改程序,其典型應用就是使用boot或者叫做bootloader的一下段代碼來進行跳轉,從而進行程序的升級。
ISP/IAP相關寄存器列表:

ISP_DATA---ISP/IAP操作時的數(shù)據(jù)寄存器,包括:
ISP/IAP從Flash讀出的數(shù)據(jù)放于此處,向Flash寫入的數(shù)據(jù)也放于此處。
ISP_ADDRH---ISP/IAP操作時的地址寄存器高八位
ISP_ADDRL---ISP/IAP操作時的地址寄存器低八位
ISP_CMD---ISP/IAP操作時的命令模式寄存器,須命令觸發(fā)寄存器觸發(fā)方可生效,其模式設置如圖:

程序在系統(tǒng)ISP程序區(qū)時,可以對用戶應用程序/數(shù)據(jù)Flash區(qū)(EEPROM)進行字節(jié)讀/字節(jié)編程/扇區(qū)擦除,
程序在用戶應用程序區(qū)時,盡可以對數(shù)據(jù)Flash區(qū)(EEPROM)進行字節(jié)讀/字節(jié)編程/扇區(qū)擦除
ST89C51RC/RD+系列MCU出場時已經固化有ISP引導碼,并設置為上電復位進入ISP程序去,并且出廠時就已經完全加密。
ISP_TRIG---ISP/IAP操作時的命令觸發(fā)寄存器。
在ISPEN(ISP_CONTR.7)=1時,對ISP_TRIG 寫入46H,在寫入B9H,ISP/IAP 命令才會生效。
STC89C52RC,STC89LE52RC內部可用data Flash(EEPROM)地址列表:

每個扇區(qū)為5112B,寫程序時,將一次修改的數(shù)據(jù)放在同一個扇區(qū),,因為擦除的時候,一次至少擦除一個扇區(qū)的數(shù)據(jù)。
更新數(shù)據(jù)前,必須先擦除原來的數(shù)據(jù),不能再原來的數(shù)據(jù)基礎上更新內容。
具體實現(xiàn)代碼:
-----------------------------------------------------------------------------------------------------------------------
#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; //開中斷
}
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
//觸發(fā)代碼
void ISP_Trig(void)
{
ISP_IAP_Enable(); //打開ISP/IAP功能
ISP_TRIG=0X46; //觸發(fā)ISP/IAP命令字節(jié)1
ISP_TRIG=0XB9; //觸發(fā)ISP/IAP命令字節(jié)2
_nop_();
}
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
//指定地址---字節(jié)讀
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(); //觸發(fā)執(zhí)行
ISP_IAP_Disable(); //關閉ISP/IAP功能
return(ISP_DATA); //返回讀到的數(shù)據(jù)
}
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
//指定地址---扇區(qū)擦除
void Sector_Erase(uint sector_addr)
{
uintSector_Addr;
Sector_Addr=sector_addr &0XFE00; //取扇區(qū)地址
ISP_ADDRH=(uchar)(Sector_Addr>>8);
ISP_ADDRL=0X00;
ISP_CMD=ISP_CMD &0XF8; //清空低三位
ISP_CMD=ISP_CMD |EraseCommand; //擦出命令3
ISP_Trig(); //觸發(fā)執(zhí)行
ISP_IAP_Disable(); //關閉ISP/IAP功能
}
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
//指定地址---字節(jié)寫
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; //寫入數(shù)據(jù)準備
ISP_Trig(); //觸發(fā)執(zhí)行
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)的最小扇區(qū)的地址為:
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位.
|