zoukankan      html  css  js  c++  java
  • 【转】24Cxx 系列EEPROM通用程序及应用

    关于I2C 学习的时候介绍得最多的就是24C02 这里存储EEPROM了,但学的时候基本只是讲讲简单的I2C 的总线数据传输而已,即使先gooogle上搜索也绝大部分这这样的文章,很少有说到如何在实际情况中如何使用的程序。

        24Cxx系列数据块存储时也是比较讲究的,


    图为 几类不同容量的芯片的存储空间结构,24C16以下空间的大于8位后的寻址高位地址在片选地址中选择,详细看芯片手册。另外要注意的就是字节页,一次连续写入的数据量不能超过一页的数据量。有些老款的芯片甚至不支持跨页写入。为了适用也参照不跨页写入的方法写这个程序。而读取数据没有这个限制,只要单片机开辟的缓存够大,可以一直连续读下去。

    /*****24Cxx Seriel EEPROM*************************/
    #define EEPROM 8
    /********
    01 -> 24C01;   02 -> 24C02;  04 -> 24C04;   08 -> 24C08;
    16 -> 24C16;   32 -> 24C32;  64 -> 24C64;   128 -> 24C128;
    256-> 24C256;  512 -> 24C512;  
    *****/
    
    #if EEPROM==1
       #define PAGE_SIZE           8
       #define EE_SIZE             0x007F
    #elif EEPROM==2
       #define PAGE_SIZE           16 
       #define EE_SIZE             0x00FF
    #elif EEPROM==4
       #define PAGE_SIZE           16
       #define EE_SIZE             0x01FF
    #elif EEPROM==8
       #define PAGE_SIZE           16
       #define EE_SIZE             0x03FF
    #elif EEPROM==16
       #define PAGE_SIZE           16
       #define EE_SIZE             0x07FF
    #elif EEPROM==32
       #define PAGE_SIZE           32
       #define EE_SIZE             0x0FFF
    #elif EEPROM==64
       #define PAGE_SIZE           32
       #define EE_SIZE             0x1FFF
    #elif EEPROM==128
       #define PAGE_SIZE           64
       #define EE_SIZE             0x3FFF
    #elif EEPROM==256
       #define PAGE_SIZE           64
       #define EE_SIZE             0x7FFF
    #elif EEPROM==512
       #define PAGE_SIZE           128
       #define EE_SIZE             0xFFFF
    
    #endif 
         
        头文件可以写成预编译模式,方便移植后修改,PAGE_SIZE为一页的存储量,EE_SIZE为芯片的存储量,而后一些程序的判断也根据选择的存储芯片来判断。
    顶层用于外部程序调用的函数只有两个,读和写两个情况而已
    unsigned char EEPROM_Write(unsigned char* pBuffer,unsigned int WriteAddress,unsigned char NumbyteToWrite);
    unsigned char EEPROM_Read(unsigned char* pBuffer,unsigned int ReadAddress,unsigned char NumbyteToWrite);
     
    传递函数有三个:
    pBuffer:要存储或读出来的数据所在的变量存储区字符串头指针;
    WriteAddress/ReadAddress:要存入EEPROM所在的存储空间的第一个存储空间地址;
    NumbyteToWrite:数据写入或读出的字节个数;
    这样的应用比较简单 例如在头文件中分配了两类数据的存储空间起始地址DATA1、DATA2
    #define DATA1  0x0010
    #define DATA2  0x0050
    存储数据所在缓存 EE_Buffer[20],应用程序如下写法:
    EEPROM_Write(EE_Buffer,DATA1,20);
    这样EE_Buffer内的数据便被写入EEPROM中 0x10~0x30 的数据存储空间中了。
    合理的分配陪EEPROM 的存储空间对数据管理非常重要。甚至于可以作为一个小型黑匣子一样。
    unsigned char EEPROM_Write(unsigned char* pBuffer,unsigned int WriteAddress,unsigned char NumbyteToWrite)
    {
      unsigned char TempBuffer,Temp2Buffer;
      if((WriteAddress+NumbyteToWrite) > EE_SIZE)  //判断是否超出存储空间
        {
          return 0;
        }
      else
        {// 连续写入两次避免因EMC等因素造成的写入失败情况
          IIC_WriteBuffer(pBuffer,WriteAddress,NumbyteToWrite);
          IIC_WriteBuffer(pBuffer,WriteAddress,NumbyteToWrite);
     
         //读取eeprom 的数据与缓存中的数据对比 相同为确认写入成功
          IIC_ReadBuffer(&TempBuffer,WriteAddress+NumbyteToWrite-1,1);
          Temp2Buffer=*(pBuffer+NumbyteToWrite-1);
          if(TempBuffer==Temp2Buffer)
             return 1;
          else
          return 0;
        }
    }
     
    unsigned char EEPROM_Read(unsigned char* pBuffer,unsigned int ReadAddress,unsigned char NumbyteToWrite) 
    {
      if((ReadAddress+NumbyteToWrite) > EE_SIZE) 
        {
          return 0;
        }
      else
        {
          IIC_ReadBuffer(pBuffer,ReadAddress,NumbyteToWrite);
          IIC_ReadBuffer(pBuffer,ReadAddress,NumbyteToWrite);
          return 1;
        }
    }
    接下来的是是IIC_ReadBuffer、IIC_WriteBuffer,两个函数主要是对存入数据的处理,如页面内写入,超过页面数量的数据处理等,我这里把函数定义为static 函数只能对内部应用,外部只能调用上面的两个函数,累似于API函数一样,这也可以避免不必要的程序调用书写。IIC_ReadBuffer函数相对简单,因为读取没有对页面的限制,可以无限制的读下去。读取缓存的函数只对地址做一下判断即可。写入函数较为复杂,需判断数据起始存储地址 和页等关系
    static void IIC_ReadBuffer(unsigned char* pBuffer,unsigned int ReadAddress,unsigned char NumbyteToWrite);
    static void IIC_WriteBuffer(unsigned char* pBuffer,unsigned int WriteAddress,unsigned char NumByteToWrite);
     
    void IIC_ReadBuffer(unsigned char* pBuffer,unsigned int ReadAddress,unsigned char NumbyteToWrite)
    {
      u8 PageAddress=0;
      /******pageAddress is over 8bit***********/
    /******判断存储地址是否超过8位************/
    #if EEPROM < 32
      PageAddress=(u8)(ReadAddress>>7)&0x0E|ReadAddress_EEPROM;
    #else
      PageAddress=WriteAddress_EEPROM;
    #endif 
     
     IIC_ReadPage(pBuffer,PageAddress,ReadAddress,NumbyteToWrite); 
    }
    void IIC_WriteBuffer(unsigned char* pBuffer,unsigned int WriteAddress,unsigned char NumByteToWrite)
    {
      u8 NumOfPage=0,NumOfSingle=0; //
      u16 Part=0;//
      u8 PageAddress=0;
      /******pageAddress is over 8bit***********/
      /******判断存储地址是否超过8位************/
    #if EEPROM < 32
      PageAddress=(u8)(WriteAddress>>7)&0x0E|WriteAddress_EEPROM;
    #else
      PageAddress=WriteAddress_EEPROM;
    #endif 
      
      /*********判断起始地址与跨页地址的字节个数********/
      Part=WriteAddress/PAGE_SIZE;
      if(Part!=0)
        {
          Part=PAGE_SIZE*(Part+1)-WriteAddress;      
        }
      else 
        {
          Part=PAGE_SIZE-WriteAddress;
        }
      /******/
      if(Part >= NumByteToWrite)
        {
    /***写入的数据个数小于跨页剩余的个数可直接写入 ***/
          IIC_WritePage(pBuffer,PageAddress,WriteAddress,NumByteToWrite);
        }
      else
        {
          NumOfPage = (NumByteToWrite-Part)/PAGE_SIZE;  
          NumOfSingle = (NumByteToWrite-Part)%PAGE_SIZE;   
          pBuffer = IIC_WritePage(pBuffer,PageAddress,WriteAddress,Part);
        /***1.写入的数据个数大于跨页剩余的个数先把剩余的跨页个数填充满 ***/
          NumByteToWrite -= Part;
          WriteAddress += Part;
     
          while(NumOfPage--)
    {     
      pBuffer = IIC_WritePage(pBuffer,PageAddress,WriteAddress,PAGE_SIZE);
    /***2.按计算的数据量占页面数,连续写入页面*******/
      WriteAddress += PAGE_SIZE;
     
    }   
          if(NumOfSingle!=0)
    {
      IIC_WritePage(pBuffer,PageAddress,WriteAddress,NumOfSingle);
     /***3.补充页面写完后超出的不足一页数据量的数据***/
    }
        }
    }
     
    剩下的是IIC_WritePage()、IIC_ReadPage()两个函数是芯片的IIC通讯底层函数,根据单片机的IIC通讯模式写入即可。以上的程序可通用到任何24Cxx 系列所应用的程序。
     
         在实际应用中要注意的便是存储空间的分配,已经空间长度的输入,这样EEPROM的使用便能得心应手。
     
     
    参考来源:虚V界的个人空间的博客->24Cxx 系列EEPROM通用程序及应用,http://home.eeworld.com.cn/my/space-uid-93649-blogid-77560.html
     
  • 相关阅读:
    5.16
    4.29
    二十节 作业
    作业
    作业
    控件
    选择排序
    百钱买百鸡
    用颜色变色变换来调整图像的对比度和亮度
    图像的裁剪
  • 原文地址:https://www.cnblogs.com/BinB-W/p/6163216.html
Copyright © 2011-2022 走看看