|
/*
以下已經(jīng)給出數(shù)據(jù)存儲的例程。就是把N個(gè)用戶數(shù)據(jù)通過緩存器ram的xdata區(qū)(0x8000~0x801f)來把數(shù)據(jù)存儲到 rom區(qū)的指定地址域 block_a和block_a_end之中; (ram就是所謂的“內(nèi)存”,rom就是所謂的“硬盤”)
請讀懂函數(shù),并把" //**************** "和” //********************* “之間的代碼,壓縮成一個(gè)循環(huán)體(主要問題)
思路是:把ROM塊“block_a(block_a~block_a_end)”分成長度為“save_size(即'用戶數(shù)據(jù)+CRC’的長度)”的若干個(gè)區(qū),并標(biāo)記bank1、bank2。。。。。bank n ;擦除時(shí),會擦除整個(gè)塊"block_a",保存數(shù)據(jù)時(shí),
則是先保存在bank1,下次保存在bank2,再次保存,則保存在緊挨著的下個(gè)bank; 最后整個(gè)block_a塊都滿了,則重新擦除塊“block_a“,再次從bank1(block_a的首地址)開始保存數(shù)據(jù)。就這樣周而復(fù)始;
注:
一次性最多只能擦除或者寫32byte,所有的數(shù)據(jù),必須經(jīng)過xdata區(qū)(0x8000~0x801f)的32byte緩沖區(qū)來完成。
擦除數(shù)據(jù):1次最少可以擦除1byte的數(shù)據(jù),最多一次性可以擦除32byte數(shù)據(jù),在xdata區(qū)(0x8000~0x801f)把需要擦除的字節(jié)清零,接著執(zhí)行擦除動作就可以了。
數(shù)據(jù)存儲:對于已經(jīng)擦除過的扇區(qū),則把要保存的數(shù)據(jù)發(fā)送到在xdata區(qū)(0x8000~0x801f),接著執(zhí)行寫的動作就可以了
先選擇FMCR=0x01;來激活xdata區(qū),并激活其他關(guān)于false操作的寄存器。
激活xdata區(qū)后,只有對xdata區(qū)(0x8000~0x801f)賦值的byte的才會對應(yīng)的被擦或?qū)憽?br />
在執(zhí)行擦除和寫動作時(shí),會自動屏蔽中斷,不需要軟件屏蔽。
以長度為N數(shù)據(jù)鏈為例,其結(jié)構(gòu)為:前面第0到第(N-2)個(gè)數(shù)據(jù)為用戶數(shù)據(jù),最后一個(gè)——————第(N-1)為數(shù)據(jù)鏈的冗余碼。
*/
- #define block_a ((unsigned char code *)0x3c00) /* BLOCK A ADDRESS 首地址*/
- #define block_a_end ((unsigned char code *)0x3fff) /* BLOCK A end_ADDRESS 末地址*/
- #define pgbuf_size 32 //緩沖區(qū)大小
- #define pgbuf_start ((unsigned char xdata *)0x8000) //緩沖區(qū)首地址
- #define pgbuf_end ((unsigned char xdata *)0x801f) //緩沖區(qū)末地址
- //==========================================================
- //塊擦除
- //輸入block首地址(ers_start_addr)和末地址(ers_end_addr)
- //擦除輸入的地址段
- //芯片支持單個(gè)byte的擦除,但是本子程序不支持
- //==========================================================
- void fnblock_erase(uchar code *ers_start_addr,uchar code *ers_end_addr);
- //===========================================
- // 設(shè)置數(shù)據(jù)的保存
- //本子程序允許存儲的數(shù)據(jù)鏈長度不限
- //主要用于掉電記憶
- //===========================================
- #define save_size 45 //儲存的數(shù)據(jù)長度
- uchar fntake_crc(uchar *p,uchar num_size); //求數(shù)據(jù)連的CRC
- void fnact_circuit(); //激活燒錄升壓電路
- void fnact_write(); //執(zhí)行燒錄
- void fnsave_data()
- {
- uchar code *write_addr;
- uchar i,k,m,n,y;
- k=take_crc(&save[0],(save_size-1)); //求CRC
- save[save_size-1]=k; //保存CRC
- write_addr=block_a;
-
- y=0;
- while(y<100) //如果換區(qū)100個(gè)都寫不成功,則認(rèn)為芯片永久損壞,報(bào)廢。
- {
- while(write_addr<=(block_a_end-save_size)) //確保要寫的數(shù)據(jù)在block_a區(qū)域內(nèi)
- { //-----------------查空,空時(shí)為0 ,當(dāng)rom區(qū)為“空”時(shí),邏輯數(shù)據(jù)為“0”
- //在數(shù)據(jù)保存之前,先檢查需要保存的地址區(qū)域連save_size的長度都為“空”
- for(i=0;i<save_size;i++)
- {
- if(*(write_addr+i)!=0) break;
- }
- if(i==save_size) break; //判斷,如果連續(xù)save_size的長度都為“空”,則結(jié)束循環(huán)并跳出
- write_addr+=save_size; //如果當(dāng)前的地址域不是連續(xù)“空”,則準(zhǔn)備查詢下一個(gè)區(qū)
- if(write_addr>(block_a_end-save_size)) //如果從block_a到(block_a_end-save_size)的區(qū)間都有非零數(shù)據(jù)(不是“空”),則執(zhí)行調(diào)用擦除函數(shù)fnblock_erase()
- {
- block_erase(block_a,block_a_end); //擦除數(shù)據(jù)塊block_a
- write_addr=block_a; //重置寫數(shù)據(jù)的區(qū)
- bflash_erase=true; //置1,避免第85行,重復(fù)調(diào)用fnblock_erase()
- break;
- }
- }
- if((write_addr==block_a)&&(bflash_erase==false))
- { //第一次存儲時(shí),也需要擦除一次
- block_erase(block_a,block_a_end); //擦除
- write_addr=block_a;
- }
- bflash_erase=false;
-
-
- //開始寫入
- //*****************************************************************
- n=0;
- while(n<8) //同一個(gè)區(qū)允許寫8次
- {
- //=================寫入一部分?jǐn)?shù)據(jù)======================
- k=(write_addr-block_a)%pgbuf_size; //計(jì)算開始寫的緩沖區(qū)相對地址
- pgbuf=pgbuf_start+k; //開始寫的緩沖區(qū)絕對地址
-
- fnact_circuit(); //激活燒錄升壓電路
-
- m=pgbuf_size-k; //m=要保存數(shù)據(jù)的首地址(在緩沖區(qū)“0x8000~0x801f”中的首地址)
- for(i=0;((i<m)&&(i<save_size));i++)
- { //把需要保存的數(shù)據(jù)移到緩沖區(qū)
- *(pgbuf+i)=save[i];
- }
-
- if(write_addr>=0x3800)
- {
- FSADRL=(ushort)write_addr; //數(shù)據(jù)要保存在rom中的絕對地址低8位
- FSADRM=(ushort)write_addr>>8; //數(shù)據(jù)要保存在rom中的絕對地址高8位
- FSADRH=0;
-
- fnact_write(); //執(zhí)行燒錄
- }
- //=================================================
- //================繼續(xù)寫剩下部分====================
- for(;m<save_size;)
- { /
- pgbuf=pgbuf_start;
-
- fnact_circuit(); //激活燒錄升壓電路
-
- for(i=0;((i<pgbuf_size)&&(i<(save_size-m)));i++)
- { //把需要保存的數(shù)據(jù)移到緩沖區(qū)
- *(pgbuf+i)=save[i+m];
- }
-
- if(write_addr>=0x3800)
- {
- FSADRL=((ushort)write_addr+m);
- FSADRM=((ushort)write_addr+m)>>8;
- FSADRH=0;
-
- fnact_write(); //執(zhí)行燒錄
- }
- m=m+i;
- }
- //======================================
- //**************************************
-
- //-----------------------------驗(yàn)證存儲是否成功
- for(i=0;i<save_size;i++)
- {
- if(*(write_addr+i)!=save[i]) break;
- }
-
- if(i==save_size) break;
- n++;
- }
- if(i==save_size) break;
- y++;
- write_addr+=save_size; //如果同一區(qū)寫8次不成功,則換區(qū)
- if(write_addr>(block_a_end-save_size))
- {
- block_erase(block_a,block_a_end); //擦除
- write_addr=block_a;
- bflash_erase=true;
- }
- }
- }
復(fù)制代碼
|
|