/*
以下已经给出数据存储的例程。就是把N个用户数据通过缓存器ram的xdata区(0x8000~0x801f)来把数据存储到 rom区的指定地址域 block_a和block_a_end之中; (ram就是所谓的“内存”,rom就是所谓的“硬盘”)
请读懂函数,并把" //**************** "和” //********************* “之间的代码,压缩成一个循环体(主要问题)
思路是:把ROM块“block_a(block_a~block_a_end)”分成长度为“save_size(即'用户数据+CRC’的长度)”的若干个区,并标记bank1、bank2。。。。。bank n ;擦除时,会擦除整个块"block_a",保存数据时,
则是先保存在bank1,下次保存在bank2,再次保存,则保存在紧挨着的下个bank; 最后整个block_a块都满了,则重新擦除块“block_a“,再次从bank1(block_a的首地址)开始保存数据。就这样周而复始;
注:
一次性最多只能擦除或者写32byte,所有的数据,必须经过xdata区(0x8000~0x801f)的32byte缓冲区来完成。
擦除数据:1次最少可以擦除1byte的数据,最多一次性可以擦除32byte数据,在xdata区(0x8000~0x801f)把需要擦除的字节清零,接着执行擦除动作就可以了。
数据存储:对于已经擦除过的扇区,则把要保存的数据发送到在xdata区(0x8000~0x801f),接着执行写的动作就可以了
先选择FMCR=0x01;来激活xdata区,并激活其他关于false操作的寄存器。
激活xdata区后,只有对xdata区(0x8000~0x801f)赋值的byte的才会对应的被擦或写。
在执行擦除和写动作时,会自动屏蔽中断,不需要软件屏蔽。
以长度为N数据链为例,其结构为:前面第0到第(N-2)个数据为用户数据,最后一个——————第(N-1)为数据链的冗余码。
*/
- #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 //缓冲区大小
- #define pgbuf_start ((unsigned char xdata *)0x8000) //缓冲区首地址
- #define pgbuf_end ((unsigned char xdata *)0x801f) //缓冲区末地址
- //==========================================================
- //块擦除
- //输入block首地址(ers_start_addr)和末地址(ers_end_addr)
- //擦除输入的地址段
- //芯片支持单个byte的擦除,但是本子程序不支持
- //==========================================================
- void fnblock_erase(uchar code *ers_start_addr,uchar code *ers_end_addr);
- //===========================================
- // 设置数据的保存
- //本子程序允许存储的数据链长度不限
- //主要用于掉电记忆
- //===========================================
- #define save_size 45 //储存的数据长度
- uchar fntake_crc(uchar *p,uchar num_size); //求数据连的CRC
- void fnact_circuit(); //激活烧录升压电路
- void fnact_write(); //执行烧录
- 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) //如果换区100个都写不成功,则认为芯片永久损坏,报废。
- {
- while(write_addr<=(block_a_end-save_size)) //确保要写的数据在block_a区域内
- { //-----------------查空,空时为0 ,当rom区为“空”时,逻辑数据为“0”
- //在数据保存之前,先检查需要保存的地址区域连save_size的长度都为“空”
- for(i=0;i<save_size;i++)
- {
- if(*(write_addr+i)!=0) break;
- }
- if(i==save_size) break; //判断,如果连续save_size的长度都为“空”,则结束循环并跳出
- write_addr+=save_size; //如果当前的地址域不是连续“空”,则准备查询下一个区
- if(write_addr>(block_a_end-save_size)) //如果从block_a到(block_a_end-save_size)的区间都有非零数据(不是“空”),则执行调用擦除函数fnblock_erase()
- {
- block_erase(block_a,block_a_end); //擦除数据块block_a
- write_addr=block_a; //重置写数据的区
- bflash_erase=true; //置1,避免第85行,重复调用fnblock_erase()
- break;
- }
- }
- if((write_addr==block_a)&&(bflash_erase==false))
- { //第一次存储时,也需要擦除一次
- block_erase(block_a,block_a_end); //擦除
- write_addr=block_a;
- }
- bflash_erase=false;
-
-
- //开始写入
- //*****************************************************************
- n=0;
- while(n<8) //同一个区允许写8次
- {
- //=================写入一部分数据======================
- k=(write_addr-block_a)%pgbuf_size; //计算开始写的缓冲区相对地址
- pgbuf=pgbuf_start+k; //开始写的缓冲区绝对地址
-
- fnact_circuit(); //激活烧录升压电路
-
- m=pgbuf_size-k; //m=要保存数据的首地址(在缓冲区“0x8000~0x801f”中的首地址)
- for(i=0;((i<m)&&(i<save_size));i++)
- { //把需要保存的数据移到缓冲区
- *(pgbuf+i)=save[i];
- }
-
- if(write_addr>=0x3800)
- {
- FSADRL=(ushort)write_addr; //数据要保存在rom中的绝对地址低8位
- FSADRM=(ushort)write_addr>>8; //数据要保存在rom中的绝对地址高8位
- FSADRH=0;
-
- fnact_write(); //执行烧录
- }
- //=================================================
- //================继续写剩下部分====================
- for(;m<save_size;)
- { /
- pgbuf=pgbuf_start;
-
- fnact_circuit(); //激活烧录升压电路
-
- for(i=0;((i<pgbuf_size)&&(i<(save_size-m)));i++)
- { //把需要保存的数据移到缓冲区
- *(pgbuf+i)=save[i+m];
- }
-
- if(write_addr>=0x3800)
- {
- FSADRL=((ushort)write_addr+m);
- FSADRM=((ushort)write_addr+m)>>8;
- FSADRH=0;
-
- fnact_write(); //执行烧录
- }
- m=m+i;
- }
- //======================================
- //**************************************
-
- //-----------------------------验证存储是否成功
- 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; //如果同一区写8次不成功,则换区
- if(write_addr>(block_a_end-save_size))
- {
- block_erase(block_a,block_a_end); //擦除
- write_addr=block_a;
- bflash_erase=true;
- }
- }
- }
复制代码
|