Professional Documents
Culture Documents
* stm32f407xx_i2c_driver.c
*
* Created on: Feb 20, 2019
* Author: admin
*/
#include "stm32f407xx_i2c_driver.h"
}
else
{
//clear the ADDR flag ( read SR1 , read SR2)
dummy_read = pI2CHandle->pI2Cx->SR1;
dummy_read = pI2CHandle->pI2Cx->SR2;
(void)dummy_read;
}
else
{
//device is in slave mode
//clear the ADDR flag ( read SR1 , read SR2)
dummy_read = pI2CHandle->pI2Cx->SR1;
dummy_read = pI2CHandle->pI2Cx->SR2;
(void)dummy_read;
}
/*********************************************************************
* @fn - I2C_PeripheralControl
*
* @brief -
*
* @param[in] -
* @param[in] -
* @param[in] -
*
* @return -
*
* @Note -
*/
void I2C_PeripheralControl(I2C_RegDef_t *pI2Cx, uint8_t EnOrDi)
{
if(EnOrDi == ENABLE)
{
pI2Cx->CR1 |= (1 << I2C_CR1_PE);
//pI2cBaseAddress->CR1 |= I2C_CR1_PE_Bit_Mask;
}else
{
pI2Cx->CR1 &= ~(1 << 0);
}
/*********************************************************************
* @fn - I2C_PeriClockControl
*
* @brief -
*
* @param[in] -
* @param[in] -
* @param[in] -
*
* @return -
*
* @Note -
*/
void I2C_PeriClockControl(I2C_RegDef_t *pI2Cx, uint8_t EnorDi)
{
if(EnorDi == ENABLE)
{
if(pI2Cx == I2C1)
{
I2C1_PCLK_EN();
}else if (pI2Cx == I2C2)
{
I2C2_PCLK_EN();
}else if (pI2Cx == I2C3)
{
I2C3_PCLK_EN();
}
}
else
{
//TODO
}
}
/*********************************************************************
* @fn - I2C_Init
*
* @brief -
*
* @param[in] -
* @param[in] -
* @param[in] -
*
* @return -
*
* @Note -
*/
void I2C_Init(I2C_Handle_t *pI2CHandle)
{
uint32_t tempreg = 0 ;
//CCR calculations
uint16_t ccr_value = 0;
tempreg = 0;
if(pI2CHandle->I2C_Config.I2C_SCLSpeed <= I2C_SCL_SPEED_SM)
{
//mode is standard mode
ccr_value = (RCC_GetPCLK1Value() / ( 2 *
pI2CHandle->I2C_Config.I2C_SCLSpeed ) );
tempreg |= (ccr_value & 0xFFF);
}else
{
//mode is fast mode
tempreg |= ( 1 << 15);
tempreg |= (pI2CHandle->I2C_Config.I2C_FMDutyCycle << 14);
if(pI2CHandle->I2C_Config.I2C_FMDutyCycle == I2C_FM_DUTY_2)
{
ccr_value = (RCC_GetPCLK1Value() / ( 3 *
pI2CHandle->I2C_Config.I2C_SCLSpeed ) );
}else
{
ccr_value = (RCC_GetPCLK1Value() / ( 25 *
pI2CHandle->I2C_Config.I2C_SCLSpeed ) );
}
tempreg |= (ccr_value & 0xFFF);
}
pI2CHandle->pI2Cx->CCR = tempreg;
//TRISE Configuration
if(pI2CHandle->I2C_Config.I2C_SCLSpeed <= I2C_SCL_SPEED_SM)
{
//mode is standard mode
}else
{
//mode is fast mode
tempreg = ( (RCC_GetPCLK1Value() * 300) / 1000000000U ) + 1;
/*********************************************************************
* @fn - I2C_DeInit
*
* @brief -
*
* @param[in] -
* @param[in] -
* @param[in] -
*
* @return -
*
* @Note -
*/
void I2C_DeInit(I2C_RegDef_t *pI2Cx)
{
//2. confirm that start generation is completed by checking the SB flag in the SR1
// Note: Until SB is cleared SCL will be stretched (pulled to LOW)
while( ! I2C_GetFlagStatus(pI2CHandle->pI2Cx,I2C_FLAG_SB) );
//3. Send the address of the slave with r/nw bit set to w(0) (total 8 bits )
I2C_ExecuteAddressPhaseWrite(pI2CHandle->pI2Cx,SlaveAddr);
//4. Confirm that address phase is completed by checking the ADDR flag in teh SR1
while( ! I2C_GetFlagStatus(pI2CHandle->pI2Cx,I2C_FLAG_ADDR) );
while(Len > 0)
{
while(! I2C_GetFlagStatus(pI2CHandle->pI2Cx,I2C_FLAG_TXE) ); //Wait till TXE
is set
pI2CHandle->pI2Cx->DR = *pTxbuffer;
pTxbuffer++;
Len--;
}
//7. when Len becomes zero wait for TXE=1 and BTF=1 before generating the STOP
condition
// Note: TXE=1 , BTF=1 , means that both SR and DR are empty and next transmission
should begin
// when BTF=1 SCL will be stretched (pulled to LOW)
while(! I2C_GetFlagStatus(pI2CHandle->pI2Cx,I2C_FLAG_TXE) );
while(! I2C_GetFlagStatus(pI2CHandle->pI2Cx,I2C_FLAG_BTF) );
//8. Generate STOP condition and master need not to wait for the completion of stop
condition.
// Note: generating STOP, automatically clears the BTF
if(Sr == I2C_DISABLE_SR )
I2C_GenerateStopCondition(pI2CHandle->pI2Cx);
//3. Send the address of the slave with r/nw bit set to R(1) (total 8 bits )
I2C_ExecuteAddressPhaseRead(pI2CHandle->pI2Cx,SlaveAddr);
//4. wait until address phase is completed by checking the ADDR flag in teh SR1
while( ! I2C_GetFlagStatus(pI2CHandle->pI2Cx,I2C_FLAG_ADDR) );
//re-enable ACKing
if(pI2CHandle->I2C_Config.I2C_AckControl == I2C_ACK_ENABLE)
{
I2C_ManageAcking(pI2CHandle->pI2Cx,I2C_ACK_ENABLE);
}
/*********************************************************************
* @fn - I2C_IRQInterruptConfig
*
* @brief -
*
* @param[in] -
* @param[in] -
* @param[in] -
*
* @return -
*
* @Note -
*/
void I2C_IRQInterruptConfig(uint8_t IRQNumber, uint8_t EnorDi)
{
if(EnorDi == ENABLE)
{
if(IRQNumber <= 31)
{
//program ISER0 register
*NVIC_ISER0 |= ( 1 << IRQNumber );
/*********************************************************************
* @fn - I2C_IRQPriorityConfig
*
* @brief -
*
* @param[in] -
* @param[in] -
* @param[in] -
*
* @return -
*
* @Note -
*/
void I2C_IRQPriorityConfig(uint8_t IRQNumber,uint32_t IRQPriority)
{
//1. first lets find out the ipr register
uint8_t iprx = IRQNumber / 4;
uint8_t iprx_section = IRQNumber %4 ;
/*********************************************************************
* @fn - I2C_MasterSendDataIT
*
* @brief -
*
* @param[in] -
* @param[in] -
* @param[in] -
*
* @return -
*
* @Note -
*/
uint8_t I2C_MasterSendDataIT(I2C_Handle_t *pI2CHandle,uint8_t *pTxBuffer, uint32_t Len,
uint8_t SlaveAddr,uint8_t Sr)
{
uint8_t busystate = pI2CHandle->TxRxState;
return busystate;
}
/*********************************************************************
* @fn - I2C_MasterReceiveDataIT
*
* @brief -
*
* @param[in] -
* @param[in] -
* @param[in] -
*
* @return -
*
* @Note -
*/
uint8_t I2C_MasterReceiveDataIT(I2C_Handle_t *pI2CHandle,uint8_t *pRxBuffer, uint8_t Len,
uint8_t SlaveAddr,uint8_t Sr)
{
uint8_t busystate = pI2CHandle->TxRxState;
return busystate;
}
if(pI2CHandle->TxLen > 0)
{
//1. load the data in to DR
pI2CHandle->pI2Cx->DR = *(pI2CHandle->pTxBuffer);
if(pI2CHandle->RxSize > 1)
{
if(pI2CHandle->RxLen == 2)
{
//clear the ack bit
I2C_ManageAcking(pI2CHandle->pI2Cx,DISABLE);
}
//read DR
*pI2CHandle->pRxBuffer = pI2CHandle->pI2Cx->DR;
pI2CHandle->pRxBuffer++;
pI2CHandle->RxLen--;
}
if(pI2CHandle->RxLen == 0 )
{
//close the I2C data reception and notify the application
pI2CHandle->TxRxState = I2C_READY;
pI2CHandle->pRxBuffer = NULL;
pI2CHandle->RxLen = 0;
pI2CHandle->RxSize = 0;
if(pI2CHandle->I2C_Config.I2C_AckControl == I2C_ACK_ENABLE)
{
I2C_ManageAcking(pI2CHandle->pI2Cx,ENABLE);
}
pI2CHandle->TxRxState = I2C_READY;
pI2CHandle->pTxBuffer = NULL;
pI2CHandle->TxLen = 0;
}
I2C_ExecuteAddressPhaseRead(pI2CHandle->pI2Cx,pI2CHandle->DevAddr);
}
}
I2C_ApplicationEventCallback(pI2CHandle,I2C_EV_TX_CMPLT);
}
}
pI2CHandle->pI2Cx->CR1 |= 0x0000;
}else
{
//slave
//make sure that the slave is really in receiver mode
if(!(pI2CHandle->pI2Cx->SR2 & ( 1 << I2C_SR2_TRA)))
{
I2C_ApplicationEventCallback(pI2CHandle,I2C_EV_DATA_RCV);
}
}
}
}
/*********************************************************************
* @fn - I2C_ER_IRQHandling
*
* @brief -
*
* @param[in] -
* @param[in] -
* @param[in] -
*
* @return -
*
* @Note - Complete the code also define these macros in the driver
header file
#define I2C_ERROR_BERR 3
#define I2C_ERROR_ARLO 4
#define I2C_ERROR_AF 5
#define I2C_ERROR_OVR 6
#define I2C_ERROR_TIMEOUT 7
*/
uint32_t temp1,temp2;