找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 1810|回復(fù): 2
收起左側(cè)

STC單片機(jī)的EEPROM問題

[復(fù)制鏈接]
ID:740383 發(fā)表于 2022-10-5 11:44 | 顯示全部樓層 |閱讀模式
  1. .C


  2. #include "eeprom.h"

  3. #include        "STC15Fxxxx.H"





  4. //========================================================================
  5. // 函數(shù): void        ISP_Disable(void)
  6. // 描述: 禁止訪問ISP/IAP.
  7. // 參數(shù): non.
  8. // 返回: non.
  9. // 版本: V1.0, 2022-05-28
  10. //========================================================================
  11. void        DisableEEPROM(void)
  12. {
  13.         ISP_CONTR = 0;                        //禁止ISP/IAP操作
  14.         ISP_CMD   = 0;                        //去除ISP/IAP命令
  15.         ISP_TRIG  = 0;                        //防止ISP/IAP命令誤觸發(fā)
  16.         
  17.         ISP_ADDRH = 0xff;                //清0地址高字節(jié)
  18.         ISP_ADDRL = 0xff;                //清0地址低字節(jié),指向非EEPROM區(qū),防止誤操作
  19. }

  20. //========================================================================
  21. // 函數(shù): void EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number)
  22. // 描述: 從指定EEPROM首地址讀出n個(gè)字節(jié)放指定的緩沖.
  23. // 參數(shù): EE_address:  讀出EEPROM的首地址.
  24. //       DataAddress: 讀出數(shù)據(jù)放緩沖的首地址.
  25. //       number:      讀出的字節(jié)長度.
  26. // 返回: non.
  27. // 版本: V1.0, 2022-05-28
  28. //========================================================================

  29. void EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number)
  30. {
  31.         ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);        //設(shè)置等待時(shí)間,允許ISP/IAP操作,送一次就夠
  32.         ISP_READ();                                                                                        //送字節(jié)讀命令,命令不需改變時(shí),不需重新送命令
  33.         
  34.         do
  35.         {
  36.                 ISP_ADDRH = EE_address / 256;                          //送地址高字節(jié)(地址需要改變時(shí)才需重新送地址)
  37.                 ISP_ADDRL = EE_address % 256;                          //送地址低字節(jié)
  38.                 _ISP_TRIG();                                                                        //先送5AH,再送A5H到ISP/IAP觸發(fā)寄存器,每次都需要如此
  39.                                                                                                                 //送完A5H后,ISP/IAP命令立即被觸發(fā)啟動(dòng)
  40.                                                                                                                 //CPU等待IAP完成后,才會(huì)繼續(xù)執(zhí)行程序。
  41.                 _nop_();
  42.                
  43.                 *DataAddress = ISP_DATA;                                    //讀出的數(shù)據(jù)送往
  44.                
  45.                 EE_address++;
  46.                 DataAddress++;
  47.         }while(--number);
  48.         
  49.         
  50.         DisableEEPROM();
  51. }


  52. /******************** 扇區(qū)擦除函數(shù) *****************/
  53. //========================================================================
  54. // 函數(shù): void EEPROM_SectorErase(u16 EE_address)
  55. // 描述: 把指定地址的EEPROM扇區(qū)擦除.
  56. // 參數(shù): EE_address:  要擦除的扇區(qū)EEPROM的地址.
  57. // 返回: non.
  58. // 版本: V1.0, 2022-05-28
  59. //========================================================================
  60. void EEPROM_SectorErase(u16 EE_address)
  61. {
  62.                                                                                                                 //只有扇區(qū)擦除,沒有字節(jié)擦除,512字節(jié)/扇區(qū)。
  63.                                                                                                                 //扇區(qū)中任意一個(gè)字節(jié)地址都是扇區(qū)地址。
  64.         ISP_ADDRH = EE_address / 256;                                  //送扇區(qū)地址高字節(jié)(地址需要改變時(shí)才需重新送地址)
  65.         ISP_ADDRL = EE_address % 256;                                  //送扇區(qū)地址低字節(jié)
  66.         
  67.         ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);        //設(shè)置等待時(shí)間,允許ISP/IAP操作,送一次就夠
  68.         
  69.         ISP_ERASE();                                                                          //送扇區(qū)擦除命令,命令不需改變時(shí),不需重新送命令
  70.         
  71.         _ISP_TRIG();                                                                          //先送5AH,再送A5H到ISP/IAP觸發(fā)寄存器,每次都需要如此
  72.                                                                                                                 //送完A5H后,ISP/IAP命令立即被觸發(fā)啟動(dòng)
  73.         
  74.         _nop_();
  75.         
  76.         DisableEEPROM();
  77. }

  78. //========================================================================
  79. // 函數(shù): void EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number)
  80. // 描述: 把緩沖的n個(gè)字節(jié)寫入指定首地址的EEPROM.
  81. // 參數(shù): EE_address:  寫入EEPROM的首地址.
  82. //       DataAddress: 寫入源數(shù)據(jù)的緩沖的首地址.
  83. //       number:      寫入的字節(jié)長度.
  84. // 返回: non.
  85. // 版本: V1.0, 2022-05-28
  86. //========================================================================
  87. void EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number)
  88. {
  89.         ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY);        //設(shè)置等待時(shí)間,允許ISP/IAP操作,送一次就夠
  90.         
  91.         ISP_WRITE();                                                                          //送字節(jié)寫命令,命令不需改變時(shí),不需重新送命令
  92.         
  93.         do
  94.         {
  95.                 ISP_ADDRH = EE_address / 256;                          //送地址高字節(jié)(地址需要改變時(shí)才需重新送地址)
  96.                 ISP_ADDRL = EE_address % 256;                           //送地址低字節(jié)
  97.                
  98.                 ISP_DATA  = *DataAddress;                                    //送數(shù)據(jù)到ISP_DATA,只有數(shù)據(jù)改變時(shí)才需重新送
  99.                
  100.                 _ISP_TRIG();                                                                        //先送5AH,再送A5H到ISP/IAP觸發(fā)寄存器,每次都需要如此
  101.                                                                                                                 //送完A5H后,ISP/IAP命令立即被觸發(fā)啟動(dòng)
  102.                
  103.                 _nop_();
  104.                
  105.                 EE_address++;
  106.                 DataAddress++;
  107.         }while(--number);

  108.         DisableEEPROM();
  109. }
復(fù)制代碼


STC芯片的IAP版本:IAP15F2K61S2

使用官方IAP示例代碼測(cè)試,如代碼所示:

IAP15F2K61S2據(jù)說整片F(xiàn)lash都可以模擬EEPROM,地址:0x0000-0xF3FF(測(cè)試時(shí)需要避開程序空間,測(cè)試讀寫地址:0xF200)使用官方IAP示例代碼測(cè)試

測(cè)試:部分代碼

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);                //擦除一個(gè)扇區(qū)
EEPROM_write_n(0xF200,EPR1,sizeof(EPR1));  //寫

讀:
EEPROM_read_n(0xF200,EPR1,sizeof(EPR1));  //讀出n字節(jié),存放在EPR1數(shù)組內(nèi)
uartWrite(EPR1,sizeof(EPR1));//串口發(fā)送


測(cè)試結(jié)果如圖:

問題:
1,代碼是使用IAP讀寫官方Demo修改,有沒有問題?

2,正常讀出來的數(shù)據(jù)為0x20,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,但是芯片運(yùn)行一段時(shí)間后,F(xiàn)lash好像無法通過IAP程序再次讀寫了,即讀出來都是0x00,目測(cè)壞了,更換新的同型號(hào)芯片又沒有問題了(代碼均一致,只是換了新的芯片),但是或者有什么辦法修復(fù)一下?還是代碼哪里可以優(yōu)化一下?又感覺沒壞,因?yàn)槌绦蜻在正常運(yùn)行,只是沒辦法通過IAP讀寫Flash,來模擬EEPROM了


PS:正常與非正常的芯片,代碼運(yùn)行均正常(因?yàn)榇诎l(fā)送0x15是用來測(cè)試IC的,由此得出芯片其實(shí)除了IAP,其他正常),讀寫次數(shù)最多也沒超過100次,地址均為0xF200,且沒有與程序區(qū)沖突,就壞了


沒有遇到過類似無法IAP讀寫的問題,分享一下!


1正常.png
2非正常.png
回復(fù)

使用道具 舉報(bào)

ID:526108 發(fā)表于 2022-10-5 15:47 | 顯示全部樓層
http://www.torrancerestoration.com/bbs/dpj-223265-1.html
用這軟件生成通用型EEPROM函數(shù),簡(jiǎn)單明了
回復(fù)

使用道具 舉報(bào)

ID:213173 發(fā)表于 2022-10-5 16:56 | 顯示全部樓層
所有端口初始化為準(zhǔn)雙向口試試,以前用IAP15F4K58S4吃過苦頭。
        P0M0 = 0x00;
        P0M1 = 0x00;
        P1M0 = 0x00;
        P1M1 = 0x00;
        P2M0 = 0x00;
        P2M1 = 0x00;
        P3M0 = 0x00;
        P3M1 = 0x00;
        P4M0 = 0x00;
        P4M1 = 0x00;
        P5M0 = 0x00;
        P5M1 = 0x00;
        P6M0 = 0x00;
        P6M1 = 0x00;
        P7M0 = 0x00;
        P7M1 = 0x00;
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表