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

QQ登錄

只需一步,快速開始

搜索
查看: 8111|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

STC8G單片機(jī)的片上EEPROM程序

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:162691 發(fā)表于 2021-3-20 16:04 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
本帖最后由 407871699 于 2021-3-20 16:40 編輯

最近研究了STC8G的片上EEPROM,比片外ROM方便多了。
但剛開始使用STC官網(wǎng)下載的例程時(shí)候老報(bào)錯(cuò),還是不熟悉啊。
然后和官方的手冊(cè)上的例程比較:手冊(cè)提供了3個(gè)函數(shù),寫1個(gè)字節(jié)函數(shù)void IapProgramByte(WORD addr, BYTE dat),讀1個(gè)字節(jié)函數(shù)BYTE IapReadByte(WORD addr),擦除扇區(qū)函數(shù)void IapEraseSector(WORD addr)。   手冊(cè)上這3個(gè)函數(shù)不方便與主函數(shù)進(jìn)行數(shù)據(jù)交換,還要在編數(shù)據(jù)交換函數(shù);因此結(jié)合手冊(cè)例程,把官網(wǎng)下載的EEPROM例程改動(dòng)了一下,編成EEPROM.H,就可以直接調(diào)用
片上EEPROM寫入時(shí),重點(diǎn)是必須先用扇區(qū)擦除,否則寫入的數(shù)值錯(cuò)誤。

單片機(jī)源程序如下:
#include<STC8xxxx.h>      //建議到官網(wǎng)下載,則包含sfr IAP_TPS = 0xF5;
//sfr  IAP_TPS = 0xF5;         //這個(gè)是STC8新增的寄存器,按CPU頻率計(jì)算等待時(shí)間
#define  EEPROM_ADD_0  0x0000           //EROM ADDRESS  起始地址,大家可以根據(jù)需要改存儲(chǔ)位置,但是要符合MCU手冊(cè)
#define  MAIN_Fosc                11059200L        //定義MCU頻率;這句可以放在初始化配置中或主程序中
#define  IAP_EN          (1<<7)                   //啟動(dòng)IAP;等價(jià)于IAP_EN=0X80;
#define  IAP_ENABLE()        IAP_CONTR = IAP_EN; IAP_TPS = MAIN_Fosc / 1000000   //使能+等待


void        DisableEEPROM(void)                //禁止IAP操作
{
        IAP_CONTR = 0;                //禁止IAP操作
        IAP_CMD   = 0;                //去除IAP命令
        IAP_TRIG  = 0;                //防止IAP命令誤觸發(fā)
        IAP_ADDRH = 0xff;        //清0地址高字節(jié)
        IAP_ADDRL = 0xff;        //清0地址低字節(jié),指向非EEPROM區(qū),防止誤操作
}


void EEPROM_Trig(void)   //觸發(fā)EEPROM
{
        F0 = EA;    //保存全局中斷
        EA = 0;     //禁止中斷, 避免觸發(fā)命令無效
        IAP_TRIG = 0x5A; //先送5AH,再送A5H到IAP觸發(fā)寄存器,每次都需要如此
        IAP_TRIG = 0xA5; //送完A5H后,IAP命令立即被觸發(fā)啟動(dòng)//CPU等待IAP完成后,才會(huì)繼續(xù)執(zhí)行程序。
        _nop_();        _nop_();     //2個(gè)空指令等待一下
        EA = F0;    //恢復(fù)全局中斷
}

// 參數(shù): EE_address:  讀取EEPROM的首地址.
//       DataAddress: 讀取數(shù)據(jù)后給到 數(shù)組首地址.
//       number:      讀取的字節(jié)長度.
void EEPROM_read_n(unsigned int EE_address,unsigned char *DataAddress,unsigned int number)      
{
IAP_ENABLE();             //設(shè)置等待時(shí)間,允許IAP操作,送一次就夠
IAP_CMD = 1;              //=1讀;送字節(jié)讀命令,命令不需改變時(shí),不需重新送命令
do
  {
        IAP_ADDRH = EE_address / 256;  //送地址高字節(jié)(地址需要改變時(shí)才需重新送地址)
        IAP_ADDRL = EE_address % 256;       //送地址低字節(jié)
        EEPROM_Trig();                      //觸發(fā)EEPROM操作
        *DataAddress = IAP_DATA;            //讀出的數(shù)據(jù)送往
        EE_address++;
        DataAddress++;
  }while(--number);
DisableEEPROM();
}
void EEPROM_SectorErase(unsigned int EE_address)
{
        IAP_ENABLE();  //設(shè)置等待時(shí)間,允許IAP操作,送一次就夠
        IAP_CMD = 3;   //宏調(diào)用, =3,送扇區(qū)擦除命令,命令不需改變時(shí),不需重新送命令
                        //只有扇區(qū)擦除,沒有字節(jié)擦除,512字節(jié)/扇區(qū)。
                        //扇區(qū)中任意一個(gè)字節(jié)地址都是扇區(qū)地址。
        IAP_ADDRH = EE_address / 256; //送扇區(qū)地址高字節(jié)(地址需要改變時(shí)才需重新送地址)
        IAP_ADDRL = EE_address % 256;  //送扇區(qū)地址低字節(jié)
        EEPROM_Trig();                 //觸發(fā)EEPROM操作
        DisableEEPROM();               //禁止EEPROM操作
}

// 參數(shù): EE_address:  寫入EEPROM的首地址.
//       DataAddress: 寫入源數(shù)據(jù)的緩沖的首地址. 就是從數(shù)組讀取數(shù)據(jù),
//       number:      寫入的字節(jié)長度.

void EEPROM_write_n(unsigned int EE_address,unsigned char *DataAddress,unsigned int number)
{
        IAP_ENABLE();       //設(shè)置等待時(shí)間,允許IAP操作,送一次就夠
        IAP_CMD = 2;        //宏調(diào)用, =2,送字節(jié)寫命令
        do
        {
        IAP_ADDRH = EE_address / 256; //送地址高字節(jié)(地址需要改變時(shí)才需重新送地址)
        IAP_ADDRL = EE_address % 256;     //送地址低字節(jié)
        IAP_DATA  = *DataAddress;         //送數(shù)據(jù)到IAP_DATA,只有數(shù)據(jù)改變時(shí)才需重新送
        EEPROM_Trig();                    //觸發(fā)EEPROM操作
        EE_address++;                     //下一個(gè)地址
        DataAddress++;                    //下一個(gè)數(shù)據(jù)
        }while(--number);                   //直到結(jié)束
        DisableEEPROM();
}

調(diào)用舉例:(建議定義一個(gè)數(shù)組)
unsigned char ROM_num[6];        //存儲(chǔ)數(shù)據(jù)的數(shù)組,最后與EEPROM進(jìn)行數(shù)據(jù)交換

EEPROM_read_n(EEPROM_ADD_0,ROM_num,6);          //讀取ROM信息到數(shù)組

void _write_ROM()      //編制專門的寫入函數(shù)
{
EEPROM_SectorErase(EEPROM_ADD_0);           //必須先擦除數(shù)據(jù)(由MCU自動(dòng),512字節(jié)被擦除),之后再寫入,才能寫正確
ROM_num[0]=test_1/256;                           //將4個(gè)測試數(shù)值分別給到臨時(shí)交換數(shù)組。
ROM_num[1]=test_1%256;
ROM_num[2]=test_2;                               //test_1、3是16位的數(shù)據(jù)(2個(gè)字節(jié));
ROM_num[3]=test_3/256;
ROM_num[4]=test_3%256;
ROM_num[5]=test_4;                               //test_2、test_4是單字節(jié)數(shù)據(jù)(8位)
EEPROM_write_n(EEPROM_ADD_0,ROM_num,6);        //從數(shù)組寫如到ROM中
}



評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏8 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:162691 發(fā)表于 2021-3-20 17:01 | 只看該作者
自己頂一個(gè)
回復(fù)

使用道具 舉報(bào)

板凳
ID:250631 發(fā)表于 2021-3-23 23:39 | 只看該作者
我選用的是8h8k64u芯片,希望能用上。感謝樓主無私分享
回復(fù)

使用道具 舉報(bào)

地板
ID:307493 發(fā)表于 2024-1-23 17:37 | 只看該作者
為啥我 照著寫 沒有把數(shù)據(jù)保存住
回復(fù)

使用道具 舉報(bào)

5#
ID:771630 發(fā)表于 2024-1-24 22:34 | 只看該作者
qq378912453 發(fā)表于 2024-1-23 17:37
為啥我 照著寫 沒有把數(shù)據(jù)保存住

要加延時(shí),靠他自動(dòng)延時(shí)存不住數(shù)據(jù)
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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