cancel
Showing results for 
Search instead for 
Did you mean: 

I2C slave transmitter problem

davidrojas9
Associate II
Posted on March 02, 2012 at 11:49

Hello. I'm trying to connect two stm32f4discovery boards through I2C. One will be the master receiver, and will ask for 4 bytes of data to the other (slave receiver). I found an example for the master receiver, and it seems is working. Everything is correctly wired and configured, here is the function in the master receiver (uses polling) that reads the data:

/*re-enable ACK bit incase it was disabled last call*/

I2C_AcknowledgeConfig(I2C1, ENABLE);

/* Test on BUSY Flag */

while (I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));

I2C_GenerateSTART(I2C1, ENABLE);

/* Test on start flag */

while (!I2C_GetFlagStatus(I2C1,I2C_FLAG_SB));

/* Send address for read */

I2C_Send7bitAddress(I2C1, Address, I2C_Direction_Receiver);

/* Test Receive mode Flag */

while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

/* load in all 4 registers */

while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));

CapValueH = I2C_ReceiveData(I2C1);

while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));

CapValueL = I2C_ReceiveData(I2C1);

while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));

TempValueH = I2C_ReceiveData(I2C1);

while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));

TempValueL = I2C_ReceiveData(I2C1);

/*enable NACK bit */

I2C_NACKPositionConfig(I2C1, I2C_NACKPosition_Current); // Indicates that the current byte is the last received byte

I2C_AcknowledgeConfig(I2C1, DISABLE);

/* Send STOP Condition */

I2C_GenerateSTOP(I2C1, ENABLE);

while(I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF));

I've omitted some debugging stuf (led flashing to see what's happening). I've also omitted the configuration part (GPIO, clocks, i2c parameters), since it's pretty standard and no problem there.

And here, the slave transmitter, that uses interrupts. This is the interrupt EV routine:

void I2C1_EV_IRQHandler(void)

{

switch (I2C_GetLastEvent(I2C1))

{

//Slave Events

case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: // EV1

{

//I2C_StretchClockCmd(I2C1, ENABLE);

I2C_SendData(I2C1, 1);

while (!I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_BYTE_TRANSMITTED));

I2C_SendData(I2C1, 0);

while (!I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_BYTE_TRANSMITTED));

I2C_SendData(I2C1, 1);

while (!I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_BYTE_TRANSMITTED));

I2C_SendData(I2C1, 3);

while (!I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_BYTE_TRANSMITTED));

//I2C_StretchClockCmd(I2C1, DISABLE);

break;

}

case I2C_EVENT_SLAVE_BYTE_RECEIVED: //EV2

{

break;

}

case I2C_EVENT_SLAVE_BYTE_TRANSMITTED: //EV3

{

break;

}

case I2C_EVENT_SLAVE_ACK_FAILURE: // EV3-1

{

break;

}

case I2C_EVENT_SLAVE_STOP_DETECTED: // EV4

{

break;

}

default:

{

break;

}

}

}

I use again some led flashing for debug that I've omitted, and the data I send is just random numbers to test.

If I try it like this, the master performs all the correct functions, receives the data, generates the stop and finish his function. The 4 bytes received are correct, but when it finishes the slave holds down the clock, so I cannot make more requests unless I reset the slave board. Now If I remove the clock stretching commented commands in the interrupt, and also disable clock stretching when I configure the slave i2c, everything seems to work fine, I receive the data and the slave releases the clock, so I can make another request, but the data received is always 0x03 in any new request (in the 4 bytes the same value).

I've been banging my head against this for several days and tested a lot of things. Unfortunately I don't have a logic analyzer at hand now.

#stm32-i2c #stm32-i2c-clock-speed
10 REPLIES 10
davidrojas9
Associate II
Posted on March 06, 2012 at 08:59

Yes, I know, I already recalculated some timers in other parts of my code to account for this APB1/HCLK clock changes. In this design there is no problem with performance/power.