<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > STC單片機內部EEPROM的應用

STC單片機內部EEPROM的應用

作者: 時(shí)間:2016-11-13 來(lái)源:網(wǎng)絡(luò ) 收藏
單片機運行時(shí)的數據都存在于RAM(隨機存儲器)中,在掉電后RAM中的數據是無(wú)法保留的,那么怎樣使數據在掉電后不丟失呢?這就需要使用EEPROM或FLASHROM等存儲器來(lái)實(shí)現。在傳統的單片機系統中,一般是在片外擴展存儲器,單片機與存儲器之間通過(guò)IIC或SPI等接口來(lái)進(jìn)行數據通信。這樣不光會(huì )增加開(kāi)發(fā)成本,同時(shí)在程序開(kāi)發(fā)上也要花更多的心思。在STC單片機中內置了EEPROM(其實(shí)是采用IAP技術(shù)讀寫(xiě)內部FLASH來(lái)實(shí)現EEPROM),這樣就節省了片外資源,使用起來(lái)也更加方便。下面就詳細介紹STC單片機內置EEPROM及其使用方法。

STC各型號單片機內置的EEPROM的容量各有不同,見(jiàn)下表:

本文引用地址:http://dyxdggzs.com/article/201611/316202.htm

單片機芯片型號

起始地址

內置EEPROM容量(每扇區512字節)

STC89C51RC,STC89LE51RC

0x2000

共八個(gè)扇區

STC89C52RC,STC89LE52RC

0x2000

共八個(gè)扇區

STC89C54RD+,STC89LE54RD+

0x8000

共五十八個(gè)扇區

STC89C55RD+,STC89LE55RD+

0x8000

共五十八個(gè)扇區

STC89C58RD+,STC89LE58RD+

0x8000

共五十八個(gè)扇區

內部EEPROM可以擦寫(xiě)100000次以上)

上面提到了IAP,它的意思是“在應用編程”,即在程序運行時(shí)程序存儲器可由程序自身進(jìn)行擦寫(xiě)。正是是因為有了IAP,從而可以使單片機可以將數據寫(xiě)入到程序存儲器中,使得數據如同燒入的程序一樣,掉電不丟失。當然寫(xiě)入數據的區域與程序存儲區要分開(kāi)來(lái),以使程序不會(huì )遭到破壞。

要使用IAP功能,與以下幾個(gè)特殊功能寄存器相關(guān):

寄存器標識

地址

名稱(chēng)

7

6

5

4

3

2

1

0

初始值

ISP_DATA

0xE2

ISP/IAP閃存數據寄存器

11111111

ISP_ADDRH

0xE3

ISP/IAP閃存地址高位

00000000

ISP_ADDRL

0xE4

ISP/IAP閃存地址低位

00000000

ISP_CMD

0xE5

ISP/IAP閃存命令寄存器

-

-

-

-

-

MS2

MS1

MS0

xxxxx000

ISP_TRIG

0xE6

ISP/IAP閃存命令觸發(fā)

xxxxxxxx

ISP_CONTR

0xE7

ISP/IAP控制寄存器

ISPEN

SWBS

SWRST

-

-

WT2

WT1

WT0

00xx000

ISP_DATA: ISP/IAP操作時(shí)的數據寄存器。

ISP/IAP從Flash讀出的數據放在此處,向Flash寫(xiě)的數據也需放在此處

ISP_ADDRH:ISP/IAP操作時(shí)的地址寄存器高八位。

ISP_ADDRL:ISP/IAP操作時(shí)的地址寄存器低八位。

ISP_CMD: ISP/IAP操作時(shí)的命令模式寄存器,須命令觸發(fā)寄存器觸發(fā)方可生效。

B7

B6

B5

B4

B3

B2

B1

B0

命令/操作模式選擇

保留

命令選擇

0

0

0

待機模式,無(wú)ISP/IAP操作

0

0

1

對用戶(hù)的應用程序Flash區及數據Flash區字節讀

0

1

0

對用戶(hù)的應用程序Flash區及數據Flash區字節編程

0

1

1

對用戶(hù)的應用程序Flash區及數據Flash區扇區擦除

ISP_TRIG:ISP/IAP操作時(shí)的命令觸發(fā)寄存器。

當ISPEN(ISP_CONTR.7)=1時(shí),對ISP_TRIG先寫(xiě)入0x46,再寫(xiě)入0xb9,ISP/IAP命令才會(huì )生效。

ISP_CONTR:ISP/IAP控制寄存器。

D7

D6

D5

D4

D3

D2

D1

D0

ISPEN

SWBS

SWRST

WT2

WT1

WT0

ISPEN:ISP/IAP功能允許位。0:禁止ISP/IAP編程改變Flash,1:允許編程改變Flash

SWBS:軟件選擇從用戶(hù)主程序區啟動(dòng)(0),還是從ISP程序區啟動(dòng)(1)。

SWRST:0:不操作,1:產(chǎn)生軟件系統復位,硬件自動(dòng)清零。

ISP_CONTR中的SWBS與SWRST這兩個(gè)功能位,可以實(shí)現單片機的軟件啟動(dòng),并啟動(dòng)到ISP區或用戶(hù)程序區,這在“STC單片機自動(dòng)下載”一節,亦有所應用。

如:

ISP_CONTR=0x60; 則可以實(shí)現從用戶(hù)應用程序區軟件復位到ISP程序區開(kāi)始運行程序。

ISP_CONTR=0x20; 則可以實(shí)現從ISP程序區軟件復位到用戶(hù)應用程序區開(kāi)始運行程序。

用IAP向Flash中讀寫(xiě)數據,是需要一定的讀寫(xiě)時(shí)間的,讀寫(xiě)數據命令發(fā)出后,要等待一段時(shí)間才可以讀寫(xiě)成功。這個(gè)等待時(shí)間就是由WT2、WT1、WT0與晶體振蕩器頻率決定的。

設置等待時(shí)間

CPU等待時(shí)間(機器周期)

WT2

WT1

WT0

讀取

編程

扇區擦除

建議的系統時(shí)鐘

0

1

1

6

30

5471

5MHz

0

1

0

11

60

10942

10MHz

0

0

1

22

120

21885

20MHz

0

0

0

43

240

43769

40MHz

(以上的建議時(shí)鐘是(WT2、WT1、WT0)取不同的值時(shí)的標稱(chēng)時(shí)鐘,用戶(hù)系統中的時(shí)鐘不要過(guò)高,否則可能使操作不穩定。)

以下是具體的實(shí)現代碼:

EEPROM操作函數:

#define RdCommand 0x01

#define PrgCommand 0x02

#define EraseCommand 0x03

#define Error 1

#define Ok 0

#define WaitTime 0x01

#define PerSector 512

unsignedchar xdata Ttotal[512];

/*

---------------------------------------------------------------------

打開(kāi) ISP,IAP功能

---------------------------------------------------------------------

*/

voidISP_IAP_enable(void)

{

EA=0;/*關(guān)中斷*/

ISP_CONTR|=0x18;/*0001,1000*/

ISP_CONTR|=WaitTime;/*寫(xiě)入硬件延時(shí)*/

ISP_CONTR|=0x80;/*ISPEN=1*/

}

/*

---------------------------------------------------------------------

關(guān)閉 ISP,IAP功能

---------------------------------------------------------------------

*/

voidISP_IAP_disable(void)

{

ISP_CONTR&=0x7f;/* ISPEN = 0 */

ISP_TRIG=0x00;

EA=1;/*開(kāi)中斷 */

}

/*

----------------------------------------------------------------------

公用的觸發(fā)代碼

----------------------------------------------------------------------

*/

voidISPgoon(void)

{

ISP_IAP_enable();/*打開(kāi) ISP,IAP功能 */

ISP_TRIG=0x46;/*觸發(fā)ISP_IAP命令字節1 */

ISP_TRIG=0xb9;/*觸發(fā)ISP_IAP命令字節2 */

_nop_();

}

/*

-----------------------------------------------------------------------

字節讀

-----------------------------------------------------------------------

*/

unsignedchar byte_read(unsigned int byte_addr)

{

ISP_ADDRH=(unsigned char)(byte_addr>>8); /*地址賦值*/

ISP_ADDRL=(unsigned char)(byte_addr&0x00ff);

ISP_CMD&=0xf8; /*清除低3位 */

ISP_CMD|=RdCommand;/*寫(xiě)入讀命令*/

ISPgoon();/*觸發(fā)執行*/

ISP_IAP_disable();/*關(guān)閉ISP,IAP功能*/

return ISP_DATA;/*返回讀到的數據*/

}

/*

------------------------------------------------------------------------

扇區擦除

------------------------------------------------------------------------

*/

voidsectorerase(unsigned int sector_addr)

{

unsigned int iSectorAddr;

iSectorAddr=(sector_addr&0xfe00);/*取扇區地址*/

ISP_ADDRH=(unsigned char)(iSectorAddr>>8);

ISP_ADDRL=0x00;

ISP_CMD&=0xf8;/*清空低3位*/

ISP_CMD|=EraseCommand;/*擦除命令3*/

ISPgoon();/*觸發(fā)執行 */

ISP_IAP_disable();/*關(guān)閉ISP,IAP功能*/

}

/*

-------------------------------------------------------------------------------------

字節寫(xiě)

-------------------------------------------------------------------------------------

*/

voidbyte_write(unsigned int byte_addr, unsigned char original_data)

{

ISP_ADDRH=(unsigned char)(byte_addr>>8); /*取地址*/

ISP_ADDRL=(unsigned char)(byte_addr & 0x00ff);

ISP_CMD&=0xf8;/*清低3位*/

ISP_CMD|=PrgCommand;/*寫(xiě)命令2*/

ISP_DATA=original_data;/*寫(xiě)入數據準備*/

ISPgoon();/*觸發(fā)執行*/

ISP_IAP_disable();/*關(guān)閉IAP功能*/

}

/*

-----------------------------------------------------------------

字節寫(xiě)并校驗

-----------------------------------------------------------------

*/

unsignedchar byte_write_verify(unsigned int byte_addr, unsigned char original_data)

{

ISP_ADDRH=(unsigned char)(byte_addr>>8); /*取地址*/

ISP_ADDRL=(unsigned char)(byte_addr&0xff);

ISP_CMD&=0xf8;/*清低3位*/

ISP_CMD|=PrgCommand;/*寫(xiě)命令2*/

ISP_DATA=original_data;

ISPgoon();/*觸發(fā)執行*/

/*開(kāi)始讀,沒(méi)有在此重復給地址,地址不會(huì )被自動(dòng)改變*/

ISP_DATA=0x00;/*清數據傳遞寄存器*/

ISP_CMD&=0xf8;/*清低3位*/

ISP_CMD|=RdCommand;/*讀命令1*/

ISP_TRIG=0x46;/*觸發(fā)ISP_IAP命令字節1 */

ISP_TRIG=0xb9;/*觸發(fā)ISP_IAP命令字節2 */

_nop_();/*延時(shí)*/

ISP_IAP_disable();/*關(guān)閉IAP功能*/

if(ISP_DATA==original_data)/*讀寫(xiě)數據校驗*/

return Ok;/*返回校驗結果*/

else

return Error;

}

/*

--------------------------------------------------------------------------

數組寫(xiě)入

--------------------------------------------------------------------------

*/

unsignedchar arraywrite(unsigned int begin_addr, unsigned int len, unsigned char *array)

{

unsigned int i;

unsigned int in_addr;

/*判是否是有效范圍,此函數不允許跨扇區操作 */

if(len > PerSector)

return Error;

in_addr = begin_addr & 0x01ff;/*扇區內偏移量 */

if((in_addr+len)>PerSector)

return Error;

in_addr = begin_addr;

/*逐個(gè)寫(xiě)入并校對 */

ISP_IAP_enable();/*打開(kāi)IAP功能 */

for(i=0;i

{

/*寫(xiě)一個(gè)字節 */

ISP_ADDRH=(unsigned char)(in_addr >> 8);

ISP_ADDRL=(unsigned char)(in_addr & 0x00ff);

ISP_DATA=array[i]; /*取數據 */

ISP_CMD&=0xf8;/*清低3位 */

ISP_CMD|=PrgCommand;/*寫(xiě)命令2 */

ISP_TRIG=0x46;/*觸發(fā)ISP_IAP命令字節1 */

ISP_TRIG=0xb9;/*觸發(fā)ISP_IAP命令字節2 */

_nop_();

/*讀回來(lái) */

ISP_DATA=0x00;

ISP_CMD&=0xf8;/*清低3位*/

ISP_CMD|=RdCommand;/*讀命令1*/

ISP_TRIG=0x46;/*觸發(fā)ISP_IAP命令字節1 */

ISP_TRIG=0xb9;/*觸發(fā)ISP_IAP命令字節2 */

_nop_();

/*比較對錯 */

if(ISP_DATA!=array[i])

{

ISP_IAP_disable();

return Error;

}

in_addr++;/*指向下一個(gè)字節*/

}

ISP_IAP_disable();

return Ok;

}

/*

-----------------------------------------------------------------------------

扇區讀出

-----------------------------------------------------------------------------

*/

/*程序對地址沒(méi)有作有效性判斷,請調用前事先保證他在規定范圍內 */

voidarrayread(unsigned int begin_addr, unsigned char len)

{

unsigned int iSectorAddr;

unsigned int i;

iSectorAddr = begin_addr; // & 0xfe00; /*取扇區地址*/

ISP_IAP_enable();

for(i=0;i

{

ISP_ADDRH=(unsigned char)(iSectorAddr>>8);

ISP_ADDRL=(unsigned char)(iSectorAddr & 0x00ff);

ISP_CMD&=0xf8;/*清低3位*/

ISP_CMD|=RdCommand;/*讀命令1*/

ISP_DATA=0;

ISP_TRIG=0x46;/*觸發(fā)ISP_IAP命令字節1 */

ISP_TRIG=0xb9;/*觸發(fā)ISP_IAP命令字節2 */

_nop_();

Ttotal[i]=ISP_DATA;

iSectorAddr++;

}

ISP_IAP_disable();/*關(guān)閉IAP功能*/

}

主函數對EEPROM操作函數進(jìn)行調用:

#include c51rd.h>

#include

#include

#include

inti;

voiddelay(unsigned int time)

{

while(time--);

}

voidmain()

{

_ADOS(22.1184);

//ADOS自動(dòng)下載

//for(i=0;i<100;i++)

//{

//Ttotal[i]=i;

//}

//arraywrite(0x8000,100,Ttotal);

/*

第一次運行時(shí)向EEPROM中寫(xiě)入數據

然后再將寫(xiě)入函數注釋掉,將先前寫(xiě)

入的數據讀出,輸出在P2口上。

*/

arrayread(0x8000,100);

for(i=0;i<100;i++)

{

P2=~Ttotal[i];

delay(10000);

}

while(1);

}



關(guān)鍵詞: STC單片機內部EEPRO

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>