/** ************************************************************************************************** * @file i2c.c * @author Kerem Yollu & Edwin Koch * @date 18.07.2022 * @version 1.0 ************************************************************************************************** * @brief I2C communitation based on the Standart I2C Protocol V7 Defined by NXP/Philips : * following third Party Protocols based on I2C Bus are not going to be implemented : C-BUS SMBUS PMBUS IPMI DDC ATCA * This will also not have a I3C support for the forseable futrue. This code is generated for the stm32f4xK6 series of mcu for stm * * **Detailed Description :** * * I2C communitation based on the Standart I2C Protocol V7 Defined by NXP/Philips : * following third Party Protocols based on I2C Bus are not going to be implemented : C-BUS SMBUS PMBUS IPMI DDC ATCA * This will also not have a I3C support for the forseable futrue. * * @todo * - 18.07.2021 : Implement the i2c.c ************************************************************************************************** */ #include "i2c.h" uint8_t temp8 = 0; uint16_t temp16 = 0; void i2cEnableHardware(i2c_t *i2cHardware) { i2cHardwareReset(i2cHardware); // Enables the i2c bus RCC->APB1ENR |= (1 << i2cBus_En_bitPos[i2cHardware->channelNo]); pinInit(pinA9); pinInit(pinA10); pinConfig(pinA9, alternate, openDrain, pullUp, fast);// I2C SCL pinConfig(pinA10, alternate, openDrain, pullUp, fast);// I2C CSA pinSetAlternate(pinA9, 4); pinSetAlternate(pinA10, 4); } void i2cHardwareReset(i2c_t *i2cHardware) { // Resete the I2C hardware using the reset registers, RCC->APB1RSTR |= (1 << i2cBus_Rst_bitPos[i2cHardware->channelNo]); RCC->APB1RSTR &= ~(1 << i2cBus_Rst_bitPos[i2cHardware->channelNo]); } void i2cEnablePeriferal(i2c_t *i2cHardware) { I2C_BASE->CR1 |= I2C_CR1_PE; } void i2cDisablePeriferal(i2c_t *i2cHardware) { I2C_BASE->CR1 &= ~I2C_CR1_PE; } void i2cSetMode(i2c_t *i2cHardware, i2cMode_t mode) { //This device will set himself automatically to master mode if(i2cHardware->mode == i2cModeMaster) { //Automatic end mode (master mode) disabled Enablede as default I2C_BASE->CR2 &= ~I2C_CR2_AUTOEND; //I2C_BASE->CR2 |= I2C_CR2_AUTOEND; } else if(i2cHardware->mode == i2cModeSlave) { // to be written. } } void i2cSetAddress(i2c_t *i2cHardware, uint16_t mainAddress, uint16_t secondAddress) { } void i2cSetAddressLenght(i2c_t *i2cHardware, i2cAddressSize_t size) { if(i2cHardware->mode == i2cModeMaster) { if(i2cHardware->addressSize == i2cAddressSizeTenBits) { I2C_BASE->CR2 |= I2C_CR2_ADD10; // 10 Bit addressing I2C_BASE->CR2 &= ~I2C_CR2_HEAD10R; // 7 Bit header read turned on DEFAULT } else { I2C_BASE->CR2 &= ~I2C_CR2_ADD10; // 7 Bit addressing DEFAULT I2C_BASE->CR2 |= I2C_CR2_HEAD10R; // 7 Bit header read turned off DEFAULT } } else if(i2cHardware->mode == i2cModeSlave) { // to be written. } } void i2cSetClockStretch(i2c_t *i2cHardware, i2cClockStretching_t stretching) { if(i2cHardware->stretching == i2cClockStretchingEnable) { I2C_BASE->CR1 &=~ I2C_CR1_NOSTRETCH; } else if(i2cHardware->stretching == i2cClockStretchingDisable) { I2C_BASE->CR1 |= I2C_CR1_NOSTRETCH; } } void i2cSetSpeed(i2c_t *i2cHardware, i2cSpeed_t speed) { switch(speed) { case i2cSpeedStandart: I2C_BASE->TIMINGR = 0x2000090E; break; case i2cSpeedFast: break; case i2cSpeedFastPlus: break; case i2cSpeedHightSpeed: break; case i2cSpeedUltraFast: break; default: break; } } void i2cConfigureFilters(i2c_t *i2cHardware) { //Anlalog filter is on I2C_BASE->CR1 &= ~I2C_CR1_ANFOFF; } /************************************************************************************************** I2C Hardware functions ***************************************************************************************************/ void i2cGenerateStart(i2c_t *i2cHardware) { I2C_BASE->CR2 &=~ I2C_CR2_STOP; I2C_BASE->CR2 |= I2C_CR2_START; //Wait until the start condition in generated. while(!(I2C_BASE->ISR & (I2C_ISR_BUSY))); i2cHardware->hardwareState = i2cHwStartGenerated; // This device places the salve address automaticalyy in the output buffer before sending the star condition i2cHardware->hardwareState = i2cHwOutputBufferFull; } void i2cGenerateStop(i2c_t *i2cHardware) { // Send stop command I2C_BASE->CR2 |= I2C_CR2_STOP; I2C_BASE->CR2 &=~ I2C_CR2_START; i2cHardware->hardwareState = i2cHwStopGenerated; } void i2cIsPeriferalReady(i2c_t *i2cHardware) { if((I2C_BASE->ISR & (I2C_ISR_BUSY))!=I2C_ISR_BUSY) { i2cHardware->periferalState = i2cPerifReady; } } void i2cSetTransferCounter(i2c_t *i2cHardware, uint8_t count) { I2C_BASE->CR2 &= ~(0xFF << I2C_CR2_NBYTES_Pos); I2C_BASE->CR2 |= (count << I2C_CR2_NBYTES_Pos); } void i2cSendSlaveAddress(i2c_t *i2cHardware, uint16_t *slaveAddress) { // The Slave addrress is automatically place on the output buffer (must be done before the start condition) I2C_BASE->CR2 |= (*slaveAddress & 0xff) << 1; // The bit no 0 is not taken in concideration in 7bit mode i2cGenerateStart(i2cHardware); // Wait until the data in the ouput buffer is put to the i2c BUS while(i2cHardware->hardwareState =! i2cHwOutputBufferEmpty) { i2cIsOutputBufferEmpty(i2cHardware); } } void i2cSendRegisterAddress(i2c_t *i2cHardware, uint16_t *registerAddress) { i2cSendData(i2cHardware,registerAddress); } void i2cInitiateWriteCommand(i2c_t *i2cHardware) { I2C_BASE->CR2 &= ~I2C_CR2_RD_WRN; } void i2cInitiateReadCommand(i2c_t *i2cHardware) { I2C_BASE->CR2 |= I2C_CR2_RD_WRN; } void i2cSendData(i2c_t *i2cHardware, uint8_t *registerAddress) { while(i2cHardware->hardwareState =! i2cHwOutputBufferEmpty) { i2cIsOutputBufferEmpty(i2cHardware); } i2cSetOutputRegister(i2cHardware,registerAddress); while(i2cHardware->hardwareState =! i2cHwOutputBufferEmpty) { i2cIsOutputBufferEmpty(i2cHardware); } } void i2cIsOutputBufferEmpty(i2c_t *i2cHardware) { if(i2cHardware->periferalState == i2cPerifTransmitting) { if((I2C_BASE->ISR & (I2C_ISR_TXIS)) == I2C_ISR_TXIS) { i2cHardware->hardwareState = i2cHwOutputBufferEmpty; } else { i2cHardware->hardwareState = i2cHwOutputBufferFull; } } else if(i2cHardware->periferalState == i2cPerifRecieving) { if((I2C_BASE->ISR & (I2C_ISR_TXE)) == I2C_ISR_TXE) { i2cHardware->hardwareState = i2cHwOutputBufferEmpty; } else { i2cHardware->hardwareState = i2cHwOutputBufferFull; } } } void i2cIsInputBufferEmpty(i2c_t *i2cHardware) { if((I2C_BASE->ISR & (I2C_ISR_RXNE)) == I2C_ISR_RXNE) { i2cHardware->hardwareState = i2cHwInputBufferFull; } else { i2cHardware->hardwareState = i2cHwInputBufferEmpty; } } void i2cReadInputRegister(i2c_t *i2cHardware, uint8_t *data) { *data = I2C_BASE->RXDR; } void i2cSetOutputRegister(i2c_t *i2cHardware, uint8_t *data) { I2C_BASE->TXDR = *data; i2cHardware->hardwareState = i2cHwOutputBufferFull; } void i2cIsTransferComplete(i2c_t *i2cHardware) { if((I2C_BASE->ISR & (I2C_ISR_TC)) == I2C_ISR_TC) { i2cHardware->periferalState = i2cPerifTransferComplete; } else { i2cHardware->periferalState = i2cPerifTransferOngoign; } } void i2cGenerateNack(i2c_t *i2cHardware) { if(i2cHardware->mode == i2cModeMaster) { //IN master mode this ic geretes NACK's otomatically i2cHardware->hardwareState = i2cHwSentNack; } else if(i2cHardware->mode == i2cModeSlave) { // to be written. } }