<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > STC89C5x系列單片機內(nèi)部EEPROM

          STC89C5x系列單片機內(nèi)部EEPROM

          作者: 時間:2016-11-11 來源:網(wǎng)絡(luò) 收藏
          //(c)Copyright2007-2017,GuozhouChen.AllRightsReserved.

          /********************************************************************************
          *個人申明:*
          *本人在運用STC89C5x系列單片機內(nèi)部EEPROM時,了解其對非0xff值的存儲空間*
          *不能通過字節(jié)編程直接寫入。這一約定可能給一些人帶來應(yīng)用的麻煩,所以本*
          *人決定編寫一能夠讓程序員不考慮這一約定的API。經(jīng)過幾個小時的編寫和調(diào)*
          *試,基本能達到本人原本設(shè)想的目標。由于時間倉促及個人水平有限,不免會*
          *有些算法低效,還望高手指教。Email:chenguozhou1982@yahoo.com.cn。*
          **
          *本程序通過改幾個宏定義可以運用到STC的很多型號MCU上,本人只測試了*
          *STC89C5x系列*

          *本程序可以任意修改和傳播,修改者請注明修改人、修改時間,傳播過程請注*
          *明原著。不得用于任何商業(yè)目的。*
          **
          ********************************************************************************
          *FileName:EEPROM.C,V0.2.0*
          *Author:GuozhouChen*
          *Date:2007.09.15*
          **
          ********************************************************************************
          *使用數(shù)據(jù)類型說明:*
          *UINT:16位無符號整形*
          *BYTE:8位無符號字符型*
          *BOOL:1位布爾類型*
          **
          ********************************************************************************
          *直接調(diào)用的API說明:*
          **
          *讀函數(shù)原形:UINTEEPROM_ReadBytes(UINTaddr,BYTE*buf,UINTsize)*
          *函數(shù)返回為UINT類型的實際讀出數(shù)據(jù)字節(jié)數(shù)。*
          *參數(shù)說明:addr為需要讀取EEPROM區(qū)域的第一字節(jié)地址,取值范圍為內(nèi)部*
          *EEPROM除最后一扇區(qū)外的地址,因最后一扇區(qū)被犧牲做為緩存。*
          *buf為目的數(shù)據(jù)區(qū)指針,即指向保存讀出數(shù)據(jù)區(qū)域的首地址。*
          *size為要求讀出數(shù)據(jù)的字節(jié)數(shù)*
          **
          *寫函數(shù)原形:UINTEEPROM_WritBytes(UINTaddr,BYTE*buf,UINTsize)*
          *函數(shù)返回為UINT類型的實際寫入數(shù)據(jù)字節(jié)數(shù)。*
          *參數(shù)說明:addr為需要寫入EEPROM區(qū)域的第一字節(jié)地址,取值范圍為內(nèi)部*
          *EEPROM除最后一扇區(qū)外的地址,因最后一扇區(qū)被犧牲做為緩存。*
          *buf為源數(shù)據(jù)區(qū)指針,即指向需要寫入數(shù)據(jù)區(qū)域的首地址。*
          *size為要求寫入數(shù)據(jù)的字節(jié)數(shù)*
          **
          ********************************************************************************
          *使用說明:*
          *1、根據(jù)MCU和編譯器的實際情況修改幾個宏定義和數(shù)據(jù)類型定義。宏定義和數(shù)據(jù)類*
          *型定義部分可以單獨寫成頭文件。*
          *2、在需要使用EEPROM_ReadBytes()和EEPROM_WritBytes()函數(shù)的文件中做個*
          *原形申明。*
          *3、在需要的地方直接添入實參調(diào)用即可。*
          **
          ********************************************************************************/

          /********************************************************************************
          **
          *頭文件*
          **
          ********************************************************************************/
          #include"STC89C5x.h"

          /********************************************************************************
          **
          *數(shù)據(jù)類型定義*
          **
          ********************************************************************************/
          typedefunsignedintUINT;
          typedefunsignedcharBYTE;
          typedefbitBOOL;

          /********************************************************************************
          **
          *宏定義*
          **
          ********************************************************************************/
          #defineBYTES_EACH_SECTOR512//MCUEEPROM每扇區(qū)的字節(jié)數(shù)

          //CPU等待時間,晶振0-5M設(shè)置為3,5-10M為2,10-20M為1,大于20M為0
          #defineWAIT_TIME0

          #defineUSEING_EACH_SECTOR512//計劃每扇區(qū)要用的字節(jié)數(shù),用量越小寫速度越快

          #defineEEPROM_ADDR_START0x2000//EEPROM起始地址
          #defineEEPROM_ADDR_END0x2fff//EEPROM結(jié)束地址


          /********************************************************************************
          **
          *從指定首地址為addr的EEPROM區(qū)域讀出size字節(jié)數(shù)據(jù)到buf指向的區(qū)域內(nèi),并返回實際讀*
          *出數(shù)據(jù)的字節(jié)數(shù)*
          **
          ********************************************************************************/

          UINTEEPROM_ReadBytes(UINTaddr,BYTE*buf,constUINTsize)
          {
          BOOLold_EA;

          BYTE*p_buf;
          UINTi,current_size;

          p_buf=buf;
          current_size=0;

          ISP_CMD=0x01;
          ISP_CONTR=0x80|WAIT_TIME;

          for(i=0;i{
          //地址越界檢測
          if((addrEEPROM_ADDR_END))
          {
          break;
          }

          ISP_ADDRH=addr>>8;
          ISP_ADDRL=addr&0x00ff;

          old_EA=EA;
          EA=0;

          ISP_TRIG=0x46;
          ISP_TRIG=0xB9;

          EA=old_EA;

          *p_buf=ISP_DATA;

          addr++;
          p_buf++;
          current_size++;

          }
          ISP_CMD=0x00;
          ISP_CONTR=0x00;

          returncurrent_size;
          }

          /********************************************************************************
          **
          *把buf指向單元內(nèi)的數(shù)據(jù)寫入地址為addr的EEPROM單元內(nèi),成功返回1,或則返回0*
          **
          ********************************************************************************/
          BOOLEEPROM_WritByte(UINTaddr,BYTE*buf)
          {
          BOOLold_EA;

          if((addrEEPROM_ADDR_END))
          {
          return0;
          }

          ISP_CMD=0x02;
          ISP_CONTR=0x80|WAIT_TIME;

          ISP_DATA=(*buf);

          ISP_ADDRH=addr>>8;
          ISP_ADDRL=addr&0x00ff;

          old_EA=EA;
          EA=0;

          ISP_TRIG=0x46;
          ISP_TRIG=0xB9;

          EA=old_EA;

          ISP_CMD=0x00;
          ISP_CONTR=0x00;

          return1;
          }

          /********************************************************************************
          **
          *擦除AddrInSector地址所在的整個扇區(qū)*
          **
          ********************************************************************************/
          voidErasureAllSector(UINTAddrInSector)
          {
          BOOLold_EA;

          ISP_CMD=0x03;
          ISP_CONTR=0x80|WAIT_TIME;

          ISP_ADDRH=AddrInSector>>8;
          ISP_ADDRL=AddrInSector&0x00ff;

          old_EA=EA;
          EA=0;

          ISP_TRIG=0x46;
          ISP_TRIG=0xB9;

          EA=old_EA;

          ISP_CMD=0x00;
          ISP_CONTR=0x00;
          }

          /********************************************************************************
          **
          *從首地址為src扇區(qū)單元拷貝連續(xù)size字節(jié)數(shù)據(jù)到首地址為des的連續(xù)扇區(qū)單元內(nèi),并返*
          *回實際拷貝的字節(jié)數(shù)*
          **
          ********************************************************************************/
          UINTCopySector(UINTsrc,UINTdes,constUINTsize)
          {
          BYTEtemp;
          UINTcurrent_size,i;

          current_size=0;

          for(i=0;i{
          if(!EEPROM_ReadBytes(src,&temp,1))
          {
          break;
          }

          if(!EEPROM_WritByte(des,&temp))
          {
          break;
          }

          des++;
          src++;
          current_size++;
          }

          returncurrent_size;
          }

          /********************************************************************************
          **
          *把buf指向區(qū)域內(nèi)的size字節(jié)數(shù)據(jù)寫入首地址為addr的EEPROM連續(xù)區(qū)域,并返回實際寫入*
          *數(shù)據(jù)的字節(jié)數(shù)*
          **
          ********************************************************************************/
          UINTEEPROM_WritBytes(UINTaddr,BYTE*buf,constUINTsize)
          {
          BYTE*p_buf,temp,move;

          UINTi,bufaddr,current_size,cur_sector_start_addr;

          p_buf=buf;

          move=0;
          current_size=0;

          for(i=0;i{
          if(!EEPROM_ReadBytes(addr,&temp,1))
          {
          break;
          }

          if(temp==0xff)
          {
          EEPROM_WritByte(addr,p_buf);
          }
          //發(fā)現(xiàn)第一個單元不是0xff,要從新寫入數(shù)據(jù)需要做擦除整個扇區(qū)
          else
          {
          //擦除用作緩沖的這個扇區(qū)
          ErasureAllSector(EEPROM_ADDR_END);

          cur_sector_start_addr=addr&0xfe00;

          //把第一個非0xff單元前的數(shù)據(jù)拷貝到緩沖扇區(qū)
          CopySector(cur_sector_start_addr
          ,(EEPROM_ADDR_END+1-BYTES_EACH_SECTOR)
          ,(addr-cur_sector_start_addr));

          //計算剩余需要存儲的數(shù)據(jù)需寫入緩沖扇區(qū)的首個單元地址
          bufaddr=(addr-cur_sector_start_addr)
          +(EEPROM_ADDR_END+1-BYTES_EACH_SECTOR);

          //把剩余要存儲的數(shù)據(jù)寫入緩沖扇區(qū)
          for(;i{
          EEPROM_WritByte(bufaddr,p_buf);

          addr++;
          bufaddr++;
          p_buf++;
          current_size++;
          }

          //把需要改變區(qū)域后的數(shù)據(jù)寫入緩沖扇區(qū)
          if(addr{
          CopySector(addr,bufaddr,USEING_EACH_SECTOR
          -(addr-cur_sector_start_addr));
          }

          //擦除當前扇區(qū)
          ErasureAllSector(cur_sector_start_addr);
          move=1;
          break;
          }

          addr++;
          p_buf++;
          current_size++;
          }

          if(move)
          {
          //把緩沖扇區(qū)數(shù)據(jù)拷貝到當前扇區(qū)
          CopySector((EEPROM_ADDR_END-BYTES_EACH_SECTOR+1)
          ,cur_sector_start_addr,USEING_EACH_SECTOR);
          }

          returncurrent_size;
          }
          /*****************************Nothingbelowthisline***************************/


          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();