- .C
- #include "eeprom.h"
- #include "STC15Fxxxx.H"
- //========================================================================
- // 函數: void ISP_Disable(void)
- // 描述: 禁止訪問ISP/IAP.
- // 參數: non.
- // 返回: non.
- // 版本: V1.0, 2022-05-28
- //========================================================================
- void DisableEEPROM(void)
- {
- ISP_CONTR = 0; //禁止ISP/IAP操作
- ISP_CMD = 0; //去除ISP/IAP命令
- ISP_TRIG = 0; //防止ISP/IAP命令誤觸發
-
- ISP_ADDRH = 0xff; //清0地址高字節
- ISP_ADDRL = 0xff; //清0地址低字節,指向非EEPROM區,防止誤操作
- }
- //========================================================================
- // 函數: void EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number)
- // 描述: 從指定EEPROM首地址讀出n個字節放指定的緩沖.
- // 參數: EE_address: 讀出EEPROM的首地址.
- // DataAddress: 讀出數據放緩沖的首地址.
- // number: 讀出的字節長度.
- // 返回: non.
- // 版本: V1.0, 2022-05-28
- //========================================================================
- void EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number)
- {
- ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //設置等待時間,允許ISP/IAP操作,送一次就夠
- ISP_READ(); //送字節讀命令,命令不需改變時,不需重新送命令
-
- do
- {
- ISP_ADDRH = EE_address / 256; //送地址高字節(地址需要改變時才需重新送地址)
- ISP_ADDRL = EE_address % 256; //送地址低字節
- _ISP_TRIG(); //先送5AH,再送A5H到ISP/IAP觸發寄存器,每次都需要如此
- //送完A5H后,ISP/IAP命令立即被觸發啟動
- //CPU等待IAP完成后,才會繼續執行程序。
- _nop_();
-
- *DataAddress = ISP_DATA; //讀出的數據送往
-
- EE_address++;
- DataAddress++;
- }while(--number);
-
-
- DisableEEPROM();
- }
- /******************** 扇區擦除函數 *****************/
- //========================================================================
- // 函數: void EEPROM_SectorErase(u16 EE_address)
- // 描述: 把指定地址的EEPROM扇區擦除.
- // 參數: EE_address: 要擦除的扇區EEPROM的地址.
- // 返回: non.
- // 版本: V1.0, 2022-05-28
- //========================================================================
- void EEPROM_SectorErase(u16 EE_address)
- {
- //只有扇區擦除,沒有字節擦除,512字節/扇區。
- //扇區中任意一個字節地址都是扇區地址。
- ISP_ADDRH = EE_address / 256; //送扇區地址高字節(地址需要改變時才需重新送地址)
- ISP_ADDRL = EE_address % 256; //送扇區地址低字節
-
- ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //設置等待時間,允許ISP/IAP操作,送一次就夠
-
- ISP_ERASE(); //送扇區擦除命令,命令不需改變時,不需重新送命令
-
- _ISP_TRIG(); //先送5AH,再送A5H到ISP/IAP觸發寄存器,每次都需要如此
- //送完A5H后,ISP/IAP命令立即被觸發啟動
-
- _nop_();
-
- DisableEEPROM();
- }
- //========================================================================
- // 函數: void EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number)
- // 描述: 把緩沖的n個字節寫入指定首地址的EEPROM.
- // 參數: EE_address: 寫入EEPROM的首地址.
- // DataAddress: 寫入源數據的緩沖的首地址.
- // number: 寫入的字節長度.
- // 返回: non.
- // 版本: V1.0, 2022-05-28
- //========================================================================
- void EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number)
- {
- ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //設置等待時間,允許ISP/IAP操作,送一次就夠
-
- ISP_WRITE(); //送字節寫命令,命令不需改變時,不需重新送命令
-
- do
- {
- ISP_ADDRH = EE_address / 256; //送地址高字節(地址需要改變時才需重新送地址)
- ISP_ADDRL = EE_address % 256; //送地址低字節
-
- ISP_DATA = *DataAddress; //送數據到ISP_DATA,只有數據改變時才需重新送
-
- _ISP_TRIG(); //先送5AH,再送A5H到ISP/IAP觸發寄存器,每次都需要如此
- //送完A5H后,ISP/IAP命令立即被觸發啟動
-
- _nop_();
-
- EE_address++;
- DataAddress++;
- }while(--number);
- DisableEEPROM();
- }
復制代碼
STC芯片的IAP版本:IAP15F2K61S2
使用官方IAP示例代碼測試,如代碼所示:
IAP15F2K61S2據說整片Flash都可以模擬EEPROM,地址:0x0000-0xF3FF(測試時需要避開程序空間,測試讀寫地址:0xF200)使用官方IAP示例代碼測試
測試:部分代碼
unsigned char EPR1[20]={0x20,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
寫:
EEPROM_SectorErase(0xF200); //擦除一個扇區
EEPROM_write_n(0xF200,EPR1,sizeof(EPR1)); //寫
讀:
EEPROM_read_n(0xF200,EPR1,sizeof(EPR1)); //讀出n字節,存放在EPR1數組內
uartWrite(EPR1,sizeof(EPR1));//串口發送
測試結果如圖:
問題:
1,代碼是使用IAP讀寫官方Demo修改,有沒有問題?
2,正常讀出來的數據為0x20,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,但是芯片運行一段時間后,Flash好像無法通過IAP程序再次讀寫了,即讀出來都是0x00,目測壞了,更換新的同型號芯片又沒有問題了(代碼均一致,只是換了新的芯片),但是或者有什么辦法修復一下?還是代碼哪里可以優化一下?又感覺沒壞,因為程序還在正常運行,只是沒辦法通過IAP讀寫Flash,來模擬EEPROM了
PS:正常與非正常的芯片,代碼運行均正常(因為串口發送0x15是用來測試IC的,由此得出芯片其實除了IAP,其他正常),讀寫次數最多也沒超過100次,地址均為0xF200,且沒有與程序區沖突,就壞了
沒有遇到過類似無法IAP讀寫的問題,分享一下!
|