?? iap_sstmcu.c
字號(hào):
/***********************************************************************************************************
* IAP_SSTMCU.c - SST89X564/554 SST89X516/58/54/52RD2的IAP在使用中編程的常用函數(shù)
* 弘微科技(SPAC) 田伯運(yùn)
* WEB: www.spacltd.com.cn TEL:0755-26010579 E-MAIL:andy.tian@spacltd.com.cn
* 功能介紹:
* SST的MCU內(nèi)部FLASH的基本操作函數(shù),包括扇區(qū)擦除,字節(jié)編程,字節(jié)校驗(yàn)等常用基本函數(shù),
* 還有三個(gè)外部常用到的數(shù)據(jù)存儲(chǔ)的函數(shù)(不用考慮具體FLASH的操作命令,注意要將IAP_SSMCU.C文件加入到你的項(xiàng)目中即可):
* 1. modify_single_byte_flash(ADDR,DATA)函數(shù)便可對(duì)指定的FLASH單元的內(nèi)容進(jìn)行改寫;
* 2. modify_multi_byte_flash(begin_ADDR,counter,DATA_array)函數(shù)便可對(duì)指定起始地址的多個(gè)FLASH單元的內(nèi)容進(jìn)行改寫;
* 3. Flash_byte_read(Address); 讀FLASH地址單元內(nèi)容的函數(shù)
* 從而很簡(jiǎn)單的實(shí)現(xiàn)數(shù)據(jù)存儲(chǔ)等功能.
***********************************************************************************************************/
#include <SST89x5xxRD2.H> //加入SST MCU單片機(jī)的頭文件,這樣就剩去了許多的特殊寄存器的聲明
#include <stdio.h>
/***********************************************************************************************************
* 設(shè)置SST單片機(jī)的型號(hào):是52-58,還是516/564?因其BLOCK1的地址是不同的
***********************************************************************************************************/
#define SST89X5XRD 0 //判斷MCU的容量,SST89X5XRD=1:是52-58RD的,BLOCK1的地址:0E000H-0FFFFH
//SST89X5XRD=0:是516/564RD的,BLOCK1的地址:01000H-01FFFH
#define DATAFLASH_BLOCK1 1 //DATAFLASH_BLOCK1=1:選擇是DATA存放在BLOCK1存儲(chǔ)區(qū)域
//DATAFLASH_BLOCK1=0:選擇是DATA存放在BLOCK0存儲(chǔ)區(qū)域
/***********************************************************************************************************
* 定義 SST單片機(jī)的各種IAP命令
***********************************************************************************************************/
#define SFCM_SE 0x0B; /* 扇區(qū)擦除命令字(Sector-Erase)為0X0B */
#define SFCM_VB 0x0C; /* 字節(jié)校驗(yàn)命令字(Byte-Verify)為0X0C */
#define SFCM_PB 0x0E; /* 字節(jié)校驗(yàn)命令字(Byte-Program)為0X0E */
/***********************************************************************************************************
* Function Prototype,用到的函數(shù)聲明
***********************************************************************************************************/
void Flash_sector_erase(unsigned short int dataAddr); //扇區(qū)擦除函數(shù),擦除的地址為dataAddr
void Flash_byte_program(unsigned short int dataAddr, unsigned char dataByte);//字節(jié)編程函數(shù)
bit modify_single_byte_flash(unsigned short int dataAddr,unsigned char dataByte);//修改一個(gè)FLASH地址單元的內(nèi)容
bit modify_multi_byte_flash(unsigned int Begin_Addr, unsigned char counter, unsigned int array[]);//修改多個(gè)FLASH地址單元的內(nèi)容
unsigned char Flash_byte_read(unsigned short int dataAddr); //字節(jié)校驗(yàn)函數(shù)
unsigned char ready(); //檢查是否擦除或編程的操作是否已經(jīng)完成
void error(); //超時(shí)錯(cuò)誤
/**************************** SST單片機(jī)的IAP函數(shù) **********************************************/
/***********************************************************************************************************
* 扇區(qū)擦除函數(shù)--Flash_sector_erase(unsigned short int dataAddr)
* 輸入?yún)?shù): dataAddr---擦除的扇區(qū)地址
***********************************************************************************************************/
void Flash_sector_erase(unsigned short int dataAddr)
{
unsigned short int Dest_Addr = dataAddr;
SFCF = SFCF | 0x40; // SFCF.6=1: IAP功能使能
SFAH = Dest_Addr>>8; // 將扇區(qū)地址的高8位裝入FLASH的高8位地址寄存器(SFAH)中
SFAL = Dest_Addr; // 將扇區(qū)地址的低8位裝入FLASH的低8位地址寄存器(SFAL)中
SFCM = SFCM_SE; // 在FLASH的命令寄存器(SFCM)中填入扇區(qū)擦除命令--SFCM_SE=0X0B
SFAL = Dest_Addr; // 將扇區(qū)地址的低8位裝入FLASH的低8位地址寄存器(SFAL)中
if(!ready()) // 等待擦除完畢
error(); // 等待超時(shí)--錯(cuò)誤
SFCF = SFCF & ~0x40; // SFCF.6=0: IAP功能禁止
return;
}
/***********************************************************************************************************
* 字節(jié)編程函數(shù)---Flash_byte_program()
* 輸入?yún)?shù): dataAddr---編程的字節(jié)地址
* 輸入?yún)?shù): dataByte---編程的數(shù)據(jù)
***********************************************************************************************************/
void Flash_byte_program(unsigned short int dataAddr, unsigned char dataByte)
{
unsigned short int Dest_Addr = dataAddr;
SFCF = SFCF | 0x40; // SFCF.6=1: IAP功能使能
SFAH = Dest_Addr>>8; // 將扇區(qū)地址的高8位裝入FLASH的高8位地址寄存器(SFAH)中
SFAL = Dest_Addr; // 將扇區(qū)地址的低8位裝入FLASH的低8位地址寄存器(SFAL)中
SFDT = dataByte; // 在FLASH的數(shù)據(jù)寄存器(SFDT)中填入編程的數(shù)據(jù)--dataByte
SFCM = SFCM_PB; // 在FLASH的命令寄存器(SFCM)中填入字節(jié)編程命令--SFCM_PB=0X0E
if(!ready()) // 等待編程完畢
error(); // 等待超時(shí)--錯(cuò)誤
SFCF = SFCF & ~0x40; // SFCF.6=0: IAP功能禁止
return;
}
/***********************************************************************************************************
* 字節(jié)校驗(yàn)讀函數(shù)---Flash_byte_read()
* 輸入?yún)?shù): dataAddr---校驗(yàn)讀的字節(jié)地址
* 返回參數(shù): readByte---讀出的單元數(shù)值
***********************************************************************************************************/
unsigned char Flash_byte_read(unsigned short int dataAddr)
{
unsigned short int Dest_Addr = dataAddr;
unsigned char readByte;
SFCF = SFCF | 0x40; // SFCF.6=1: IAP功能使能
SFAH = Dest_Addr>>8; // 將扇區(qū)地址的高8位裝入FLASH的高8位地址寄存器(SFAH)中
SFAL = Dest_Addr; // 將扇區(qū)地址的低8位裝入FLASH的低8位地址寄存器(SFAL)中
SFCM = SFCM_VB; // 在FLASH的命令寄存器(SFCM)中填入字節(jié)校驗(yàn)命令--SFCM_PB=0X0E
readByte = SFDT; // 取得讀到的單元數(shù)據(jù)
SFCF = SFCF & 0xBF; // SFCF.6=0: 關(guān)閉IAP功能
SFDT = 0;
return readByte; //返回讀到的數(shù)據(jù)
}
/***********************************************************************************************************
* 檢查IAP操作是否完成函數(shù)---ready()
* 輸入?yún)?shù): 無(wú)
* 返回參數(shù): 1--IAP操作(FLASH擦除或字節(jié)編程)完成成功標(biāo)志
* 0--IAP操作超時(shí)錯(cuò)誤退出
***********************************************************************************************************/
unsigned char ready()
{
unsigned int TimeOut = 0;
while (TimeOut < 10000) //要設(shè)的等待時(shí)間足夠長(zhǎng),否則有些芯片的擦除時(shí)間可能不夠,引起錯(cuò)誤的編程信息.
{
if ((SFST&4) == 0) //SFST.2=0:IAP操作完成
{
SFCF = SFCF & 0xBF; //IAP操作完成,關(guān)閉IAP功能--SFCF.6=0
SFDT = 0;
return 1; //返回成功標(biāo)志--1
}
TimeOut++;
}
SFCF = SFCF & 0xBF; //時(shí)間超時(shí),關(guān)閉IAP功能--SFCF.6=0
SFDT = 0; /*any value other than 0x55*/
return 0; //返回失敗標(biāo)志--0
}
/***********************************************************************************************************
* IAP操作失敗指示函數(shù),
***********************************************************************************************************/
void error()
{
//ErrorCode=1; //置IAP失敗標(biāo)志--ErrorCode=1
//LED_ERR=0; //點(diǎn)亮錯(cuò)誤燈,關(guān)閉成功燈,表示編程出錯(cuò)失敗.
//LED_OK=1;
while(1) //程序停止
{}
}
/***********************************************************************************************************
* 字節(jié)編程函數(shù)---modify_single_byte_flash()
* 輸入?yún)?shù): dataAddr---編程的字節(jié)地址
* 輸入?yún)?shù): dataByte---編程的數(shù)據(jù)
***********************************************************************************************************/
bit modify_single_byte_flash(unsigned int dataAddr, unsigned char dataByte)
{
unsigned int xdata Flash_addr; // = dataAddr+DATAFLASH_ADDR_START; //將FLASH的DATA存儲(chǔ)地址由原來(lái)的相對(duì)地址轉(zhuǎn)換為具體芯片的FLASH絕對(duì)地址
unsigned int xdata Addr_Sector; // = Dest_Addr & 0xff80; //要修改數(shù)據(jù)所站的扇區(qū)的起始地址
unsigned char xdata temp,counter=0x80; //作為計(jì)數(shù)器,一個(gè)扇區(qū)
unsigned char xdata Sector_Buffer[0x80]; //定義內(nèi)部擴(kuò)展RAM的0x80個(gè)單元作為一個(gè)扇區(qū)數(shù)據(jù)的緩沖區(qū)
#if SST89X5XRD //如果是SST89X52-58,BLOCK1在0XE000--0XFFFF區(qū)間
Flash_addr = dataAddr+0xe000; //且當(dāng)前的BOOT CODE處于BLOCK0,IAP編程的范圍只能在BLOCK1的0xe000-0xffff范圍內(nèi)
#else //如果是SST89X516/564,BLOCK1在0X1000--0X1FFF區(qū)間
Flash_addr = dataAddr+0x0000; //且當(dāng)前的BOOT CODE處于BLOCK0,IAP編程的范圍只能在BLOCK1的0x1000-0x1fff范圍內(nèi)
#endif
if(dataByte==(dataByte&(Flash_byte_read(Flash_addr)))) //如果要寫的單元原來(lái)內(nèi)容只需1->0的過(guò)程,而沒有0->1的過(guò)程,
{ //就不用擦除整個(gè)扇區(qū),而只需使用字節(jié)編程命令即可,減少FLASH的擦寫次數(shù),延長(zhǎng)FLASH的使用壽命
Flash_byte_program(Flash_addr,dataByte);
if (dataByte==Flash_byte_read(Flash_addr)) return 1; //讀出的數(shù)據(jù)等于要寫的數(shù)據(jù),返回1
else return 0; //讀出的數(shù)據(jù)不等于要寫的數(shù)據(jù),返回0
}
else //如果有0->1的過(guò)程,就必須進(jìn)行扇區(qū)擦除,將整個(gè)扇區(qū)的內(nèi)容,重新寫一遍.
temp = AUXR; //暫存AUXR輔助寄存器.以便用完128個(gè)RAM的BUFFER后恢復(fù).
AUXR = 0x00; //使用SST89E516內(nèi)部的768 RAM,EXRAM=0,
Addr_Sector = Flash_addr & 0xff80; //計(jì)算出要修改數(shù)據(jù)所站的扇區(qū)的起始地址
counter=0x80; //一個(gè)扇區(qū)有128個(gè)存儲(chǔ)單元,
for (counter=0;counter<0x80;counter++) //讀一個(gè)扇區(qū)(128個(gè)字節(jié))的內(nèi)容到擴(kuò)展RAM緩沖區(qū)中
{
Sector_Buffer[counter]=Flash_byte_read(Addr_Sector);
Addr_Sector++;
}
Sector_Buffer[Flash_addr&0x007f]=dataByte; //在RAM緩沖區(qū)中寫入新的修改后數(shù)據(jù)
Addr_Sector=Flash_addr&0xff80; //重新置要修改扇區(qū)的首地址
Flash_sector_erase(Addr_Sector); //將這個(gè)要修改單元所在的扇區(qū)進(jìn)行全部擦除
for (counter=0;counter<0x80;counter++) //將修改后的扇區(qū)內(nèi)容重新寫回到這個(gè)扇區(qū)內(nèi)
{
Flash_byte_program(Addr_Sector,Sector_Buffer[counter]); //對(duì)扇區(qū)中的單元寫入一個(gè)扇區(qū)更改后的內(nèi)容
Addr_Sector++; //指向下一個(gè)地址單元
}
AUXR = temp; //恢復(fù)為占用前的AUXR
if (dataByte==Flash_byte_read(Flash_addr)) return 1; //讀出的數(shù)據(jù)等于要寫的數(shù)據(jù),返回1
else return 0; //讀出的數(shù)據(jù)不等于要寫的數(shù)據(jù),返回0
}
/*-----------------------------------------------------------------------------------*/
/* 修改多個(gè)單元的Flash存儲(chǔ)器內(nèi)容, 只在同一個(gè)扇區(qū)內(nèi)寫,保留同一扇區(qū)中不需修改的數(shù)據(jù) */
/* Begin_Addr,被寫數(shù)據(jù)Flash開始地址;counter,連續(xù)寫多少個(gè)字節(jié); array[],數(shù)據(jù)來(lái)源 */
/*-----------------------------------------------------------------------------------*/
bit modify_multi_byte_flash(unsigned int Begin_Addr, unsigned char counter, unsigned int array[])
{
unsigned int xdata Dest_Addr,Flash_addr; // = dataAddr+DATAFLASH_ADDR_START; //將FLASH的DATA存儲(chǔ)地址由原來(lái)的相對(duì)地址轉(zhuǎn)換為具體芯片的FLASH絕對(duì)地址
unsigned int xdata Addr_Sector,Addr_Flash; // = Dest_Addr & 0xff80; //要修改數(shù)據(jù)所站的扇區(qū)的起始地址
unsigned char xdata temp,i;//,counter=0x80; //作為計(jì)數(shù)器,一個(gè)扇區(qū)
unsigned char xdata Sector_Buffer[0x80]; //定義內(nèi)部擴(kuò)展RAM的0x80個(gè)單元作為一個(gè)扇區(qū)數(shù)據(jù)的緩沖區(qū)
#if SST89X5XRD //如果是SST89X52-58,BLOCK1在0XE000--0XFFFF區(qū)間
Flash_addr = Begin_Addr+0xe000; //且當(dāng)前的BOOT CODE處于BLOCK0,IAP編程的范圍只能在BLOCK1的0xe000-0xffff范圍內(nèi)
#else //如果是SST89X516/564,BLOCK1在0X1000--0X1FFF區(qū)間
Flash_addr = Begin_Addr+0x0000; //且當(dāng)前的BOOT CODE處于BLOCK0,IAP編程的范圍只能在BLOCK1的0x1000-0x1fff范圍內(nèi)
#endif
if(counter > 0x80) return 0; //只允許最大是一個(gè)扇區(qū)(0x80=128個(gè)字節(jié))空間的數(shù)據(jù)修改
if((Flash_addr&0x007f+counter) > 0x80) return 0; //修改的起始地址+修改的個(gè)數(shù)也不能超過(guò)一個(gè)扇區(qū)(128字節(jié))的數(shù)目
temp = AUXR; //暫存AUXR輔助寄存器.以便用完128個(gè)RAM的BUFFER后恢復(fù).
AUXR = 0x00; //使用SST89E516內(nèi)部的768 RAM,EXRAM=0,
Addr_Sector = Flash_addr & 0xff80; //計(jì)算出要修改數(shù)據(jù)所站的扇區(qū)的起始地址
//--------------第1步:讀一個(gè)扇區(qū)(128個(gè)字節(jié))的內(nèi)容到擴(kuò)展RAM緩沖區(qū)中--------------
Addr_Flash=Flash_addr&0xff80; //置FLASH編程的地址指針
i=0x80; //一個(gè)扇區(qū)有128個(gè)存儲(chǔ)單元,
for (i=0;i<0x80;i++) //讀一個(gè)扇區(qū)(128個(gè)字節(jié))的內(nèi)容到擴(kuò)展RAM緩沖區(qū)中
{
Sector_Buffer[i]=Flash_byte_read(Addr_Flash);
Addr_Flash++;
}
//--------------第2步:將要修改的內(nèi)容寫入扇區(qū)緩沖區(qū)內(nèi),共修改COUNTER個(gè)--------------
Dest_Addr=Flash_addr&0x007f; //轉(zhuǎn)為一個(gè)扇區(qū)內(nèi)的相對(duì)地址(只取低7位)
for (i=0;i<counter;i++) //將要修改的內(nèi)容寫入扇區(qū)緩沖區(qū)內(nèi),共修改COUNTER個(gè)
{
Sector_Buffer[Dest_Addr]=array[i]; //將要修改的內(nèi)容寫入扇區(qū)緩沖區(qū)的對(duì)應(yīng)地址
Dest_Addr++; //指向下一個(gè)緩沖地址
}
//-------------第3步:擦除要修改地址所在的扇區(qū)---------------------------------------
Addr_Sector=Flash_addr&0xff80; //重新置要修改扇區(qū)的首地址
Flash_sector_erase(Addr_Sector); //將這個(gè)要修改單元所在的扇區(qū)進(jìn)行全部擦除
//-------------第4步:將修改后的緩沖區(qū)內(nèi)容重新寫回到FLASH中--------------------------
Addr_Flash=Flash_addr&0xff80; //置FLASH編程的地址指針
for (i=0;i<0x80;i++) //將修改后的扇區(qū)內(nèi)容重新寫回到這個(gè)扇區(qū)內(nèi)
{
Flash_byte_program(Addr_Flash,Sector_Buffer[i]); //對(duì)扇區(qū)中的單元寫入一個(gè)扇區(qū)更改后的內(nèi)容
if ((Flash_byte_read(Addr_Flash)) != Sector_Buffer[i]) //對(duì)剛寫入的FLASH單元進(jìn)行讀出校驗(yàn),
return 0; //如果不等于剛寫入的內(nèi)容,則錯(cuò)誤返回
Addr_Flash++; //校驗(yàn)正確,指向下一個(gè)FLASH地址單元,繼續(xù)FLASH編程
}
AUXR = temp; //恢復(fù)為占用前的AUXR
return 1; //整個(gè)扇區(qū)128個(gè)字節(jié)全部編程成功,返回1
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -