You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
302 lines
7.5 KiB
302 lines
7.5 KiB
/**
|
|
**************************************************************************************************
|
|
* @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"
|
|
|
|
#define I2C_BASE ((I2C_TypeDef*)i2cBase_Addr_List[i2cHardware->channelNo])
|
|
|
|
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, uint8_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.
|
|
}
|
|
}
|