cancel
Showing results for 
Search instead for 
Did you mean: 

I2C busy flag

edgar
Associate II
Posted on August 05, 2013 at 12:10

Hello,

I am trying to connect two boards using I2C. I have already configured one as master but whenever I send the start condition the I2C bus is busy. Maybe I am wrong in the initialization of the GPIO pins. Find the initialization code below. Thanks in advance!

void init_I2C2(void){
GPIO_InitTypeDef GPIO_InitStruct;
I2C_InitTypeDef I2C_InitStruct;
// enable APB1 peripheral clock for I2C2
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
// enable clock for SCL and SDA pins
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);
/* setup SCL and SDA pins
* SCL on PH5 and SDA on PH4
*/
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5; // we are going to use PH4 and PH5
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // set pins to alternate function
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // set GPIO speed
GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; // set output to open drain --> the line has to be only pulled low, not driven high
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOH, &GPIO_InitStruct); // init GPIOH
// Connect I2C2 pins to AF
GPIO_PinAFConfig(GPIOH, GPIO_PinSource4, GPIO_AF_I2C2); // SCL
GPIO_PinAFConfig(GPIOH, GPIO_PinSource5, GPIO_AF_I2C2); // SDA
// configure I2C2
I2C_InitStruct.I2C_ClockSpeed = 100000; // 100kHz
I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; // I2C mode
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; // 50% duty cycle --> standard
I2C_InitStruct.I2C_OwnAddress1 = 0x00; // own address, not relevant in master mode
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; // disable acknowledge when reading (can be changed later on)
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // set address length to 7 bit addresses
I2C_Init(I2C2, &I2C_InitStruct); // init I2C2
// enable I2C2
I2C_Cmd(I2C2, ENABLE);
}
/* This function issues a start condition and
* transmits the slave address + R/W bit
*
* Parameters:
* I2Cx --> the I2C peripheral e.g. I2C1
* address --> the 7 bit slave address
* direction --> the tranmission direction can be:
* I2C_Direction_Transmitter for Master transmitter mode
* I2C_Direction_Receiver for Master receiver
*/
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction){
// wait until I2C2 is not busy anymore
while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
// Send I2C1 START condition
I2C_GenerateSTART(I2Cx, ENABLE);
// wait for I2C1 EV5 --> Slave has acknowledged start condition
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
// Send slave Address for write
I2C_Send7bitAddress(I2Cx, address, direction);
/* wait for I2C1 EV6, check if
* either Slave has acknowledged Master transmitter or
* Master receiver mode, depending on the transmission
* direction
*/
if(direction == I2C_Direction_Transmitter){
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
else if(direction == I2C_Direction_Receiver){
while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}

4 REPLIES 4
zzdz2
Associate II
Posted on August 05, 2013 at 13:24

Try to reset I2C peripheral before configuring it (I2C_SoftwareResetCmd)

edgar
Associate II
Posted on August 05, 2013 at 14:04

Nope. It doesn't work.

I forgot to mention I use 22k pull-up resistors.

edgar
Associate II
Posted on August 06, 2013 at 11:01

I have decided to implement the communication with interrupts. Master uses I2C2 and Slave I2C3. Here is the code, but it doesn't work either.

Common code:

void I2CInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);
/* Enable UART clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2 | RCC_APB1Periph_I2C3, ENABLE);
GPIO_PinAFConfig(GPIOH, GPIO_PinSource4, GPIO_AF_I2C2);
GPIO_PinAFConfig(GPIOH, GPIO_PinSource5, GPIO_AF_I2C2);
GPIO_PinAFConfig(GPIOH, GPIO_PinSource7, GPIO_AF_I2C3);
GPIO_PinAFConfig(GPIOH, GPIO_PinSource8, GPIO_AF_I2C3);
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOH, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_Init(GPIOH, &GPIO_InitStructure);
I2C_InitStructure.I2C_ClockSpeed = 200000;
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = I2C2_MASTER_ADDRESS;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
/* Enable I2C */
I2C_Cmd(I2C2, ENABLE);
I2C_Init(I2C2, &I2C_InitStructure);
I2C_InitStructure.I2C_OwnAddress1 = I2C3_SLAVE_ADDRESS;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_Cmd(I2C3, ENABLE);
I2C_Init(I2C3, &I2C_InitStructure);
/* Configure the SPI interrupt priority */
NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = I2C3_EV_IRQn;
NVIC_Init(&NVIC_InitStructure);
}
void I2C2_EV_IRQHandler(void)
{
switch(I2C_GetLastEvent(I2C2))
{
case I2C_EVENT_MASTER_MODE_SELECT:
I2C_Send7bitAddress(I2C2, I2C3_SLAVE_ADDRESS, I2C_Direction_Transmitter);
break;
case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
I2C_CalculatePEC(I2C2, ENABLE);
I2C_CalculatePEC(I2C3, ENABLE);
I2C_SendData(I2C2, I2C2_Buffer_Tx[Tx_Index ++]);
break;
case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
if(Tx_Index < 4)
{
I2C_SendData(I2C2, I2C2_Buffer_Tx[Tx_Index ++]);
}
else
{
I2C_ITConfig(I2C2, I2C_IT_BUF | I2C_IT_EVT, DISABLE);
I2C_TransmitPEC(I2C3, ENABLE);
I2C_TransmitPEC(I2C2, ENABLE);
}
break;
default:
break;
}
}
void I2C3_EV_IRQHandler(void)
{
switch(I2C_GetLastEvent(I2C3))
{
case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED :
break;
case I2C_EVENT_SLAVE_BYTE_RECEIVED:
if(Rx_Index < 4)
{
I2C3_Buffer_Rx[Rx_Index ++] = I2C_ReceiveData(I2C3);
}
else
{
PEC_Value = I2C_ReceiveData(I2C3);
Rx_Index ++;
I2C_GenerateSTOP(I2C2, ENABLE);
}
break;
case I2C_EVENT_SLAVE_STOP_DETECTED :
I2C_ITConfig(I2C3, I2C_IT_BUF | I2C_IT_EVT, DISABLE);
break;
default:
break;
}
}
TestResult CmpBuffer(u8* Buffer1, u8* Buffer2, u32 BufferLength)
{
while(BufferLength--)
{
if(*Buffer1 != *Buffer2)
{
return Fail;
}
Buffer1++;
Buffer2++;
}
return Pass;
}

Master main:

int main(void)
{
SD_Init();
STM_EVAL_LEDInit(LED1);
prvSetupHardware();
STM_EVAL_LEDInit(LED2);
I2CInit();
I2C_ITConfig(I2C2, I2C_IT_BUF | I2C_IT_EVT, ENABLE);
I2C_ITConfig(I2C3, I2C_IT_BUF | I2C_IT_EVT, ENABLE);
I2C_GenerateSTART(I2C2, ENABLE);
while (1)
{
}
}

Slave main:

int main(void)
{
SD_Init();
STM_EVAL_LEDInit(LED1);
prvSetupHardware();
STM_EVAL_LEDInit(LED2);
I2CInit();
I2C_ITConfig(I2C2, I2C_IT_BUF | I2C_IT_EVT, ENABLE);
I2C_ITConfig(I2C3, I2C_IT_BUF | I2C_IT_EVT, ENABLE);
while(Rx_Index < 5)
{
}
a = CmpBuffer(I2C2_Buffer_Tx , I2C3_Buffer_Rx, 4);
if(a == 1)
{
STM_EVAL_LEDToggle(LED1);
}
else
{
STM_EVAL_LEDToggle(LED2);
}
while (1)
{
}
}

Any idea? Thanks!
edgar
Associate II
Posted on August 08, 2013 at 16:32

anybody?