/*IAP讀寫規則******************************************
1:EEPROM讀取沒有規則,按地址讀取就可以了.
2:并不需要按地址順序讀取和寫入,兩種操作都可以設置隨機地址.
3:除非進行IAP過程,否則寫入EEPROM的數據即使在刷程序后仍然存
在.
4:寫操作時,如果當前地址已經寫入過一次,則沒有進行擦除操作時
,寫操作將在原數據上疊加,結果會造成讀取錯誤.
5:擦除操作的地址是扇區地址,而非字節地址,例如60S2有兩個扇區
,擦除0x0000H將擦除從0x0000H到0x01FFH的所有512字節數據擦
除0x0001H將擦除從0x0200H到0x03FFH地址內的所有數據
******************************************************/
#include "intrins.h"
//IAP相關端口定義(備忘,不須寫)
/*
sfr IAP_DATA = 0xC2; //Flash 數據寄存器
sfr IAP_ADDRH = 0xC3; //Flash 高位地址
sfr IAP_ADDRL = 0xC4; //Flash 低位地址
sfr IAP_CMD = 0xC5; //Flash 命令寄存器
sfr IAP_TRIG = 0xC6; //Flash 命令觸發
sfr IAP_CONTR = 0xC7; //Flash 控制寄存器
*/
//IAP命令常數
#define CMD_IDLE 0 //待機
#define CMD_READ 1 //位-讀
#define CMD_WRITE 2 //位-程序
#define CMD_ERASE 3 //扇區-擦除
//IAP時間常數
#define ENABLE_IAP 0x80 //如果系統時鐘<30MHz
//#define ENABLE_IAP 0x81 //如果系統時鐘<24MHz
//#define ENABLE_IAP 0x82 //如果系統時鐘<20MHz
//#define ENABLE_IAP 0x83 //如果系統時鐘<12MHz
//#define ENABLE_IAP 0x84 //如果系統時鐘<6MHz
//#define ENABLE_IAP 0x85 //如果系統時鐘<3MHz
//#define ENABLE_IAP 0x86 //如果系統時鐘<2MHz
//#define ENABLE_IAP 0x87 //如果系統時鐘<1MHz
#define IAP_ADDRESS 0x0000 //STC12C5A60S2 系列 EEPROM 起點地址
//void Delay(unsigned char n);
void IapIdle(); //退出IAP過程
unsigned char IapReadByte(unsigned int addr); //IAP讀
void IapWriteByte(unsigned int addr, unsigned char dat); //IAP寫
void IapEraseSector(unsigned int addr); //擦除扇區
/**********************************************************
** 函數名稱: void IapIdle();
** 功能描述: 退出IAP過程
**********************************************************/
void IapIdle()
{
IAP_CONTR = 0; //關閉 IAP 功能
IAP_CMD = 0; //清除命令寄存器進入待機模式
IAP_TRIG = 0; //清除觸發寄存器
IAP_ADDRH = 0xFF; //IAP指針移動到非 EEPROM 區域
IAP_ADDRL = 0xFF;
}
/**********************************************************
** 函數名稱: unsigned char IapReadByte(unsigned int addr);
** 功能描述: 讀EEPROM
** 輸 入: unsigned int addr 地址
** 輸 出: unsigned char dat 數據
**********************************************************/
unsigned char IapReadByte(unsigned int addr)
{
unsigned char dat; //數據緩沖
IAP_CONTR = ENABLE_IAP; //打開 IAP 過程, 并設置等待時間
IAP_CMD = CMD_READ; //設置 ISP/IAP/EEPROM 為讀命令
IAP_ADDRL = addr; //設置 ISP/IAP/EEPROM 低位地址
IAP_ADDRH = addr >> 8; //設置 ISP/IAP/EEPROM 高位地址
IAP_TRIG = 0x5a; //發送觸發命令 1 (0x5a)
IAP_TRIG = 0xa5; //發送觸發命令 2 (0xa5)
_nop_(); //MCU 延遲等待 ISP/IAP/EEPROM 作業完成
_nop_(); //兼容15F104E一個bug,NOP3次
_nop_(); //
dat = IAP_DATA; //讀取 ISP/IAP/EEPROM 數據
IapIdle(); //關閉 ISP/IAP/EEPROM 過程
return dat; //返回 Flash 數據
}
/**********************************************************
** 函數名稱: void IapWriteByte(unsigned int addr, unsigned char dat);
** 功能描述: 寫EEPROM扇區
** 輸 入: unsigned int addr 寫地址
unsigned char dat 寫數據
**********************************************************/
void IapWriteByte(unsigned int addr, unsigned char dat)
{
IAP_CONTR = ENABLE_IAP; //打開 IAP 過程, 并設置等待時間
IAP_CMD = CMD_WRITE; //設置 ISP/IAP/EEPROM 為寫命令
IAP_ADDRL = addr; //設置 ISP/IAP/EEPROM 低位地址
IAP_ADDRH = addr >> 8; //設置 ISP/IAP/EEPROM 高位地址
IAP_DATA = dat; //寫 ISP/IAP/EEPROM 數據
IAP_TRIG = 0x5a; //發送觸發命令 1 (0x5a)
IAP_TRIG = 0xa5; //發送觸發命令 2 (0xa5)
_nop_(); //MCU 延遲等待 ISP/IAP/EEPROM 作業完成
_nop_(); //兼容15F104E一個bug,NOP3次
_nop_(); //
IapIdle(); //關閉 ISP/IAP/EEPROM 過程
}
/**********************************************************
** 函數名稱: void IapEraseSector(unsigned int addr);
** 功能描述: 擦除EEPROM扇區
** 輸 入: unsigned int addr 擦除地址
**********************************************************/
void IapEraseSector(unsigned int addr)
{
IAP_CONTR = ENABLE_IAP; //打開 IAP 過程, 并設置等待時間
IAP_CMD = CMD_ERASE; //設置 ISP/IAP/EEPROM 為擦除命令
IAP_ADDRL = addr; //設置 ISP/IAP/EEPROM 低位地址
IAP_ADDRH = addr >> 8; //設置 ISP/IAP/EEPROM 高位地址
IAP_TRIG = 0x5a; //發送觸發命令 1 (0x5a)
IAP_TRIG = 0xa5; //發送觸發命令 2 (0xa5)
_nop_(); //MCU 延遲等待 ISP/IAP/EEPROM 作業完成
_nop_(); //兼容15F104E一個bug,NOP3次
_nop_(); //
IapIdle(); //關閉 ISP/IAP/EEPROM 過程
}
|