2015-02-18 03:42 AM
Hello everybody,
I have a problem with I2C on STM32F4 I communicate with a touchpad controller: everything is OK, I can configure this I2C controller and get its datas. But when I communicate it takes a lot of time and I can see my uC slowing down. It's strange because I don't send it a lot of datas and it don't send me a lot of datas. And the I2C clock speed is 400kHz. And even sometimes the communication freeze my program... I attached my code below, can you please advise me on what going wrong? Thanks a lot and have a good day! I2C DRIVER:/* Direction = I2C_Direction_Transmitter or I2C_Direction_Receiver */
void
I2C1_Repeated_Start(uint8_t direction)
{
// Send I2C1 START condition
I2C_GenerateSTART(I2C1, ENABLE);
// wait for I2C1 EV5 --> Slave has acknowledged start condition
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// Clear flag
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
// Send slave Address for write
I2C_Send7bitAddress(I2C1, TP_ADRESS<<1, direction);
if
(direction == I2C_Direction_Transmitter)
{
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
else
if
(direction == I2C_Direction_Receiver)
{
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}
/* Direction = I2C_Direction_Transmitter or I2C_Direction_Receiver */
void
I2C1_Start(uint8_t direction)
{
// wait until I2C1 is not busy anymore
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
// Send I2C1 START condition
I2C_GenerateSTART(I2C1, ENABLE);
// wait for I2C1 EV5 --> Slave has acknowledged start condition
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
// Clear flag
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
// Send slave Address for write
I2C_Send7bitAddress(I2C1, TP_ADRESS<<1, 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(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
}
else
if
(direction == I2C_Direction_Receiver)
{
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
}
}
void
I2C1_Stop(
void
)
{
// Send I2C1 STOP Condition
I2C_GenerateSTOP(I2C1, ENABLE);
// Clear flag
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
}
void
I2C1_Wr(uint8_t data)
{
I2C_SendData(I2C1, data);
// wait for I2C1 EV8_2 --> byte has been transmitted
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
// Clear flag
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
}
uint8_t I2C1_Read_Ack(
void
)
{
// enable acknowledge of recieved data
I2C_AcknowledgeConfig(I2C1, ENABLE);
// wait until one byte has been received
while
( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) );
// read data from I2C data register and return data byte
uint8_t data = I2C_ReceiveData(I2C1);
// Clear flag
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
return
data;
}
uint8_t I2C1_Read(
void
)
{
// enable acknowledge of recieved data
I2C_AcknowledgeConfig(I2C1, DISABLE);
// wait until one byte has been received
while
( !I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
// read data from I2C data register and return data byte
uint8_t data = I2C_ReceiveData(I2C1);
// Clear flag
I2C_ClearFlag(I2C1, I2C_FLAG_AF);
return
data;
}
CALCULATE FINGER POSITION:
void
CALCULATE_POSITION(
void
)
{
I2C1_Start(I2C_Direction_Transmitter);
// Communication started
I2C1_Wr(0x01);
// Send data address
I2C1_Repeated_Start(I2C_Direction_Receiver);
// Issue repeated start signal
info = I2C1_Read_Ack();
// Read the data (01 Info Byte)
if
(info > 128){
// If there are any active coordinates, read all the bytes
// Touch 1
ID_1 = I2C1_Read_Ack();
// Read the data (02 ID 1)
x_h_1 = I2C1_Read_Ack();
// Read the data (03 X 1 High Byte)
x_l_1 = I2C1_Read_Ack();
// Read the data (04 X 1 Low Byte)
y_h_1 = I2C1_Read_Ack();
// Read the data (05 Y 1 High Byte)
y_l_1 = I2C1_Read_Ack();
t_h_1 = I2C1_Read_Ack();
// Read the data (07 Touch Strength 1 High Byte)
t_l_1 = I2C1_Read();
// Read the data (08 Touch Strength 1 Low Byte)
I2C1_Stop();
// Close communication window
}
}
2015-02-18 05:01 AM
Perhaps a more state-full implementation that doesn't spend all it's time in while() loops.
Suggest you profile the code an figure where it's burning all your time.2015-02-18 05:58 AM
Thanks Clive1,
To remove the while() loops I need to use I2C interrupts isn't it ?I have troubles to find on the internet a simple communication example with interrupts. I imagine that the functionI2C1_EV_IRQHandler
is called at each interrupt, and inside I can get the last I2C event, and depending on the event (e.g.I2C_EVENT_MASTER_MODE_SELECT
orI2C_FLAG_BUSY
) I can launch the according action?Seems a little bit complicated, is there an easier way to use interrups?Thanks!2015-02-18 06:07 AM
Well I guess you could use threads and yield.