STC單片機 IAP(EEPROM)的使用


STC89C51、52內部都自帶有2K字節的EEPROM,54、55和58都自帶有16K字節的EEPROM,STC單片機是利用IAP技術實現的EEPROM,內部Flash擦寫次數可達100,000 次以上,先來介紹下ISP與IAP的區別和特點。

知識點:ISP與IAP介紹
    ISP:In System Programable 是指在系統編程,通俗的講,就是片子已經焊板子上,不用取下,就可以簡單而方便地對其進行編程。比如我們通過電腦給STC單片機下載程序,或給AT89S51單片機下載程序,這就是利用了ISP技術。
IAP:In Application Programable 是指在應用編程,就是片子提供一系列的機制(硬件/軟件上的)當片子在運行程序的時候可以提供一種改變flash數據的方法。通俗點講,也就是說程序自己可以往程序存儲器里寫數據或修改程序。這種方式的典型應用就是用一小段代碼來實現程序的下載,實際上單片機的ISP功能就是通過IAP技術來實現的,即片子在出廠前就已經有一段小的boot程序在里面,片子上電后,開始運行這段程序,當檢測到上位機有下載要求時,便和上位機通信,然后下載數據到存儲區。大家要注意千萬不要嘗試去擦除這段ISP引導程序,否則恐怕以后再也下載不了程序了。
STC單片機內部有幾個專門的特殊功能寄存器負責管理ISP/IAP功能的,見表1。
表1 ISP/IAP相關寄存器列表
名稱 地址 功能描述 D7 D6 D5 D4 D3 D2 D1 D0 復位值
ISP_DATA E2h Flash數據寄存器                 1111 1111
ISP_ADDRH E3h Flash高字節地址寄存器                 0000 0000
ISP_ADDRL E4h Flash低字節地址寄存器                 0000 0000
ISP_CMD E5h Flash命令模式寄存器 -- -- -- -- -- MS2 MS1 MS0 xxxx x000
ISP_TRIG E6h Flash命令觸發寄存器                 xxxx xxxx
ISP_CONTR E7h ISP/IAP 控制寄存器 ISPEN SWBS SWRST -- -- WT2 WT1 WT0 000x x000
ISP_DATA:ISP/IAP操作時的數據寄存器。
ISP/IAP從Flash讀出的數據放在此處,向Flash寫入的數據也需放在此處。
ISP_ADDRH:ISP/IAP操作時的地址寄存器高八位。
ISP_ADDRL:ISP/IAP操作時的地址寄存器低八位。
ISP_CMD:ISP/IAP操作時的命令模式寄存器,須命令觸發寄存器觸發方可生效。命令模式如表2所示。
表2 ISP_CMD寄存器模式設置
D7 D6 D5 D4 D3 D2 D1 D0 模式選擇
保留 命令選擇  
-- -- -- -- -- 0 0 0 待機模式,無ISP操作
-- -- -- -- -- 0 0 1 對用戶的應用程序flash區及數據flash區字節讀
-- -- -- -- -- 0 1 0 對用戶的應用程序flash區及數據flash區字節編程
-- -- -- -- -- 0 1 1 對用戶的應用程序flash區及數據flash區扇區擦除
程序在系統ISP程序區時可以對用戶應用程序區/數據Flash區(EEPROM)進行字節讀/字節編程/扇區擦除;程序在用戶應用程序區時,僅可以對數據Flash區(EEPROM)進行字節讀/字節編程/扇區擦除。STC89C51RC/RD+系列單片機出廠時已經固化有ISP引導碼,並設置為上電復位進入ISP程序區,並且出廠時就已完全加密。
ISP_TRIG:ISP/IAP操作時的命令觸發寄存器。
在ISPEN(ISP_CONTR.7) =1時,對ISP_TRIG 先寫入46h,再寫入B9h,ISP/IAP命令才會生效。
STC89C52RC,STC89LE52RC單片機內部可用Data Flash(EEPROM)的地址如表3所示,其它型號單片機請查閱相關資料。
表3 STC89C52RC、STC89LE52RC單片機內部EEPROM地址表
第一扇區 第二扇區 第三扇區 第四扇區
起始地址 結束地址 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址
2000H 21FFH 2200H 23FFH 2400H 25FFH 2600H 27FFH
第五扇區 第六扇區 第七扇區 第八扇區
起始地址 結束地址 起始地址 結束地址 起始地址 結束地址 起始地址 結束地址
2800H 29FFH 2A00H 2BFFH 2C00H 2DFFH 2E00H 2FFFH
每個扇區為512字節,建議大家在寫程序時,將同一次修改的數據放在同一個扇區,方便修改,因為在執行擦除命令時,一次最少要擦除一個扇區的數據(需要提供扇區的首地址),每次在更新數據前都必須要擦除原數據方可重新寫入新數據,不能直接在原來數據基礎上更新內容。
     注意:上面的是數據存儲區的地址,程序存儲區地址是從0~1FFF,共8K,程序區只能是ISP編程。
 
以下是自己寫的這部分功能代碼,因為風格問題,不太喜歡原著代碼,感覺自己的還嚴謹一點。
 
 
/****************************************************************************/
/*                           IAP驅動                                        */
/****************************************************************************/
 
 
/************************************************************************************************************************/
/* ISP/IAP相關寄存器列表 */
/* 名稱 地址 功能描述 D7 D6 D5 D4 D3 D2 D1 D0 復位值 */
/* ISP_DATA E2h Flash數據寄存器 1111 1111 */
/* ISP_ADDRH E3h Flash高字節地址寄存器 0000 0000 */
/* ISP_ADDRL E4h Flash低字節地址寄存器 0000 0000 */
/* ISP_CMD E5h Flash命令模式寄存器 -- -- -- -- -- MS2 MS1 MS0 xxxx x000 */
/* ISP_TRIG E6h Flash命令觸發寄存器 xxxx xxxx */
/* ISP_CONTR E7h ISP/IAP 控制寄存器 ISPEN SWBS SWRST -- -- WT2 WT1 WT0 000x x000 */
/************************************************************************************************************************/
 
 
/************************************************************************************/
/*  ISP_CMD寄存器模式設置 */
/* D7 D6 D5 D4 D3 D2 D1 D0 模式選擇 */
/*  保留 命令選擇 */
/* -- -- -- -- -- 0 0 0 待機模式,無ISP操作 */
/* -- -- -- -- -- 0 0 1 對用戶的應用程序flash區及數據flash區字節讀 */
/* -- -- -- -- -- 0 1 0 對用戶的應用程序flash區及數據flash區字節編程 */
/* -- -- -- -- -- 0 1 1 對用戶的應用程序flash區及數據flash區扇區擦除 */
/************************************************************************************/
 
/*在ISPEN(ISP_CONTR.7) =1時,對ISP_TRIG 先寫入46h,再寫入B9h,ISP/IAP命令才會生效。*/
 
 
/* 定義常量 */
#define ERROR   0
#define OK      1
 
/* 定義Flash 操作等待時間 */
//#define WAIT_TIME   0x00      //mcu clock 40mhz
//#define WAIT_TIME   0x01      //mcu clock 20mhz
//#define WAIT_TIME   0x02      //mcu clock 10mhz
#define WAIT_TIME   0x03      //mcu clock 5mhz
 
sfr ISP_DATA = 0xe2;   // Flash數據寄存器
sfr ISP_ADDRH = 0xe3; // Flash高字節地址寄存器
sfr ISP_ADDRL = 0xe4; // Flash低字節地址寄存器
sfr ISP_CMD = 0xe5; // Flash命令模式寄存器
sfr ISP_TRIG = 0xe6; // Flash命令觸發寄存器
sfr ISP_CONTR = 0xe7; // ISP/IAP 控制寄存器
 
#define CMD_READ  0x01  // 定義IAP的讀字節操作
#define CMD_PRGM  0x02 // 定義IAP的寫字節操作
#define CMD_ERASE  0x03  // 定義IAP的擦除扇區操作
 
/*********************** 打開 ISP,IAP 功能 ***********************/
static void ISPIAPEnable(void)
{
  //EA  = 0;        // 關中斷
  ISP_CONTR  = ISP_CONTR & 0x18;        // 0001,1000
  ISP_CONTR  = ISP_CONTR | WAIT_TIME;  // 寫入硬件延時
  ISP_CONTR  = ISP_CONTR | 0x80;        // ISPEN = 1
}
 
 
/*********************** 關閉 ISP,IAP 功能 ***********************/
static void ISPIAPDisable(void)
{
  ISP_CONTR  = ISP_CONTR & 0x7f;  // ISPEN = 0
  ISP_TRIG  = 0x00;
  //EA    = 1;    // 開中斷
}
 
/************************* 觸發Flash操作 *************************/
static ActiveOperate(void)
{
  bit eacpy;
  eacpy = EA;
  EA = 0;
  ISPIAPEnable();
  ISP_TRIG = 0x46;   // 觸發ISP_IAP命令字節1
  ISP_TRIG = 0xb9;   // 觸發ISP_IAP命令字節2
  {UINT8 i=2; while(i--);}
  ISPIAPDisable();
  EA = eacpy;
}
 
 
/**************************** 讀一字節 ****************************/
static UINT8 IAPReadByte(const UINT16 uiAddr)
{
  ISP_ADDRH  = (UINT8)(uiAddr >> 8); // 寫地址
  ISP_ADDRL  = (UINT8)(uiAddr&0xFF);
  ISP_CMD    = ISP_CMD & 0xf8; // 清低三位
  ISP_CMD    = ISP_CMD | CMD_READ;  // 寫入讀命令
 
  ActiveOperate(); // 觸發執行
  return (ISP_DATA);     // 返回讀到的數據
}
 
/**************************** 寫一字節 ****************************/
static void IAPWriteByte(const UINT16 uiAddr, const UINT8 ucData)
{
  ISP_ADDRH  = (UINT8)(uiAddr >> 8); // 寫地址
  ISP_ADDRL  = (UINT8)(uiAddr&0xFF);
  ISP_CMD    = ISP_CMD & 0xf8; // 清低三位
  ISP_CMD    = ISP_CMD | CMD_PRGM;  // 寫入寫命令
  ISP_DATA  = ucData;    // 寫入數據准備
 
  ActiveOperate(); // 觸發執行
}
 
/**************************** 擦除一扇區 ****************************/
static void IAPEarseSection(const UINT16 uiAddr)
{
  UINT16 uiSecAddr;
 
  uiSecAddr  = (uiAddr & 0xfe00);  // 取扇區地址
  ISP_ADDRH  = (UINT8)(uiSecAddr >> 8); // 寫地址
  ISP_ADDRL  = 0x00;
  ISP_CMD  = ISP_CMD & 0xf8;    // 清低三位
  ISP_CMD  = ISP_CMD | CMD_ERASE;  // 寫入擦除命令
 
  ActiveOperate(); // 觸發執行
}
 
 
------------------------------------------------------------------------------------------------------------------------
 
 

#include<stc12c5410ad.h>//到宏晶網站下載頭文件或自己在現有的頭文件上加上相應的寄存器定義即可。
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
         
/****************uart init***********/
void UART_inti(void)
{
AUXR=0x40;//定時器1速度是普通8051的12倍,不分頻
TMOD=0x20;//定時器1工作在方式2,用來產生波特率
SCON=0x50;//串口工作在方式1,允許接收
TL1=0xF7;//波特率為38400;FB為115200
TH1=0xF7;
PCON=0x00;//SMOD=0
TR1=1;   //產生波特率 
}

void ISP_write(uint ISP_addr,uchar ISP_data)//stc12c5404啟始地址2800h ;IAP_CMD 1讀,2寫,3擦除
{
ISP_DATA=ISP_data; //送數據
ISP_ADDRL=ISP_addr%256;
ISP_ADDRH=ISP_addr/256;//送高低地址
ISP_CONTR=0x83;//IAP ENABLE ,SET CPU WAIT TIME
ISP_CMD=2;//寫字節模式
ISP_TRIG=0x46;
ISP_TRIG=0xB9;//觸發啟動ISP
_nop_();//等待寫入
ISP_CONTR=0x00;//禁止ISP/IAp操作
ISP_CMD=0;
ISP_TRIG=0x00;
}

uchar ISP_read(uint ISP_addr)//stc12c5404啟始地址2800h ;IAP_CMD 1讀,2寫,3擦除
{uchar recivedata;
ISP_ADDRL=ISP_addr%256;
ISP_ADDRH=ISP_addr/256;//送高低地址
ISP_CONTR=0x83;//IAP ENABLE ,SET CPU WAIT TIME
ISP_CMD=1;//寫字節模式
ISP_TRIG=0x46;
ISP_TRIG=0xB9;//觸發啟動ISP
_nop_();//等待讀
recivedata=ISP_DATA;
ISP_CONTR=0x00;//禁止ISP/IAp操作
ISP_CMD=0;
ISP_TRIG=0x00;
return recivedata;
}

void ISP_erase(uint ISP_addr)//stc12c5404啟始地址2800h ;IAP_CMD 1讀,2寫,3擦除
{ISP_ADDRL=ISP_addr%256;
ISP_ADDRH=ISP_addr/256;//送高低地址
ISP_CONTR=0x83;//IAP ENABLE ,SET CPU WAIT TIME
ISP_CMD=3;//寫字節模式
ISP_TRIG=0x46;
ISP_TRIG=0xB9;//觸發啟動ISP
_nop_();//等待擦除
ISP_CONTR=0x00;//禁止ISP/IAp操作
ISP_CMD=0;
ISP_TRIG=0x00;
}


//主程序只為測試時隨意編寫的,可以根據需要做相應的修改即可。
void main(void)
{
uchar returndata;
uint textdata=0x2660;
UART_inti();
while(1)
{SBUF=5;
while(!TI);
TI=0;
while(!RI);
RI=0;
ISP_erase(0x2800);
ISP_write(0x2800,textdata%256);
ISP_write(0x2801,textdata/256);
returndata=ISP_read(0x2800);
SBUF=returndata;       
while(!TI);
TI=0;
returndata=ISP_read(0x2801);
SBUF=returndata;
while(!TI);
TI=0;
}

}

//聲明下這是應用在STC的單片機中的。不同的型號地址不一樣,改下IAP的地址即可。新出的產品像STC12C5A60S2等,觸發的命令也不一樣ISP_TRIG=0x46;ISP_TRIG=0xB9;也就是這兩條要根據手冊修改下即可。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM