I2C_StatusType I2C_Mem_Read(I2C_Type* I2Cx, uint8_t SlaAddr, uint32_t ReadAddr, uint8_t ReadAddrSize, uint8_t *pBuffer, uint16_t NumByteToRead, uint32_t Timeout)
{
/* Wait until BUSY flag is reset */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BUSYF, SET, I2C_EVT_CHECK_NONE, I2C_TIMEOUT_BUSY_FLAG) != I2C_OK)
{
return I2C_ERROR_STEP_1;
}
/* Disable Pos */
I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current);
/* Enable Acknowledge */
I2C_AcknowledgeConfig(I2Cx, ENABLE);
/* Send START condition */
I2C_GenerateSTART(I2Cx, ENABLE);
/* Wait until SB flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_STARTF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_2;
}
/* Send slave address for write */
I2C_Send7bitAddress(I2Cx, SlaAddr, I2C_Direction_Transmit);
/* Wait until ADDR flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_ADDRF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_3;
}
/* Clear ADDR flag */
I2C_ClearADDRFlag(I2Cx);
/* Wait until TDE flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_4;
}
if(ReadAddrSize == I2C_MEMADD_SIZE_32BIT)
{
I2C_SendData(I2Cx, (uint8_t)(ReadAddr >> 24));
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
{
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_5;
}
ReadAddrSize -= 1;
}
if(ReadAddrSize == I2C_MEMADD_SIZE_24BIT)
{
I2C_SendData(I2Cx, (uint8_t)(ReadAddr >> 16));
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
{
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_5;
}
ReadAddrSize -= 1;
}
if(ReadAddrSize == I2C_MEMADD_SIZE_16BIT)
{
I2C_SendData(I2Cx, (uint8_t)(ReadAddr >> 8));
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
{
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_5;
}
}
/* Send Memory Address */
I2C_SendData(I2Cx, ReadAddr);
/* Wait until TDE flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_5;
}
/* Send START condition */
I2C_GenerateSTART(I2Cx, ENABLE);
/* Wait until SB flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_STARTF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_6;
}
/* Send slave address for read */
I2C_Send7bitAddress(I2Cx, SlaAddr, I2C_Direction_Receive);
/* Wait until ADDR flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_ADDRF, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_7;
}
if(NumByteToRead == 1)
{
/* Disable Acknowledge */
I2C_AcknowledgeConfig(I2Cx, DISABLE);
/* Clear ADDR flag */
I2C_ClearADDRFlag(I2Cx);
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
}
else if(NumByteToRead == 2)
{
/* Enable Pos */
I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Next);
/* Clear ADDR flag */
I2C_ClearADDRFlag(I2Cx);
/* Disable Acknowledge */
I2C_AcknowledgeConfig(I2Cx, DISABLE);
}
else
{
/* Enable Acknowledge */
I2C_AcknowledgeConfig(I2Cx, ENABLE);
/* Clear ADDR flag */
I2C_ClearADDRFlag(I2Cx);
}
while(NumByteToRead > 0)
{
if(NumByteToRead <= 3)
{
/* One byte */
if(NumByteToRead == 1)
{
/* Wait until RXNE flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_RDNE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_8;
}
/* Read data from DR */
(*pBuffer++) = I2C_ReceiveData(I2Cx);
NumByteToRead--;
}
/* Two bytes */
else if(NumByteToRead == 2)
{
/* Wait until BTF flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BTFF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_9;
}
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
/* Read data from DR */
(*pBuffer++) = I2C_ReceiveData(I2Cx);
NumByteToRead--;
/* Read data from DR */
(*pBuffer++) = I2C_ReceiveData(I2Cx);
NumByteToRead--;
}
/* 3 Last bytes */
else
{
/* Wait until BTF flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BTFF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_10;
}
/* Disable Acknowledge */
I2C_AcknowledgeConfig(I2Cx, DISABLE);
/* Read data from DR */
(*pBuffer++) = I2C_ReceiveData(I2Cx);
NumByteToRead--;
/* Wait until BTF flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BTFF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_11;
}
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
/* Read data from DR */
(*pBuffer++) = I2C_ReceiveData(I2Cx);
NumByteToRead--;
/* Read data from DR */
(*pBuffer++) = I2C_ReceiveData(I2Cx);
NumByteToRead--;
}
}
else
{
/* Wait until RXNE flag is set */
if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_RDNE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
{
/* Send STOP Condition */
I2C_GenerateSTOP(I2Cx, ENABLE);
return I2C_ERROR_STEP_12;
}
/* Read data from DR */
(*pBuffer++) = I2C_ReceiveData(I2Cx);
NumByteToRead--;
}
}
return I2C_OK;
}