/**
* @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 FM24V05_OK (0) if operation is correctly performed, else return value
* different from FM24V05_OK (0) or the timeout user callback.
*/
uint32_t FM24V05_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. */
FM24V05DataReadPointer = NumByteToRead;
/*!< While the bus is busy */
FM24V05Timeout = FM24V05_LONG_TIMEOUT;
while(I2C_GetFlagStatus(FM24V05_I2C, I2C_FLAG_BUSY))
{
if((FM24V05Timeout--) == 0) return FM24V05_TIMEOUT_UserCallback();
}
/*!< Send START condition */
I2C_GenerateSTART(FM24V05_I2C, ENABLE);
/*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
FM24V05Timeout = FM24V05_FLAG_TIMEOUT;
while(!I2C_CheckEvent(FM24V05_I2C, I2C_EVENT_MASTER_MODE_SELECT))
{
if((FM24V05Timeout--) == 0) return FM24V05_TIMEOUT_UserCallback();
}
/*!< Send EEPROM address for write */
I2C_Send7bitAddress(FM24V05_I2C, I2C_SLAVE_ADDRESS7, I2C_Direction_Transmitter);
/*!< Test on EV6 and clear it */
FM24V05Timeout = FM24V05_FLAG_TIMEOUT;
while(!I2C_CheckEvent(FM24V05_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if((FM24V05Timeout--) == 0) return FM24V05_TIMEOUT_UserCallback();
}
/*!< Send the EEPROM's internal address to read from: MSB of the address first */
I2C_SendData(FM24V05_I2C, (uint8_t)((ReadAddr & 0xFF00) >> 8));
/*!< Test on EV8 and clear it */
FM24V05Timeout = FM24V05_FLAG_TIMEOUT;
while(!I2C_CheckEvent(FM24V05_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING))
{
if((FM24V05Timeout--) == 0) return FM24V05_TIMEOUT_UserCallback();
}
/*!< Send the EEPROM's internal address to read from: LSB of the address */
I2C_SendData(FM24V05_I2C, (uint8_t)(ReadAddr & 0x00FF));
/*!< Test on EV8 and clear it */
FM24V05Timeout = FM24V05_FLAG_TIMEOUT;
while(I2C_GetFlagStatus(FM24V05_I2C, I2C_FLAG_BTF) == RESET)
{
if((FM24V05Timeout--) == 0) return FM24V05_TIMEOUT_UserCallback();
}
/*!< Send STRAT condition a second time */
I2C_GenerateSTART(FM24V05_I2C, ENABLE);
/*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
FM24V05Timeout = FM24V05_FLAG_TIMEOUT;
while(!I2C_CheckEvent(FM24V05_I2C, I2C_EVENT_MASTER_MODE_SELECT))
{
if((FM24V05Timeout--) == 0) return FM24V05_TIMEOUT_UserCallback();
}
/*!< Send EEPROM address for read */
I2C_Send7bitAddress(FM24V05_I2C, I2C_SLAVE_ADDRESS7, 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 */
FM24V05Timeout = FM24V05_FLAG_TIMEOUT;
while(I2C_GetFlagStatus(FM24V05_I2C, I2C_FLAG_ADDR) == RESET)
{
if((FM24V05Timeout--) == 0) return FM24V05_TIMEOUT_UserCallback();
}
/*!< Disable Acknowledgement */
I2C_AcknowledgeConfig(FM24V05_I2C, DISABLE);
/* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
(void)FM24V05_I2C->SR2;
/*!< Send STOP Condition */
I2C_GenerateSTOP(FM24V05_I2C, ENABLE);
/* Wait for the byte to be received */
FM24V05Timeout = FM24V05_FLAG_TIMEOUT;
while(I2C_GetFlagStatus(FM24V05_I2C, I2C_FLAG_RXNE) == RESET)
{
if((FM24V05Timeout--) == 0) return FM24V05_TIMEOUT_UserCallback();
}
/*!< Read the byte received from the EEPROM */
*pBuffer = I2C_ReceiveData(FM24V05_I2C);
/*!< Decrement the read bytes counter */
(uint16_t)(*NumByteToRead)--;
/* Wait to make sure that STOP control bit has been cleared */
FM24V05Timeout = FM24V05_FLAG_TIMEOUT;
while(FM24V05_I2C->CR1 & I2C_CR1_STOP)
{
if((FM24V05Timeout--) == 0) return FM24V05_TIMEOUT_UserCallback();
}
/*!< Re-Enable Acknowledgement to be ready for another reception */
I2C_AcknowledgeConfig(FM24V05_I2C, ENABLE);
}
else/* More than one Byte Master Reception procedure (DMA) -----------------*/
{
//************************************************************************DMA方式
/*!< Test on EV6 and clear it */
FM24V05Timeout = FM24V05_FLAG_TIMEOUT;
while(!I2C_CheckEvent(FM24V05_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{
if((FM24V05Timeout--) == 0) return FM24V05_TIMEOUT_UserCallback();
}
/* Enable the DMA clock */
RCC_AHBPeriphClockCmd(FM24V05_I2C_DMA_CLK, ENABLE);
/* Configure the DMA Rx Channel with the buffer address and the buffer size */
FM24V05_LowLevel_DMAConfig((uint32_t)pBuffer, (uint16_t)(*NumByteToRead), FM24V05_DIRECTION_RX);
/* Inform the DMA that the next End Of Transfer Signal will be the last one */
I2C_DMALastTransferCmd(FM24V05_I2C, ENABLE);
/* Enable the DMA Rx Channel */
DMA_Cmd(FM24V05_I2C_DMA_CHANNEL_RX, ENABLE);
}
/* If all operations OK, return FM24V05_OK (0) */
return FM24V05_OK;
} |