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.
272 lines
6.4 KiB
272 lines
6.4 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"
|
|
|
|
|
|
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 i2cWaitForPeriferal(i2c_t *i2cHardware)
|
|
{
|
|
while(i2cHardware->state != i2cReady)
|
|
{
|
|
i2cIsPeriferalReady(i2cHardware);
|
|
}
|
|
}
|
|
|
|
void i2cIsPeriferalReady(i2c_t *i2cHardware)
|
|
{
|
|
if((I2C_BASE->ISR & (I2C_ISR_BUSY))!=I2C_ISR_BUSY)
|
|
{
|
|
i2cHardware->state = i2cReady;
|
|
}
|
|
else
|
|
{
|
|
i2cHardware->state = i2cBusy;
|
|
}
|
|
}
|
|
|
|
|
|
void i2cSendSlaveAddress(i2c_t *i2cHardware, uint16_t slaveAddress)
|
|
{
|
|
if(i2cHardware->addressSize == i2cAddressSizeSevenBits)
|
|
{
|
|
// 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
|
|
|
|
//Set Buffer size / which is alredy full with the device address to be sent
|
|
I2C_BASE->CR2 |= 1 << I2C_CR2_NBYTES_Pos;
|
|
}
|
|
else if(i2cHardware->addressSize == i2cAddressSizeTenBits)
|
|
{
|
|
//to implement
|
|
}
|
|
|
|
i2cGenerateStart(i2cHardware);
|
|
|
|
// Wait until the data in the ouput buffer is put to the i2c BUS
|
|
while(i2cHardware->state == i2cOutputBufferFull)
|
|
{
|
|
i2cIsOutputBufferEmpty(i2cHardware);
|
|
}
|
|
}
|
|
|
|
void i2cGenerateStart(i2c_t *i2cHardware)
|
|
{
|
|
I2C_BASE->CR2 |= I2C_CR2_START;
|
|
|
|
//Wait until the start condition in generated.
|
|
while(!(I2C_BASE->ISR & (I2C_ISR_BUSY)));
|
|
i2cHardware->state = i2cStartGenrated;
|
|
// This device places the salve address automaticalyy in the buffer before sending the star condition
|
|
i2cHardware->state = i2cOutputBufferFull;
|
|
}
|
|
|
|
void i2cGenerateStop(i2c_t *i2cHardware)
|
|
{
|
|
// Sned stop command
|
|
I2C_BASE->CR2 |= I2C_CR2_STOP;
|
|
}
|
|
|
|
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 i2cIsOutputBufferEmpty(i2c_t *i2cHardware)
|
|
{
|
|
if((I2C_BASE->ISR & (I2C_ISR_TXE)) == I2C_ISR_TXE)
|
|
{
|
|
i2cHardware->state = i2cOutputBufferEmpty;
|
|
}
|
|
else
|
|
{
|
|
i2cHardware->state = i2cOutputBufferFull;
|
|
}
|
|
}
|
|
|
|
void i2cIsInputBufferEmpty(i2c_t *i2cHardware)
|
|
{
|
|
if((I2C_BASE->ISR & (I2C_ISR_RXNE)) == I2C_ISR_RXNE)
|
|
{
|
|
i2cHardware->state = i2cInputBufferFull;
|
|
}
|
|
else
|
|
{
|
|
i2cHardware->state = i2cInputBufferEmpty;
|
|
}
|
|
}
|
|
|
|
void i2cSendRegisterAddress(i2c_t *i2cHardware, uint8_t registerAddress)
|
|
{
|
|
//Register to be sent
|
|
I2C_BASE->TXDR |= registerAddress;
|
|
|
|
i2cHardware->state = i2cOutputBufferFull;
|
|
|
|
while(i2cHardware->state == i2cOutputBufferFull)
|
|
{
|
|
i2cIsOutputBufferEmpty(i2cHardware);
|
|
}
|
|
}
|
|
|
|
void i2cGenerateNack(i2c_t *i2cHardware)
|
|
{
|
|
if(i2cHardware->mode == i2cModeMaster)
|
|
{
|
|
//IN master mode this ic geretes NACK's otomatically
|
|
}
|
|
else if(i2cHardware->mode == i2cModeSlave)
|
|
{
|
|
// to be written.
|
|
}
|
|
}
|