#include "Include.h"
//#include "EEPROM_24Cxx.h"



EEPROMErrEnum EEPROM_Instant_Byte_Write(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t Data)
{
  uint8_t i;
  uint8_t ACK;
  uint8_t AddrLen;
  uint8_t Addr[3];
  
  //׼����ַ
  if (EEPROMRW.State != EEPROM_IDLE)
    return EEPROM_BUSY;
    
  if (DeviceAddr > 0x07)
    return EEPROM_INVALID_DEVICE_ADDR;
  
  if (DataAddr > EEPROM_MAX_DATA_ADDR)
    return EEPROM_INVALID_DATA_ADDR;
  
  #if   defined EEPROM_DATA_ADDR_2_BYTE
    AddrLen = 3;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    Addr[1] = (uint8_t)(DataAddr >> 8);
    Addr[2] = (uint8_t)DataAddr;
        
  #elif defined EEPROM_DATA_ADDR_2_BYTE_MIXED
    #if   defined EEPROM_24C04    //24C04ֻ��A2��A1����  
      DeviceAddr &= 0x06;
    #elif defined EEPROM_24C08    //24C08ֻ��A2����
      DeviceAddr &= 0x04;
    #elif defined EEPROM_24C16    //24C16û�����õ�ַ����
      DeviceAddr  = 0x00;
    #else
      #error Incorrect EEPROM device definition
    #endif

    AddrLen = 2;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (((uint8_t)(DataAddr >> 8) | DeviceAddr) << 1);    
    Addr[1] = (uint8_t)DataAddr;

  #elif defined EEPROM_DATA_ADDR_1_BYTE   
    AddrLen = 2;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    Addr[1] = (uint8_t)DataAddr;   

  #else
    #error Incorrect EEPROM device definition
    
  #endif    
  
  //����IIC
  IIC_Start();
  
  //���͵�ַ
  for (i = 0; i < AddrLen; i++)
  {
    IIC_Transmit_Data(Addr[i]);
    
    do
    {
      ACK = IIC_Receive_ACK();
    }
    while (ACK == IIC_INVALID_ACK);
    
    if (ACK != IIC_ACK)
    {
      IIC_Stop();
      return EEPROM_NO_RESPONSE;
    }
  }
  
  //�����
  IIC_Transmit_Data(Data);
  
  do
  {
    ACK = IIC_Receive_ACK();
  }
  while (ACK == IIC_INVALID_ACK);
  
  //ֹͣIIC
  IIC_Stop();
  
  //�������
  if (ACK == IIC_ACK)
    return EEPROM_OK;
  else
    return EEPROM_NO_RESPONSE;
}

EEPROMErrEnum EEPROM_Instant_Page_Write(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t *pData, uint8_t Len)
{
  uint8_t i;
  uint8_t ACK;
  uint8_t AddrLen;
  uint8_t Addr[3];
  
  //׼����ַ
  if (EEPROMRW.State != EEPROM_IDLE)
    return EEPROM_BUSY;
    
  if (DeviceAddr > 0x07)
    return EEPROM_INVALID_DEVICE_ADDR;
  
  if (DataAddr > EEPROM_MAX_DATA_ADDR)
    return EEPROM_INVALID_DATA_ADDR;
  
  if ((Len > EEPROM_PAGE_SIZE) || (Len == 0))
    return EEPROM_DATA_LENGTH_ERR;
  
  #if   defined EEPROM_DATA_ADDR_2_BYTE
    AddrLen = 3;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    Addr[1] = (uint8_t)(DataAddr >> 8);
    Addr[2] = (uint8_t)DataAddr;
        
  #elif defined EEPROM_DATA_ADDR_2_BYTE_MIXED
    #if   defined EEPROM_24C04    //24C04ֻ��A2��A1����  
      DeviceAddr &= 0x06;
    #elif defined EEPROM_24C08    //24C08ֻ��A2����
      DeviceAddr &= 0x04;
    #elif defined EEPROM_24C16    //24C16û�����õ�ַ����
      DeviceAddr  = 0x00;
    #else
      #error Incorrect EEPROM device definition
    #endif

    AddrLen = 2;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (((uint8_t)(DataAddr >> 8) | DeviceAddr) << 1);    
    Addr[1] = (uint8_t)DataAddr;

  #elif defined EEPROM_DATA_ADDR_1_BYTE   
    AddrLen = 2;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    Addr[1] = (uint8_t)DataAddr;   

  #else
    #error Incorrect EEPROM device definition
    
  #endif    
  
  //����IIC
  IIC_Start();
  
  //���͵�ַ
  for (i = 0; i < AddrLen; i++)
  {
    IIC_Transmit_Data(Addr[i]);
    
    do
    {
      ACK = IIC_Receive_ACK();
    }
    while (ACK == IIC_INVALID_ACK);
    
    if (ACK != IIC_ACK)
    {
      IIC_Stop();
      return EEPROM_NO_RESPONSE;
    }
  }
  
  //�����
  for (i = 0; i < Len; i++)
  {
    IIC_Transmit_Data(pData[i]);
  
    do
    {
      ACK = IIC_Receive_ACK();
    }
    while (ACK == IIC_INVALID_ACK);
    
    if (ACK != IIC_ACK)
    {
      IIC_Stop();
      return EEPROM_NO_RESPONSE;
    }
  }
  
  //ֹͣIIC
  IIC_Stop();
  
  //�������
  return EEPROM_OK;
}
EEPROMErrEnum EEPROM_Instant_Page_Write_Repeatedly(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t *pData, uint8_t Len)
{

    uint8_t   Write_Status=0;
    //ÿ��ҳд֮��  ���10ms
    while(EEPROM_Delay<(10000/API_INT_CYCLE))
    {
        _FEED_COP();
    };

    Write_Status = EEPROM_Instant_Page_Write( DeviceAddr,  DataAddr,  pData,  Len)  ;
     EEPROM_Delay=0;

    return Write_Status;
}
EEPROMErrEnum EEPROM_Byte_Write(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t Data)
{
  if (EEPROMRW.WRState != EEPROM_RW_IDLE)
    return EEPROM_BUSY;
    
  if (DeviceAddr > 0x07)
    return EEPROM_INVALID_DEVICE_ADDR;
  
  if (DataAddr > EEPROM_MAX_DATA_ADDR)
    return EEPROM_INVALID_DATA_ADDR;
  
  #if   defined EEPROM_DATA_ADDR_2_BYTE
    EEPROMRW.WRAddrLen = 3;
    EEPROMRW.WRAddr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    EEPROMRW.WRAddr[1] = (uint8_t)(DataAddr >> 8);
    EEPROMRW.WRAddr[2] = (uint8_t)DataAddr;
        
  #elif defined EEPROM_DATA_ADDR_2_BYTE_MIXED
    #if   defined EEPROM_24C04    //24C04ֻ��A2��A1����  
      DeviceAddr &= 0x06;
    #elif defined EEPROM_24C08    //24C08ֻ��A2����
      DeviceAddr &= 0x04;
    #elif defined EEPROM_24C16    //24C16û�����õ�ַ����
      DeviceAddr  = 0x00;
    #else
      #error Incorrect EEPROM device definition
    #endif

    EEPROMRW.WRAddrLen = 2;
    EEPROMRW.WRAddr[0] = EEPROM_DEVICE_ADDR_WR | (((uint8_t)(DataAddr >> 8) | DeviceAddr) << 1);    
    EEPROMRW.WRAddr[1] = (uint8_t)DataAddr;

  #elif defined EEPROM_DATA_ADDR_1_BYTE   
    EEPROMRW.WRAddrLen = 2;
    EEPROMRW.WRAddr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    EEPROMRW.WRAddr[1] = (uint8_t)DataAddr;   

  #else
    #error Incorrect EEPROM device definition
    
  #endif
  
  EEPROMRW.WRDataLen = 1;
  EEPROMRW.WRData[0] = Data;
  
  EEPROMRW.WRResult = EEPROM_RW_IN_PROGRESS;
  
  EEPROMRW.WRState = EEPROM_RW_REQ;
  if ((EEPROMRW.State == EEPROM_IDLE) || (EEPROMRW.State == EEPROM_RD_START))   //д�����ȼ����ڶ������ȼ�
    EEPROMRW.State = EEPROM_WR_START;
    
  return EEPROM_OK;
}

EEPROMErrEnum EEPROM_Page_Write(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t *pData, uint8_t Len)
{
  uint8_t i;
  
  if (EEPROMRW.WRState != EEPROM_RW_IDLE)
    return EEPROM_BUSY;
    
  if (DeviceAddr > 0x07)
    return EEPROM_INVALID_DEVICE_ADDR;
  
  if (DataAddr > EEPROM_MAX_DATA_ADDR)
    return EEPROM_INVALID_DATA_ADDR;
  
  if ((Len > EEPROM_PAGE_SIZE) || (Len == 0))
    return EEPROM_DATA_LENGTH_ERR;
  
  #if   defined EEPROM_DATA_ADDR_2_BYTE
    EEPROMRW.WRAddrLen = 3;
    EEPROMRW.WRAddr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    EEPROMRW.WRAddr[1] = (uint8_t)(DataAddr >> 8);
    EEPROMRW.WRAddr[2] = (uint8_t)DataAddr;
        
  #elif defined EEPROM_DATA_ADDR_2_BYTE_MIXED
    #if   defined EEPROM_24C04    //24C04ֻ��A2��A1����  
      DeviceAddr &= 0x06;
    #elif defined EEPROM_24C08    //24C08ֻ��A2����
      DeviceAddr &= 0x04;
    #elif defined EEPROM_24C16    //24C16û�����õ�ַ����
      DeviceAddr  = 0x00;
    #else
      #error Incorrect EEPROM device definition
    #endif

    EEPROMRW.WRAddrLen = 2;
    EEPROMRW.WRAddr[0] = EEPROM_DEVICE_ADDR_WR | (((uint8_t)(DataAddr >> 8) | DeviceAddr) << 1);    
    EEPROMRW.WRAddr[1] = (uint8_t)DataAddr;

  #elif defined EEPROM_DATA_ADDR_1_BYTE   
    EEPROMRW.WRAddrLen = 2;
    EEPROMRW.WRAddr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    EEPROMRW.WRAddr[1] = (uint8_t)DataAddr;   

  #else
    #error Incorrect EEPROM device definition
    
  #endif
  
  EEPROMRW.WRDataLen = Len;
  for (i = 0; i < Len; i++)
    EEPROMRW.WRData[i] = pData[i];
  
  EEPROMRW.WRResult = EEPROM_RW_IN_PROGRESS;
  
  EEPROMRW.WRState = EEPROM_RW_REQ;
  if ((EEPROMRW.State == EEPROM_IDLE) || (EEPROMRW.State == EEPROM_RD_START))   //д�����ȼ����ڶ������ȼ�
    EEPROMRW.State = EEPROM_WR_START;
    
  return EEPROM_OK;
}

EEPROMRWResultEnum EEPROM_Get_Write_Result(void)
{
  EEPROMRWResultEnum Result;
  
  if (EEPROMRW.WRState == EEPROM_RW_BUSY)
    return EEPROM_RW_IN_PROGRESS;
  else
  {
    Result = EEPROMRW.WRResult;
    if (Result != EEPROM_RW_IN_PROGRESS)
      EEPROMRW.WRResult = EEPROM_RW_NONE;
    return Result;
  }
}

void EEPROM_Write_In(void)
{
  uint8_t ACK;
  
  switch (EEPROMRW.State)
  {
    case EEPROM_WR_START  : IIC_Start();                                        //����IIC
                            EEPROMRW.WRState = EEPROM_RW_BUSY;                  //�ѿ���д�����
                            EEPROMRW.State   = EEPROM_WR_ADDR;                  //������д��ַ
                            EEPROMRW.Cnt     = 0;                               //�����ֽڼ�����
                            break;
                            
    case EEPROM_WR_ADDR   : IIC_Transmit_Data(EEPROMRW.WRAddr[EEPROMRW.Cnt]);   //д���ַ�ֽ�
    
                            do
                            {
                              ACK = IIC_Receive_ACK();
                            }
                            while (ACK == IIC_INVALID_ACK);                     //��ȡд����
                            
                            if (ACK == IIC_ACK)                                 //��ַ�ֽ�д��ɹ�
                            {
                              EEPROMRW.Cnt++;                                   //׼��д����һ�ֽڵ�ַ
                              if (EEPROMRW.Cnt >= EEPROMRW.WRAddrLen)           //��ַ��ȫ��д��
                              {
                                EEPROMRW.State   = EEPROM_WR_DATA;              //���������
                                EEPROMRW.Cnt     = 0;                           //�����ֽڼ�����
                              }
                            }
                            else                                                //��ַ�ֽ�д��ʧ��
                            {
                              EEPROMRW.State = EEPROM_WR_STOP;                  //ֹͣд�����
                              EEPROMRW.WRResult = EEPROM_RW_FAIL;               //д��ʧ��
                            }
                            break;
                            
    case EEPROM_WR_DATA   : IIC_Transmit_Data(EEPROMRW.WRData[EEPROMRW.Cnt]);   //д�������ֽ�
    
                            do
                            {
                              ACK = IIC_Receive_ACK();
                            }
                            while (ACK == IIC_INVALID_ACK);                     //��ȡд����
                            
                            if (ACK == IIC_ACK)                                 //�����ֽ�д��ɹ�
                            {
                              EEPROMRW.Cnt++;                                   //׼��д����һ�ֽ�����
                              if (EEPROMRW.Cnt >= EEPROMRW.WRDataLen)           //������ȫ��д��
                              {
                                EEPROMRW.State    = EEPROM_WR_STOP;             //����ֹֹͣͣ�źż����������д�����
                                EEPROMRW.WRResult = EEPROM_RW_DONE;             //д��ɹ�
                              }
                            }
                            else                                                //�����ֽ�д��ʧ��
                            {
                              EEPROMRW.State    = EEPROM_WR_STOP;               //ֹͣд�����
                              EEPROMRW.WRResult = EEPROM_RW_FAIL;               //д��ʧ��
                            }
                            break;
                            
    case EEPROM_WR_STOP   : IIC_Stop();                                         //ֹͣIIC
                            EEPROMRW.WRState = EEPROM_RW_IDLE;                  //д����̽���,�ص�����״̬
                            if (EEPROMRW.RDState == EEPROM_RW_REQ)              //������������������
                              EEPROMRW.State = EEPROM_RD_START;
                            else                                                //����EEPROM�������״̬
                              EEPROMRW.State = EEPROM_IDLE;
                            break;
                            
    default               : EEPROM_Init();                                      //�������д�����,�����³�ʼ��
                            break;
  }
}

EEPROMErrEnum EEPROM_Instant_Byte_Read(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t *pData)
{
  uint8_t i;
  uint8_t ACK;
  uint8_t AddrLen;
  uint8_t Addr[3];
  
  //׼����ַ
  if (EEPROMRW.State != EEPROM_IDLE)
    return EEPROM_BUSY;
    
  if (DeviceAddr > 0x07)
    return EEPROM_INVALID_DEVICE_ADDR;
  
  if (DataAddr > EEPROM_MAX_DATA_ADDR)
    return EEPROM_INVALID_DATA_ADDR;
  
  #if   defined EEPROM_DATA_ADDR_2_BYTE
    AddrLen = 3;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    Addr[1] = (uint8_t)(DataAddr >> 8);
    Addr[2] = (uint8_t)DataAddr;
        
  #elif defined EEPROM_DATA_ADDR_2_BYTE_MIXED
    #if   defined EEPROM_24C04    //24C04ֻ��A2��A1����  
      DeviceAddr &= 0x06;
    #elif defined EEPROM_24C08    //24C08ֻ��A2����
      DeviceAddr &= 0x04;
    #elif defined EEPROM_24C16    //24C16û�����õ�ַ����
      DeviceAddr  = 0x00;
    #else
      #error Incorrect EEPROM device definition
    #endif

    AddrLen = 2;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (((uint8_t)(DataAddr >> 8) | DeviceAddr) << 1);    
    Addr[1] = (uint8_t)DataAddr;

  #elif defined EEPROM_DATA_ADDR_1_BYTE   
    AddrLen = 2;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    Addr[1] = (uint8_t)DataAddr;   

  #else
    #error Incorrect EEPROM device definition
    
  #endif    
  
  //����IIC
  IIC_Start();
  
  //���͵�ַ
  for (i = 0; i < AddrLen; i++)
  {
    IIC_Transmit_Data(Addr[i]);
    
    do
    {
      ACK = IIC_Receive_ACK();
    }
    while (ACK == IIC_INVALID_ACK);
    
    if (ACK != IIC_ACK)
    {
      IIC_Stop();
      return EEPROM_NO_RESPONSE;
    }
  }
  
  //��������IIC
  IIC_Start();
  
  //�����ȡEEPROM
  Addr[0] |= EEPROM_DEVICE_ADDR_RD;
  IIC_Transmit_Data(Addr[0]);
  
  do
  {
    ACK = IIC_Receive_ACK();
  }
  while (ACK == IIC_INVALID_ACK);
  
  if (ACK != IIC_ACK)
  {
    IIC_Stop();
    return EEPROM_NO_RESPONSE;
  }
  
  //��ȡ����
  *pData = IIC_Receive_Data();
  IIC_Transmit_ACK(IIC_NAK);
  
  //ֹͣIIC
  IIC_Stop();
  
  //�������
  return EEPROM_OK;
}

EEPROMErrEnum EEPROM_Instant_Sequential_Read(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t *pData, uint8_t Len)
{
  uint8_t i;
  uint8_t ACK;
  uint8_t AddrLen;
  uint8_t Addr[3];
  
  //׼����ַ
  if (EEPROMRW.State != EEPROM_IDLE)
    return EEPROM_BUSY;
    
  if (DeviceAddr > 0x07)
    return EEPROM_INVALID_DEVICE_ADDR;
  
  if (DataAddr > EEPROM_MAX_DATA_ADDR)
    return EEPROM_INVALID_DATA_ADDR;
    
    if ((EEPROM_MAX_DATA_ADDR - DataAddr + 1 < Len) || (Len == 0))
    return EEPROM_DATA_LENGTH_ERR;
  
  #if   defined EEPROM_DATA_ADDR_2_BYTE
    AddrLen = 3;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    Addr[1] = (uint8_t)(DataAddr >> 8);
    Addr[2] = (uint8_t)DataAddr;
        
  #elif defined EEPROM_DATA_ADDR_2_BYTE_MIXED
    #if   defined EEPROM_24C04    //24C04ֻ��A2��A1����  
      DeviceAddr &= 0x06;
    #elif defined EEPROM_24C08    //24C08ֻ��A2����
      DeviceAddr &= 0x04;
    #elif defined EEPROM_24C16    //24C16û�����õ�ַ����
      DeviceAddr  = 0x00;
    #else
      #error Incorrect EEPROM device definition
    #endif

    AddrLen = 2;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (((uint8_t)(DataAddr >> 8) | DeviceAddr) << 1);    
    Addr[1] = (uint8_t)DataAddr;

  #elif defined EEPROM_DATA_ADDR_1_BYTE   
    AddrLen = 2;
    Addr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    Addr[1] = (uint8_t)DataAddr;   

  #else
    #error Incorrect EEPROM device definition
    
  #endif    
  
  //����IIC
  IIC_Start();
  
  //���͵�ַ
  for (i = 0; i < AddrLen; i++)
  {
    IIC_Transmit_Data(Addr[i]);
    
    do
    {
      ACK = IIC_Receive_ACK();
    }
    while (ACK == IIC_INVALID_ACK);
    
    if (ACK != IIC_ACK)
    {
      IIC_Stop();
      return EEPROM_NO_RESPONSE;
    }
  }
  
  //��������IIC
  IIC_Start();
  
  //�����ȡEEPROM
  Addr[0] |= EEPROM_DEVICE_ADDR_RD;
  IIC_Transmit_Data(Addr[0]);
  
  do
  {
    ACK = IIC_Receive_ACK();
  }
  while (ACK == IIC_INVALID_ACK);
  
  if (ACK != IIC_ACK)
  {
    IIC_Stop();
    return EEPROM_NO_RESPONSE;
  }
  
  //��ȡ����
  for (i = 0; i < Len - 1; i++)
  {
    pData[i] = IIC_Receive_Data();
    IIC_Transmit_ACK(IIC_ACK);
  }

  pData[i] = IIC_Receive_Data();
  IIC_Transmit_ACK(IIC_NAK);
  
  //ֹͣIIC
  IIC_Stop();
  
  //�������
  return EEPROM_OK;
}

EEPROMErrEnum EEPROM_Byte_Read(uint8_t DeviceAddr, uint16_t DataAddr)
{
  if (EEPROMRW.RDState != EEPROM_RW_IDLE)
    return EEPROM_BUSY;
    
  if (DeviceAddr > 0x07)
    return EEPROM_INVALID_DEVICE_ADDR;
  
  if (DataAddr > EEPROM_MAX_DATA_ADDR)
    return EEPROM_INVALID_DATA_ADDR;

  #if   defined EEPROM_DATA_ADDR_2_BYTE
    EEPROMRW.RDAddrLen = 3;
    EEPROMRW.RDAddr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    EEPROMRW.RDAddr[1] = (uint8_t)(DataAddr >> 8);
    EEPROMRW.RDAddr[2] = (uint8_t)DataAddr;
        
  #elif defined EEPROM_DATA_ADDR_2_BYTE_MIXED
    #if   defined EEPROM_24C04    //24C04ֻ��A2��A1����  
      DeviceAddr &= 0x06;
    #elif defined EEPROM_24C08    //24C08ֻ��A2����
      DeviceAddr &= 0x04;
    #elif defined EEPROM_24C16    //24C16û�����õ�ַ����
      DeviceAddr  = 0x00;
    #else
      #error Incorrect EEPROM device definition
    #endif

    EEPROMRW.RDAddrLen = 2;
    EEPROMRW.RDAddr[0] = EEPROM_DEVICE_ADDR_WR | (((uint8_t)(DataAddr >> 8) | DeviceAddr) << 1);    
    EEPROMRW.RDAddr[1] = (uint8_t)DataAddr;

  #elif defined EEPROM_DATA_ADDR_1_BYTE   
    EEPROMRW.RDAddrLen = 2;
    EEPROMRW.RDAddr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    EEPROMRW.RDAddr[1] = (uint8_t)DataAddr;   

  #else
    #error Incorrect EEPROM device definition
    
  #endif
  
  EEPROMRW.RDDataLen = 1;
  
  EEPROMRW.RDResult = EEPROM_RW_IN_PROGRESS;
  
  EEPROMRW.RDState = EEPROM_RW_REQ;
  if (EEPROMRW.State == EEPROM_IDLE)
    EEPROMRW.State = EEPROM_RD_START;
    
  return EEPROM_OK;
}

EEPROMErrEnum EEPROM_Sequential_Read(uint8_t DeviceAddr, uint16_t DataAddr, uint8_t Len)
{
  if (EEPROMRW.RDState != EEPROM_RW_IDLE)
    return EEPROM_BUSY;
    
  if (DeviceAddr > 0x07)
    return EEPROM_INVALID_DEVICE_ADDR;
  
  if (DataAddr > EEPROM_MAX_DATA_ADDR)
    return EEPROM_INVALID_DATA_ADDR;
    
  if ((EEPROM_MAX_DATA_ADDR - DataAddr + 1 < Len) || (Len == 0))
    return EEPROM_DATA_LENGTH_ERR;

  #if   defined EEPROM_DATA_ADDR_2_BYTE
    EEPROMRW.RDAddrLen = 3;
    EEPROMRW.RDAddr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    EEPROMRW.RDAddr[1] = (uint8_t)(DataAddr >> 8);
    EEPROMRW.RDAddr[2] = (uint8_t)DataAddr;
        
  #elif defined EEPROM_DATA_ADDR_2_BYTE_MIXED
    #if   defined EEPROM_24C04    //24C04ֻ��A2��A1����  
      DeviceAddr &= 0x06;
    #elif defined EEPROM_24C08    //24C08ֻ��A2����
      DeviceAddr &= 0x04;
    #elif defined EEPROM_24C16    //24C16û�����õ�ַ����
      DeviceAddr  = 0x00;
    #else
      #error Incorrect EEPROM device definition
    #endif

    EEPROMRW.RDAddrLen = 2;
    EEPROMRW.RDAddr[0] = EEPROM_DEVICE_ADDR_WR | (((uint8_t)(DataAddr >> 8) | DeviceAddr) << 1);    
    EEPROMRW.RDAddr[1] = (uint8_t)DataAddr;

  #elif defined EEPROM_DATA_ADDR_1_BYTE   
    EEPROMRW.RDAddrLen = 2;
    EEPROMRW.RDAddr[0] = EEPROM_DEVICE_ADDR_WR | (DeviceAddr << 1);
    EEPROMRW.RDAddr[1] = (uint8_t)DataAddr;   

  #else
    #error Incorrect EEPROM device definition
    
  #endif
  
  EEPROMRW.RDDataLen = Len;
  
  EEPROMRW.RDResult = EEPROM_RW_IN_PROGRESS;
  
  EEPROMRW.RDState = EEPROM_RW_REQ;
  if (EEPROMRW.State == EEPROM_IDLE)
    EEPROMRW.State = EEPROM_RD_START;
    
  return EEPROM_OK;
}

EEPROMRWResultEnum EEPROM_Get_Read_Result(void)
{
  EEPROMRWResultEnum Result;
  
  if (EEPROMRW.RDState == EEPROM_RW_BUSY)
    return EEPROM_RW_IN_PROGRESS;
  else
  {
    Result = EEPROMRW.RDResult;
    if ((Result != EEPROM_RW_DONE) && (Result != EEPROM_RW_IN_PROGRESS))
      EEPROMRW.RDResult = EEPROM_RW_NONE;
    return Result;
  }
}

uint8_t EEPROM_Get_Read_Out_Byte(void)
{
  if (EEPROMRW.RDResult == EEPROM_RW_DONE)
    EEPROMRW.RDResult = EEPROM_RW_NONE;
  
  return EEPROMRW.RDData[0];
}

void EEPROM_Get_Read_Out(uint8_t *pData, uint8_t Len)
{
  uint8_t i;
  
  if (EEPROMRW.RDResult == EEPROM_RW_DONE)
    EEPROMRW.RDResult = EEPROM_RW_NONE;
  
  if (Len > EEPROMRW.RDDataLen)
    Len = EEPROMRW.RDDataLen;
  
  for (i = 0; i < Len; i++)
    pData[i] = EEPROMRW.RDData[i];
}

void EEPROM_Read_Out(void)
{
  uint8_t ACK;

  switch (EEPROMRW.State)
  {
    case EEPROM_RD_START    : IIC_Start();                                        //����IIC
                              EEPROMRW.RDState = EEPROM_RW_BUSY;                  //�ѿ���д�����
                              EEPROMRW.State   = EEPROM_RD_ADDR1;                 //���������ö������ݵ�ַ
                              EEPROMRW.Cnt     = 0;                               //�����ֽڼ�����
                              break;
                            
    case EEPROM_RD_ADDR1    : IIC_Transmit_Data(EEPROMRW.RDAddr[EEPROMRW.Cnt]);   //д���ַ�ֽ�
      
                              do
                              {
                                ACK = IIC_Receive_ACK();
                              }
                              while (ACK == IIC_INVALID_ACK);                     //��ȡд����
                              
                              if (ACK == IIC_ACK)                                 //��ַ�ֽ�д��ɹ�
                              {
                                EEPROMRW.Cnt++;                                   //׼��д����һ�ֽڵ�ַ
                                if (EEPROMRW.Cnt >= EEPROMRW.RDAddrLen)           //��ַ��ȫ��д��
                                  EEPROMRW.State   = EEPROM_RD_RESTART;           //��������������IIC
                              }
                              else                                                //��ַ�ֽ�д��ʧ��
                              {
                                EEPROMRW.State = EEPROM_RD_STOP;                  //ֹͣ��������
                                EEPROMRW.RDResult = EEPROM_RW_FAIL;               //����ʧ��
                              }
                              break;
                            
    case EEPROM_RD_RESTART  : IIC_Start();                                        //��������IIC
                              EEPROMRW.State = EEPROM_RD_ADDR2;                   //����������������ַ��תΪ��ģʽ
                              EEPROMRW.RDAddr[0] |= EEPROM_DEVICE_ADDR_RD;
                              break;
                            
    case EEPROM_RD_ADDR2    : IIC_Transmit_Data(EEPROMRW.RDAddr[0]);              //д����������ַ
      
                              do
                              {
                                ACK = IIC_Receive_ACK();
                              }
                              while (ACK == IIC_INVALID_ACK);                     //��ȡд����
                              
                              if (ACK == IIC_ACK)                                 //��ַ�ֽ�д��ɹ�
                              {
                                EEPROMRW.State = EEPROM_RD_DATA;                  //��������ȡ����
                                EEPROMRW.Cnt   = 0;                               //�����ֽڼ�����
                              }
                              else                                                //��������ַд��ʧ��
                              {
                                EEPROMRW.State = EEPROM_RD_STOP;                  //ֹͣ��������
                                EEPROMRW.RDResult = EEPROM_RW_FAIL;               //����ʧ��
                              }
                              break; 
                              
    case EEPROM_RD_DATA    :  EEPROMRW.RDData[EEPROMRW.Cnt] = IIC_Receive_Data(); //���������ֽ�                              
                              EEPROMRW.Cnt++;                                     //׼��������һ�ֽ�
                              if(EEPROMRW.Cnt >= EEPROMRW.RDDataLen)              //�Ѿ������һ�ֽ���
                              {
                                IIC_Transmit_ACK(IIC_NAK);                        //���һ�ֽڷ�NAK
                                EEPROMRW.State    = EEPROM_RD_STOP;               //����ֹֹͣͣ�źż������������������
                                EEPROMRW.RDResult = EEPROM_RW_DONE;               //�����ɹ�
                              }
                              else
                                IIC_Transmit_ACK(IIC_ACK);                        //�������һ�ֽ���ACK
                              
                              break;
                              
    case EEPROM_RD_STOP     : IIC_Stop();                                         //ֹͣIIC
                              EEPROMRW.RDState = EEPROM_RW_IDLE;                  //�������̽���,�ص�����״̬
                              if (EEPROMRW.WRState == EEPROM_RW_REQ)              //���������������
                                EEPROMRW.State = EEPROM_WR_START;
                              else                                                //����EEPROM�������״̬
                                EEPROMRW.State = EEPROM_IDLE;
                              break;
                            
    default                 : EEPROM_Init();                                      //������Ķ�������,�����³�ʼ��
                              break;
  }
}

void EEPROM_Init(void)
{
  EEPROMRW.State    = EEPROM_IDLE;
  EEPROMRW.WRState  = EEPROM_RW_IDLE;
  EEPROMRW.WRResult = EEPROM_RW_NONE;
  EEPROMRW.RDState  = EEPROM_RW_IDLE;
  EEPROMRW.RDResult = EEPROM_RW_NONE;
}

void EEPROM_RW_Service(void)
{
  if (EEPROMRW.State == EEPROM_IDLE)
    return;
  else if (EEPROMRW.State & EEPROM_WR)
    EEPROM_Write_In();
  else if (EEPROMRW.State & EEPROM_RD)
    EEPROM_Read_Out();
  else
    EEPROM_Init();
}