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

          新聞中心

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

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

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

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

          *本程序可以任意修改和傳播,修改者請(qǐng)注明修改人、修改時(shí)間,傳播過程請(qǐng)注*
          *明原著。不得用于任何商業(yè)目的。*
          **
          ********************************************************************************
          *FileName:EEPROM.C,V0.2.0*
          *Author:GuozhouChen*
          *Date:2007.09.15*
          **
          ********************************************************************************
          *使用數(shù)據(jù)類型說明:*
          *UINT:16位無符號(hào)整形*
          *BYTE:8位無符號(hào)字符型*
          *BOOL:1位布爾類型*
          **
          ********************************************************************************
          *直接調(diào)用的API說明:*
          **
          *讀函數(shù)原形:UINTEEPROM_ReadBytes(UINTaddr,BYTE*buf,UINTsize)*
          *函數(shù)返回為UINT類型的實(shí)際讀出數(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í)際寫入數(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í)際情況修改幾個(gè)宏定義和數(shù)據(jù)類型定義。宏定義和數(shù)據(jù)類*
          *型定義部分可以單獨(dú)寫成頭文件。*
          *2、在需要使用EEPROM_ReadBytes()和EEPROM_WritBytes()函數(shù)的文件中做個(gè)*
          *原形申明。*
          *3、在需要的地方直接添入實(shí)參調(diào)用即可。*
          **
          ********************************************************************************/

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

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

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

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

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

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


          /********************************************************************************
          **
          *從指定首地址為addr的EEPROM區(qū)域讀出size字節(jié)數(shù)據(jù)到buf指向的區(qū)域內(nèi),并返回實(shí)際讀*
          *出數(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{
          //地址越界檢測(cè)
          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地址所在的整個(gè)扇區(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),并返*
          *回實(shí)際拷貝的字節(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í)際寫入*
          *數(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)第一個(gè)單元不是0xff,要從新寫入數(shù)據(jù)需要做擦除整個(gè)扇區(qū)
          else
          {
          //擦除用作緩沖的這個(gè)扇區(qū)
          ErasureAllSector(EEPROM_ADDR_END);

          cur_sector_start_addr=addr&0xfe00;

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

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

          //把剩余要存儲(chǔ)的數(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));
          }

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

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

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

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


          評(píng)論


          技術(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); })();