找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1829|回复: 2
打印 上一主题 下一主题
收起左侧

需要大神进行数据保存讲解,还有如何修改单片机程序

[复制链接]
跳转到指定楼层
楼主
ID:148486 发表于 2019-5-20 08:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*  
        以下已经给出数据存储的例程。就是把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)为数据链的冗余码。        
*/

  1. #define block_a     ((unsigned char code *)0x3c00)            /*  BLOCK A ADDRESS 首地址*/
  2. #define block_a_end ((unsigned char code *)0x3fff)            /*  BLOCK A end_ADDRESS 末地址*/


  3. #define        pgbuf_size        32                                                        //缓冲区大小
  4. #define pgbuf_start ((unsigned char xdata *)0x8000)        //缓冲区首地址
  5. #define        pgbuf_end        ((unsigned char xdata *)0x801f)        //缓冲区末地址

  6. //==========================================================
  7. //块擦除
  8. //输入block首地址(ers_start_addr)和末地址(ers_end_addr)
  9. //擦除输入的地址段
  10. //芯片支持单个byte的擦除,但是本子程序不支持
  11. //==========================================================
  12. void        fnblock_erase(uchar code *ers_start_addr,uchar code *ers_end_addr);


  13. //===========================================
  14. //                     设置数据的保存
  15. //本子程序允许存储的数据链长度不限
  16. //主要用于掉电记忆
  17. //===========================================
  18. #define        save_size        45                                                                                                //储存的数据长度
  19. uchar        fntake_crc(uchar        *p,uchar num_size);        //求数据连的CRC
  20. void        fnact_circuit();                        //激活烧录升压电路
  21. void        fnact_write();        //执行烧录

  22. void        fnsave_data()
  23. {
  24.         uchar code *write_addr;
  25.         uchar        i,k,m,n,y;
  26.         k=take_crc(&save[0],(save_size-1));                //求CRC
  27.         save[save_size-1]=k;                                                                        //保存CRC        
  28.         write_addr=block_a;
  29.         
  30.         y=0;
  31.         while(y<100)        //如果换区100个都写不成功,则认为芯片永久损坏,报废。
  32.         {
  33.                 while(write_addr<=(block_a_end-save_size))         //确保要写的数据在block_a区域内
  34.                 {                                //-----------------查空,空时为0 ,当rom区为“空”时,逻辑数据为“0”
  35.                               //在数据保存之前,先检查需要保存的地址区域连save_size的长度都为“空”
  36.                         for(i=0;i<save_size;i++)
  37.                         {        
  38.                                 if(*(write_addr+i)!=0)        break;
  39.                         }
  40.                         if(i==save_size)        break;                //判断,如果连续save_size的长度都为“空”,则结束循环并跳出
  41.                         write_addr+=save_size;                        //如果当前的地址域不是连续“空”,则准备查询下一个区
  42.                         if(write_addr>(block_a_end-save_size))        //如果从block_a到(block_a_end-save_size)的区间都有非零数据(不是“空”),则执行调用擦除函数fnblock_erase()
  43.                         {
  44.                                 block_erase(block_a,block_a_end);                  //擦除数据块block_a
  45.                                 write_addr=block_a;                                                                                //重置写数据的区
  46.                                 bflash_erase=true;                                                                                //置1,避免第85行,重复调用fnblock_erase()
  47.                                 break;
  48.                         }
  49.                 }
  50.                 if((write_addr==block_a)&&(bflash_erase==false))
  51.                 {        //第一次存储时,也需要擦除一次
  52.                         block_erase(block_a,block_a_end);                  //擦除
  53.                         write_addr=block_a;
  54.                 }
  55.                 bflash_erase=false;
  56.                
  57.                         
  58.                 //开始写入                        
  59.                 //*****************************************************************
  60.                 n=0;                           
  61.                 while(n<8)                                                                                                                //同一个区允许写8次
  62.                 {
  63.                         //=================写入一部分数据======================
  64.                         k=(write_addr-block_a)%pgbuf_size;        //计算开始写的缓冲区相对地址
  65.                         pgbuf=pgbuf_start+k;                                                                //开始写的缓冲区绝对地址
  66.                                                 
  67.                         fnact_circuit();                        //激活烧录升压电路
  68.                         
  69.                         m=pgbuf_size-k;                                                                                        //m=要保存数据的首地址(在缓冲区“0x8000~0x801f”中的首地址)
  70.                         for(i=0;((i<m)&&(i<save_size));i++)
  71.                         {                                                                        //把需要保存的数据移到缓冲区
  72.                                 *(pgbuf+i)=save[i];
  73.                         }
  74.                         
  75.                         if(write_addr>=0x3800)
  76.                         {
  77.                                 FSADRL=(ushort)write_addr;                        //数据要保存在rom中的绝对地址低8位
  78.                                 FSADRM=(ushort)write_addr>>8;          //数据要保存在rom中的绝对地址高8位
  79.                                 FSADRH=0;
  80.                                 
  81.                                 fnact_write();        //执行烧录
  82.                         }
  83.                         //=================================================
  84.                         //================继续写剩下部分====================
  85.                         for(;m<save_size;)
  86.                         {                                                /
  87.                                 pgbuf=pgbuf_start;
  88.                                 
  89.                                 fnact_circuit();                        //激活烧录升压电路
  90.                                    
  91.                                 for(i=0;((i<pgbuf_size)&&(i<(save_size-m)));i++)         
  92.                                 {        //把需要保存的数据移到缓冲区
  93.                                         *(pgbuf+i)=save[i+m];
  94.                                 }
  95.                                 
  96.                                 if(write_addr>=0x3800)
  97.                                 {
  98.                                         FSADRL=((ushort)write_addr+m);
  99.                                         FSADRM=((ushort)write_addr+m)>>8;        
  100.                                         FSADRH=0;
  101.                                        
  102.                                         fnact_write();        //执行烧录
  103.                                 }
  104.                                 m=m+i;
  105.                         }
  106.                         //======================================
  107.                         //**************************************
  108.                         
  109.                         //-----------------------------验证存储是否成功
  110.                         for(i=0;i<save_size;i++)
  111.                         {
  112.                                 if(*(write_addr+i)!=save[i])        break;
  113.                         }
  114.                         
  115.                         if(i==save_size)        break;
  116.                         n++;
  117.                 }
  118.                 if(i==save_size)        break;
  119.                 y++;
  120.                 write_addr+=save_size;                                                        //如果同一区写8次不成功,则换区
  121.                 if(write_addr>(block_a_end-save_size))
  122.                 {
  123.                         block_erase(block_a,block_a_end);                  //擦除
  124.                         write_addr=block_a;
  125.                         bflash_erase=true;
  126.                 }
  127.         }                                                
  128. }        
复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:330198 发表于 2019-5-20 09:56 | 只看该作者
你想要怎么改啊
回复

使用道具 举报

板凳
ID:148486 发表于 2019-5-20 12:23 | 只看该作者
把" //**************** "和” //********************* “之间的代码,压缩成一个循环体
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表