Beispiel #1
0
uint32_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead)
{

  /* While the bus is busy */
  sEETimeout = sEE_LONG_TIMEOUT;
  while(I2C_GetFlagStatus( I2C_FLAG_BUSBUSY))
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  }

  /* Send START condition */
  I2C_GenerateSTART(ENABLE);

  /* Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
  sEETimeout = sEE_FLAG_TIMEOUT;
  while(!I2C_CheckEvent( I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  }

  /* Send EEPROM address for write */
  I2C_Send7bitAddress( (uint8_t)sEEAddress, I2C_DIRECTION_TX);

  /* Test on EV6 and clear it */
  sEETimeout = sEE_FLAG_TIMEOUT;
  while(!I2C_CheckEvent( I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  } 

#ifdef sEE_M24C64_32

  /* Send the EEPROM's internal address to read from: MSB of the address first */
  I2C_SendData( (uint8_t)((ReadAddr & 0xFF00) >> 8));    

  /* Test on EV8 and clear it */
  sEETimeout = sEE_FLAG_TIMEOUT;
  while(!I2C_CheckEvent( I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  }
#endif /* sEE_M24C64_32 */
  /* Send the EEPROM's internal address to read from: LSB of the address */
  I2C_SendData( (uint8_t)(ReadAddr & 0x00FF));    



  /* Test on EV8 and clear it */
  sEETimeout = sEE_FLAG_TIMEOUT;
  while(I2C_GetFlagStatus(I2C_FLAG_TRANSFERFINISHED) == RESET)
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  }
  
  /* Send START condition a second time */  
  I2C_GenerateSTART( ENABLE);
  
  /* Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
  sEETimeout = sEE_FLAG_TIMEOUT;
  while(!I2C_CheckEvent( I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  } 
  
  /* Send EEPROM address for read */
  I2C_Send7bitAddress((uint8_t)sEEAddress, I2C_DIRECTION_RX);
  if ((uint16_t)(NumByteToRead)> 2)
  {
    sEETimeout = sEE_FLAG_TIMEOUT;
    while(!I2C_GetFlagStatus( I2C_FLAG_ADDRESSSENTMATCHED))
    {
      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
    } 
    I2C->SR3;
    /* Read data from first byte until byte N-3 */
    while ((uint16_t)(NumByteToRead)> 3) 
      {
        
        
        /* Poll on BTF */
        sEETimeout = sEE_FLAG_TIMEOUT;
        while (I2C_GetFlagStatus( I2C_FLAG_TRANSFERFINISHED) == RESET)
        {
          if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
        } 
  
        /* Read a byte from the EEPROM */
        *pBuffer = I2C_ReceiveData();
  
        /* Point to the next location where the byte read will be saved */
        pBuffer++;
  
        /* Decrement the read bytes counter */
        (uint16_t)(NumByteToRead)--;
      }
  //}
  /*  Remains three data for read: data N-2, data N-1, Data N */
  /* Three Bytes Master Reception procedure (POLLING) ------------------------*/
 // if ((uint16_t)(*NumByteToRead) == 3)  
  //{
    /* Data N-2 in DR and data N -1 in shift register */
    /* Poll on BTF */
      sEETimeout = sEE_FLAG_TIMEOUT;
      while (I2C_GetFlagStatus( I2C_FLAG_TRANSFERFINISHED) == RESET)
      {
        if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
      } 

      /* Clear ACK */
      I2C_AcknowledgeConfig(I2C_ACK_NONE);

      /* Call User callback for critical section start (should typically disable interrupts) */
      sEE_EnterCriticalSection_UserCallback();

      /* Read Data N-2 */
      *pBuffer = I2C_ReceiveData();

      /* Point to the next location where the byte read will be saved */
      pBuffer++;

      /* Program the STOP */
      I2C_GenerateSTOP(ENABLE);

      /* Read DataN-1 */
      *pBuffer = I2C_ReceiveData();

       /* Call User callback for critical section end (should typically re-enable interrupts) */
       sEE_ExitCriticalSection_UserCallback();

      /* Point to the next location where the byte read will be saved */
      pBuffer++;

      /* Poll on RxNE */
      sEETimeout = sEE_FLAG_TIMEOUT;
      while (I2C_GetFlagStatus( I2C_FLAG_RXNOTEMPTY) == RESET)
      {
        if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
      }
      /* Read DataN */
      *pBuffer = I2C_ReceiveData();

      /* Reset the number of bytes to be read from the EEPROM */
      NumByteToRead = 0;
      return sEE_OK;
    }
  
  /* If number of data to be read is 2 */
  /* Tow Bytes Master Reception procedure (POLLING) ---------------------------*/
  if ((uint16_t)(NumByteToRead) == 2)
  {
    /* Enable acknowledgement on next byte (set POS and ACK bits)*/
    I2C_AcknowledgeConfig(I2C_ACK_NEXT);
    
    /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
    sEETimeout = sEE_FLAG_TIMEOUT;
    while(I2C_GetFlagStatus( I2C_FLAG_ADDRESSSENTMATCHED) == RESET)
    {
      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
    }
    
    /* Clear ADDR register by reading SR1 then SR3 register (SR1 has already been read) */
     (void)I2C->SR3;
        
    /* Disable Acknowledgement */
    I2C_AcknowledgeConfig(I2C_ACK_NONE);
    
    /* Wait for BTF flag to be set */
      sEETimeout = sEE_FLAG_TIMEOUT;
      while (I2C_GetFlagStatus( I2C_FLAG_TRANSFERFINISHED) == RESET)
      {
        if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
      } 
    
    /* Call User callback for critical section start (should typically disable interrupts) */
    sEE_EnterCriticalSection_UserCallback();
    
    /* Program the STOP */
      I2C_GenerateSTOP(ENABLE);
      
    /* Read Data N-1 */
      *pBuffer = I2C_ReceiveData();

      /* Point to the next location where the byte read will be saved */
      pBuffer++;  
           
    /* Call User callback for critical section end (should typically re-enable interrupts) */
       sEE_ExitCriticalSection_UserCallback();
       
    /* Read Data N */
      *pBuffer = I2C_ReceiveData();
          
    /* Reset the number of bytes to be read from the EEPROM */
      NumByteToRead = 0; 
      
      return sEE_OK;
  }
  
  /* If number of data to be read is 1 */
  /* One Byte Master Reception procedure (POLLING) ---------------------------*/
  if ((uint16_t)(NumByteToRead) < 2)
  {
    /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
    sEETimeout = sEE_FLAG_TIMEOUT;
    while(I2C_GetFlagStatus( I2C_FLAG_ADDRESSSENTMATCHED) == RESET)
    {
      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
    } 
       
    /* Disable Acknowledgement */
    I2C_AcknowledgeConfig(I2C_ACK_NONE);   

    /* Call User callback for critical section start (should typically disable interrupts) */
    sEE_EnterCriticalSection_UserCallback();
    
    /* Clear ADDR register by reading SR1 then SR3 register (SR1 has already been read) */
    (void)I2C->SR3;
    
    /* Send STOP Condition */
    I2C_GenerateSTOP( ENABLE);
   
    /* Call User callback for critical section end (should typically re-enable interrupts) */
    sEE_ExitCriticalSection_UserCallback();
    
    /* Wait for the byte to be received */
    sEETimeout = sEE_FLAG_TIMEOUT;
    while(I2C_GetFlagStatus( I2C_FLAG_RXNOTEMPTY) == RESET)
    {
      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
    }
    
    /* Read the byte received from the EEPROM */
    *pBuffer = I2C_ReceiveData();
    
    /* Decrement the read bytes counter */
    (uint16_t)(NumByteToRead)--;        
    
    /* Wait to make sure that STOP control bit has been cleared */
    sEETimeout = sEE_FLAG_TIMEOUT;
    while(I2C->CR2 & I2C_CR2_STOP)
    {
      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
    }  
    
    /* Re-Enable Acknowledgement to be ready for another reception */
    I2C_AcknowledgeConfig( I2C_ACK_CURR);    
  }
  /* If all operations OK, return sEE_OK (0) */
  return sEE_OK;  
}
Beispiel #2
0
/**
  * @brief  Reads a block of data from the EEPROM.
  * @param  pBuffer : pointer to the buffer that receives the data read from
  *         the EEPROM.
  * @param  ReadAddr : EEPROM's internal address to start reading from.
  * @param  NumByteToRead : pointer to the variable holding number of bytes to
  *         be read from the EEPROM.
  *
  *        @note The variable pointed by NumByteToRead is reset to 0 when all the
  *              data are read from the EEPROM. Application should monitor this
  *              variable in order know when the transfer is complete.
  *
  * @note When number of data to be read is higher than 1, this function just
  *       configures the communication and enable the DMA channel to transfer data.
  *       Meanwhile, the user application may perform other tasks.
  *       When number of data to be read is 1, then the DMA is not used. The byte
  *       is read in polling mode.
  *
  * @retval sEE_OK (0) if operation is correctly performed, else return value
  *         different from sEE_OK (0) or the timeout user callback.
  */
uint32_t TWI_MasterWriteRead(new_twi* TwiStruct, unsigned int TransmitBytes, unsigned int ReceiveBytes)
{
	uint32_t sEETimeout;
	/* Set the pointer to the Number of data to be read. This pointer will be used
      by the DMA Transfer Completer interrupt Handler in order to reset the
      variable to 0. User should check on this variable in order to know if the
      DMA transfer has been complete or not. */
	uint16_t NumByteToRead = ReceiveBytes;
	I2C_TypeDef *I2Cx = sEE_I2C[TwiStruct->TwiNr];
	/* If bus is freeze we will reset the unit and restore the settings. */
	if(I2C_GetFlagStatus(sEE_I2C[TwiStruct->TwiNr], I2C_FLAG_AF | I2C_FLAG_ARLO) || (I2Cx->CR1 & (1 << 8))) {
		  /* sEE_I2C Peripheral Enable */
		I2C_TypeDef I2CxBack;
		I2CxBack.CR1 = I2Cx->CR1;
		I2CxBack.CR2 = I2Cx->CR2;
		I2CxBack.OAR1 = I2Cx->OAR1;
		I2CxBack.OAR2 = I2Cx->OAR2;
		I2CxBack.CCR = I2Cx->CCR;
		I2CxBack.TRISE = I2Cx->TRISE;
		I2C_SoftwareResetCmd(sEE_I2C[TwiStruct->TwiNr], ENABLE);
		I2C_SoftwareResetCmd(sEE_I2C[TwiStruct->TwiNr], DISABLE);
		I2Cx->TRISE = I2CxBack.TRISE;
		I2Cx->CCR = I2CxBack.CCR;
		I2Cx->OAR2 = I2CxBack.OAR2;
		I2Cx->OAR1 = I2CxBack.OAR1;
		I2Cx->CR2 = I2CxBack.CR2;
		I2Cx->CR1 = I2CxBack.CR1;
	}
  /*!< While the bus is busy */
	timer(TimerBusyTimeout);
	  timer_interval(&TimerBusyTimeout, TwiStruct->BusyTimeOut);
	  timer_enable(&TimerBusyTimeout);
	  while(I2C_GetFlagStatus(sEE_I2C[TwiStruct->TwiNr], I2C_FLAG_BUSY))
	  {
		  if(timer_tick(&TimerBusyTimeout)) {
				I2C_TypeDef I2CxBack;
				I2CxBack.CR1 = I2Cx->CR1;
				I2CxBack.CR2 = I2Cx->CR2;
				I2CxBack.OAR1 = I2Cx->OAR1;
				I2CxBack.OAR2 = I2Cx->OAR2;
				I2CxBack.CCR = I2Cx->CCR;
				I2CxBack.TRISE = I2Cx->TRISE;
				I2C_SoftwareResetCmd(sEE_I2C[TwiStruct->TwiNr], ENABLE);
				I2C_SoftwareResetCmd(sEE_I2C[TwiStruct->TwiNr], DISABLE);
				I2Cx->TRISE = I2CxBack.TRISE;
				I2Cx->CCR = I2CxBack.CCR;
				I2Cx->OAR2 = I2CxBack.OAR2;
				I2Cx->OAR1 = I2CxBack.OAR1;
				I2Cx->CR2 = I2CxBack.CR2;
				I2Cx->CR1 = I2CxBack.CR1;
				break;
			}
	  }
	  unsigned int cnt = 0;
	  if(!TwiStruct->NoSendWriteOnRead)
	  {
			  /*!< Send START condition */
		  I2C_GenerateSTART(sEE_I2C[TwiStruct->TwiNr], ENABLE);

		  /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
		  sEETimeout = sEE_FLAG_TIMEOUT;
		  while(!I2C_CheckEvent(sEE_I2C[TwiStruct->TwiNr], I2C_EVENT_MASTER_MODE_SELECT))
		  {
				if((sEETimeout--) == 0) {
					return false;
				}
		  }

		  /*!< Send EEPROM address for write */
		  I2C_Send7bitAddress(sEE_I2C[TwiStruct->TwiNr], TwiStruct->MasterSlaveAddr << 1, I2C_Direction_Transmitter);

		  /*!< Test on EV6 and clear it */
		  sEETimeout = sEE_FLAG_TIMEOUT;
		  while(!I2C_CheckEvent(sEE_I2C[TwiStruct->TwiNr], I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
		  {
				if((sEETimeout--) == 0) {
					return false;
				}
		  }


		  for(; cnt < TransmitBytes; cnt++)
		  {
			  /*!< Send the EEPROM's internal address to read from: MSB of the address first */
			  I2C_SendData(sEE_I2C[TwiStruct->TwiNr], TwiStruct->TxBuff[cnt]);

			  /*!< Test on EV8 and clear it */
			  sEETimeout = sEE_FLAG_TIMEOUT;
			  while(!I2C_CheckEvent(sEE_I2C[TwiStruct->TwiNr], I2C_EVENT_MASTER_BYTE_TRANSMITTED))
			  {
					if((sEETimeout--) == 0) {
						return false;
					}
			  }
		  }
	  }

  if(ReceiveBytes) {
	  /* If number of data to be read is 1, then DMA couldn't be used */
	  /* One Byte Master Reception procedure (POLLING) ---------------------------*/
	  if (NumByteToRead < 2)
	  {
		  /*!< Send STRAT condition a second time */
		  I2C_GenerateSTART(sEE_I2C[TwiStruct->TwiNr], ENABLE);

		  /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
		  sEETimeout = sEE_FLAG_TIMEOUT;
		  while(!I2C_CheckEvent(sEE_I2C[TwiStruct->TwiNr], I2C_EVENT_MASTER_MODE_SELECT))
		  {
				if((sEETimeout--) == 0) {
					return false;
				}
		  }

		  /*!< Send EEPROM address for read */
		  I2C_Send7bitAddress(sEE_I2C[TwiStruct->TwiNr], TwiStruct->MasterSlaveAddr << 1, I2C_Direction_Receiver);

		/* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
		sEETimeout = sEE_FLAG_TIMEOUT;
		while(I2C_GetFlagStatus(sEE_I2C[TwiStruct->TwiNr], I2C_FLAG_ADDR) == RESET)
		{
			if((sEETimeout--) == 0) {
				return false;
			}
		}

		/*!< Disable Acknowledgement */
		I2C_AcknowledgeConfig(sEE_I2C[TwiStruct->TwiNr], DISABLE);

		/* Call User callback for critical section start (should typically disable interrupts) */
		sEE_EnterCriticalSection_UserCallback();

		/* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
		(void)sEE_I2C[TwiStruct->TwiNr]->SR2;

		/*!< Send STOP Condition */
		I2C_GenerateSTOP(sEE_I2C[TwiStruct->TwiNr], ENABLE);

		/* Call User callback for critical section end (should typically re-enable interrupts) */
		sEE_ExitCriticalSection_UserCallback();

		/* Wait for the byte to be received */
		sEETimeout = sEE_FLAG_TIMEOUT;
		while(I2C_GetFlagStatus(sEE_I2C[TwiStruct->TwiNr], I2C_FLAG_RXNE) == RESET)
		{
			if((sEETimeout--) == 0) {
				return false;
			}
		}

		/*!< Read the byte received from the EEPROM */
		*TwiStruct->RxBuff = I2C_ReceiveData(sEE_I2C[TwiStruct->TwiNr]);

		/*!< Decrement the read bytes counter */
		NumByteToRead--;

		/* Wait to make sure that STOP control bit has been cleared */
		sEETimeout = sEE_FLAG_TIMEOUT;
		while(sEE_I2C[TwiStruct->TwiNr]->CR1 & I2C_CR1_STOP)
		{
			if((sEETimeout--) == 0) {
				return false;
			}
		}

		/*!< Re-Enable Acknowledgement to be ready for another reception */
		I2C_AcknowledgeConfig(sEE_I2C[TwiStruct->TwiNr], ENABLE);
	  }
	  else/* More than one Byte Master Reception procedure (DMA) -----------------*/
	  {
		  /*!< Send STRAT condition a second time */
		  I2C_GenerateSTART(sEE_I2C[TwiStruct->TwiNr], ENABLE);

		  /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
		  sEETimeout = sEE_FLAG_TIMEOUT;
		  while(!I2C_CheckEvent(sEE_I2C[TwiStruct->TwiNr], I2C_EVENT_MASTER_MODE_SELECT))
		  {
				if((sEETimeout--) == 0) {
					return false;
				}
		  }

		  /*!< Send EEPROM address for read */
		  I2C_Send7bitAddress(sEE_I2C[TwiStruct->TwiNr], TwiStruct->MasterSlaveAddr << 1, I2C_Direction_Receiver);

		  /* If number of data to be read is 1, then DMA couldn't be used */
		  /* One Byte Master Reception procedure (POLLING) ---------------------------*/
		  //if (NumByteToRead < 2)
		  //{
			/* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
			sEETimeout = sEE_FLAG_TIMEOUT;
			while(I2C_GetFlagStatus(sEE_I2C[TwiStruct->TwiNr], I2C_FLAG_ADDR) == RESET)
			{
				if((sEETimeout--) == 0) {
					return false;
				}
			}
			(void)sEE_I2C[TwiStruct->TwiNr]->SR2;

			  cnt = 0;
			  for(; cnt < ReceiveBytes; cnt++)
			  {
				if(cnt == ReceiveBytes - 1)
				{
					/*!< Disable Acknowledgement */
					I2C_AcknowledgeConfig(sEE_I2C[TwiStruct->TwiNr], DISABLE);

					/* Call User callback for critical section start (should typically disable interrupts) */
					sEE_EnterCriticalSection_UserCallback();

					/* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
					(void)sEE_I2C[TwiStruct->TwiNr]->SR2;

					/*!< Send STOP Condition */
					I2C_GenerateSTOP(sEE_I2C[TwiStruct->TwiNr], ENABLE);

					/* Call User callback for critical section end (should typically re-enable interrupts) */
					sEE_ExitCriticalSection_UserCallback();
				}

				/* Wait for the byte to be received */
				sEETimeout = sEE_FLAG_TIMEOUT;
				while(I2C_GetFlagStatus(sEE_I2C[TwiStruct->TwiNr], I2C_FLAG_RXNE) == RESET)
				{
					if((sEETimeout--) == 0) {
						return false;
					}
				}

				/*!< Read the byte received from the EEPROM */
				TwiStruct->RxBuff[cnt] = I2C_ReceiveData(sEE_I2C[TwiStruct->TwiNr]);
			  }

			/* Wait to make sure that STOP control bit has been cleared */
			sEETimeout = sEE_FLAG_TIMEOUT;
			while(sEE_I2C[TwiStruct->TwiNr]->CR1 & I2C_CR1_STOP)
			{
				if((sEETimeout--) == 0) {
					return false;
				}
			}

			/*!< Re-Enable Acknowledgement to be ready for another reception */
			I2C_AcknowledgeConfig(sEE_I2C[TwiStruct->TwiNr], ENABLE);
	  }
  }
  else {
		/* Call User callback for critical section start (should typically disable interrupts) */
		sEE_EnterCriticalSection_UserCallback();

		/* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
		(void)sEE_I2C[TwiStruct->TwiNr]->SR2;

		/*!< Send STOP Condition */
		I2C_GenerateSTOP(sEE_I2C[TwiStruct->TwiNr], ENABLE);

		/* Call User callback for critical section end (should typically re-enable interrupts) */
		sEE_ExitCriticalSection_UserCallback();

		/* Wait for the byte to be received */
		sEETimeout = sEE_FLAG_TIMEOUT;
		while(I2C_GetFlagStatus(sEE_I2C[TwiStruct->TwiNr], I2C_FLAG_RXNE) == RESET)
		{
			if((sEETimeout--) == 0) {
				return true;
			}
		}

  }
  /* If all operations OK, return sEE_OK (0) */
  return true;
}
Beispiel #3
0
/**
  * @brief  Reads a block of data from the EEPROM.
  * @param  pBuffer : pointer to the buffer that receives the data read from 
  *         the EEPROM.
  * @param  ReadAddr : EEPROM's internal address to start reading from.
  * @param  NumByteToRead : pointer to the variable holding number of bytes to 
  *         be read from the EEPROM.
  * 
  *        @note The variable pointed by NumByteToRead is reset to 0 when all the 
  *              data are read from the EEPROM. Application should monitor this 
  *              variable in order know when the transfer is complete.
  * 
  * @note When number of data to be read is higher than 1, this function just 
  *       configures the communication and enable the DMA channel to transfer data.
  *       Meanwhile, the user application may perform other tasks.
  *       When number of data to be read is 1, then the DMA is not used. The byte
  *       is read in polling mode.
  * 
  * @retval sEE_OK (0) if operation is correctly performed, else return value 
  *         different from sEE_OK (0) or the timeout user callback.
  */
uint32_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead)
{  
  /* Set the pointer to the Number of data to be read. This pointer will be used 
      by the DMA Transfer Completer interrupt Handler in order to reset the 
      variable to 0. User should check on this variable in order to know if the 
      DMA transfer has been complete or not. */
  sEEDataReadPointer = NumByteToRead;
  
  /*!< While the bus is busy */
  sEETimeout = sEE_LONG_TIMEOUT;
  while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BUSY))
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  }
  
  /*!< Send START condition */
  I2C_GenerateSTART(sEE_I2C, ENABLE);
  
  /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
  sEETimeout = sEE_FLAG_TIMEOUT;
  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  }
  
  /*!< Send EEPROM address for write */
  I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Transmitter);

  /*!< Test on EV6 and clear it */
  sEETimeout = sEE_FLAG_TIMEOUT;
  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  } 

#ifdef sEE_M24C08  
  
  /*!< Send the EEPROM's internal address to read from: Only one byte address */
  I2C_SendData(sEE_I2C, ReadAddr);  

#elif defined (sEE_M24C64_32)

  /*!< Send the EEPROM's internal address to read from: MSB of the address first */
  I2C_SendData(sEE_I2C, (uint8_t)((ReadAddr & 0xFF00) >> 8));    

  /*!< Test on EV8 and clear it */
  sEETimeout = sEE_FLAG_TIMEOUT;
  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  }

  /*!< Send the EEPROM's internal address to read from: LSB of the address */
  I2C_SendData(sEE_I2C, (uint8_t)(ReadAddr & 0x00FF));    
  
#endif /*!< sEE_M24C08 */

  /*!< Test on EV8 and clear it */
  sEETimeout = sEE_FLAG_TIMEOUT;
  while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_BTF) == RESET)
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  }
  
  /*!< Send STRAT condition a second time */  
  I2C_GenerateSTART(sEE_I2C, ENABLE);
  
  /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
  sEETimeout = sEE_FLAG_TIMEOUT;
  while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_MODE_SELECT))
  {
    if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
  } 
  
  /*!< Send EEPROM address for read */
  I2C_Send7bitAddress(sEE_I2C, sEEAddress, I2C_Direction_Receiver);  
  
  /* If number of data to be read is 1, then DMA couldn't be used */
  /* One Byte Master Reception procedure (POLLING) ---------------------------*/
  if ((uint16_t)(*NumByteToRead) < 2)
  {
    /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
    sEETimeout = sEE_FLAG_TIMEOUT;
    while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_ADDR) == RESET)
    {
      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
    }     
    
    /*!< Disable Acknowledgement */
    I2C_AcknowledgeConfig(sEE_I2C, DISABLE);   

    /* Call User callback for critical section start (should typically disable interrupts) */
    sEE_EnterCriticalSection_UserCallback();
    
    /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
    (void)sEE_I2C->SR2;
    
    /*!< Send STOP Condition */
    I2C_GenerateSTOP(sEE_I2C, ENABLE);
   
    /* Call User callback for critical section end (should typically re-enable interrupts) */
    sEE_ExitCriticalSection_UserCallback();
    
    /* Wait for the byte to be received */
    sEETimeout = sEE_FLAG_TIMEOUT;
    while(I2C_GetFlagStatus(sEE_I2C, I2C_FLAG_RXNE) == RESET)
    {
      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
    }
    
    /*!< Read the byte received from the EEPROM */
    *pBuffer = I2C_ReceiveData(sEE_I2C);
    
    /*!< Decrement the read bytes counter */
    (uint16_t)(*NumByteToRead)--;        
    
    /* Wait to make sure that STOP control bit has been cleared */
    sEETimeout = sEE_FLAG_TIMEOUT;
    while(sEE_I2C->CR1 & I2C_CR1_STOP)
    {
      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
    }  
    
    /*!< Re-Enable Acknowledgement to be ready for another reception */
    I2C_AcknowledgeConfig(sEE_I2C, ENABLE);    
  }
  else/* More than one Byte Master Reception procedure (DMA) -----------------*/
  {
    /*!< Test on EV6 and clear it */
    sEETimeout = sEE_FLAG_TIMEOUT;
    while(!I2C_CheckEvent(sEE_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
    {
      if((sEETimeout--) == 0) return sEE_TIMEOUT_UserCallback();
    }  
    
    /* Configure the DMA Rx Channel with the buffer address and the buffer size */
    sEE_LowLevel_DMAConfig((uint32_t)pBuffer, (uint16_t)(*NumByteToRead), sEE_DIRECTION_RX);
    
    /* Inform the DMA that the next End Of Transfer Signal will be the last one */
    I2C_DMALastTransferCmd(sEE_I2C, ENABLE); 
    
    /* Enable the DMA Rx Channel */
    DMA_Cmd(sEE_I2C_DMA_CHANNEL_RX, ENABLE);  
  }
  
  /* If all operations OK, return sEE_OK (0) */
  return sEE_OK;
}