unsigned long TWI_MasterWriteRead(new_twi* TwiStruct, unsigned int TransmitBytes, unsigned int ReceiveBytes) { uint32_t tickstart = 0; I2C_HandleTypeDef *hi2c = (I2C_HandleTypeDef *)TwiStruct->udata; /* Init tickstart for timeout management*/ tickstart = HAL_GetTick(); if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) { I2C_SoftwareResetCmd(hi2c); return HAL_TIMEOUT; } hi2c->State = HAL_I2C_STATE_BUSY_TX; hi2c->Mode = HAL_I2C_MODE_MASTER; hi2c->ErrorCode = HAL_I2C_ERROR_NONE; /* Prepare transfer parameters */ hi2c->pBuffPtr = TwiStruct->TxBuff; hi2c->XferCount = TransmitBytes; hi2c->XferISR = NULL; /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */ if(hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE); } else { if(ReceiveBytes != 0) { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE); } } do { tickstart = HAL_GetTick(); /* Wait until TXIS flag is set */ if(I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Read data from RXDR */ hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); hi2c->XferCount--; hi2c->XferSize--; if((hi2c->XferSize == 0) && (hi2c->XferCount != 0)) { /* Wait until TCR flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } if(hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); } else { if(ReceiveBytes != 0) { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_NO_STARTSTOP); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); } } } }while(hi2c->XferCount > 0); if(ReceiveBytes == 0) { /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ /* Wait until STOPF flag is reset */ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); /* Clear Configuration Register 2 */ I2C_RESET_CR2(hi2c); hi2c->State = HAL_I2C_STATE_READY; hi2c->Mode = HAL_I2C_MODE_NONE; /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_OK; } tickstart = HAL_GetTick(); /* Wait until TCR flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } hi2c->State = HAL_I2C_STATE_BUSY_RX; hi2c->Mode = HAL_I2C_MODE_MASTER; hi2c->ErrorCode = HAL_I2C_ERROR_NONE; /* Prepare transfer parameters */ hi2c->pBuffPtr = TwiStruct->RxBuff; hi2c->XferCount = ReceiveBytes; hi2c->XferISR = NULL; /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE */ if(hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr | 1, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr | 1, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); } do { tickstart = HAL_GetTick(); /* Wait until RXNE flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } /* Read data from RXDR */ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; hi2c->XferSize--; hi2c->XferCount--; if((hi2c->XferSize == 0) && (hi2c->XferCount != 0)) { /* Wait until TCR flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } if(hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr | 1, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, TwiStruct->MasterSlaveAddr | 1, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); } } }while(hi2c->XferCount > 0); /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ /* Wait until STOPF flag is reset */ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); /* Clear Configuration Register 2 */ I2C_RESET_CR2(hi2c); hi2c->State = HAL_I2C_STATE_READY; hi2c->Mode = HAL_I2C_MODE_NONE; /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_OK; }
/** * @brief Transmits in master mode an amount of data in blocking mode. * @param hi2c Pointer to a I2C_HandleTypeDef structure that contains * the configuration information for the specified I2C. * @param DevAddress Target device address The device 7 bits address value * in datasheet must be shifted to the left before calling the interface * @param pData Pointer to data buffer * @param Size Amount of data to be sent * @param Timeout Timeout duration * @param LastOp If set sends STOP, otherwise no STOP * @retval HAL status */ HAL_StatusTypeDef HAL_I2C_Master_Transmit_Custom(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout, uint8_t LastOp) { uint32_t tickstart = 0U; uint8_t prev_mode = 0; if (hi2c->State == HAL_I2C_STATE_READY) { /* Process Locked */ __HAL_LOCK(hi2c); /* Init tickstart for timeout management*/ tickstart = HAL_GetTick(); prev_mode = hi2c->Mode; if (prev_mode != HAL_I2C_MODE_MASTER_SEL) { if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) { return HAL_TIMEOUT; } } hi2c->State = HAL_I2C_STATE_BUSY_TX; hi2c->Mode = HAL_I2C_MODE_MASTER; hi2c->ErrorCode = HAL_I2C_ERROR_NONE; /* Prepare transfer parameters */ hi2c->pBuffPtr = pData; hi2c->XferCount = Size; hi2c->XferISR = NULL; /* Send Slave Address */ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ if (hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_WRITE); } else if (!LastOp) { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_GENERATE_START_WRITE); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_WRITE); } /* * Wait RESTART to be accepted */ if (prev_mode == HAL_I2C_MODE_MASTER_SEL) { if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } } while (hi2c->XferCount > 0U) { /* Wait until TXIS flag is set */ if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Write data to TXDR */ hi2c->Instance->TXDR = (*hi2c->pBuffPtr++); hi2c->XferCount--; hi2c->XferSize--; if ((hi2c->XferSize == 0U) && (hi2c->XferCount != 0U)) { /* Wait until TCR flag is set */ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } if (hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); } else if (!LastOp) { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_SOFTEND_MODE, I2C_NO_STARTSTOP); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); } } } if (LastOp) { /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ /* Wait until STOPF flag is set */ if (I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { if (hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); } else { /* No autoend/reload was requested, make sure transmission of last byte * has finished... */ if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TC, SET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } } /* Clear Configuration Register 2 */ I2C_RESET_CR2(hi2c); hi2c->State = HAL_I2C_STATE_READY; if (LastOp) { hi2c->Mode = HAL_I2C_MODE_NONE; } else { hi2c->Mode = HAL_I2C_MODE_MASTER_SEL; } /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_OK; } else { return HAL_BUSY; } }