cancel
Showing results for 
Search instead for 
Did you mean: 

Serious I²C problems

philipp239955_stm1
Associate
Posted on June 02, 2011 at 03:12

Hello guys.

I have - as the title suggests - a problem with the I²C bus. I'm eagerly trying to get it working, but fail everytime. This is the code I'm using to initialize the I²C interface:

_______

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

I2C_InitStructure.I2C_OwnAddress1 = 0x52;

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_InitStructure.I2C_ClockSpeed = 400000;

I2C_Init(I2C1, &I2C_InitStructure);

/* I2C1 SDA and SCL configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOB, &GPIO_InitStructure);

I2C_Cmd(I2C1, ENABLE);

_______

As far as I can tell this should be OK. I then try to write some data to a brushless controller:

_______

Timeout = 0xFFFF;

myprint2(''\r\nEnter...'');

I2C_GenerateSTART(I2C1, ENABLE);

myprint2(''\r\nStart'');

while ((!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)) && (!stop))

{

if(Timeout == 0)

{

lEvent = I2C_GetLastEvent(I2C1);

myprint2(''\r\n Error Occured: Code %u'', lEvent);

if(IS_I2C_EVENT(lEvent)){

myprint2(''\r\n Is I2C Event'');

}

stop = 1;

}

Timeout--;

}

stop = 0;

Timeout = 0xFFFF;

myprint2(''\r\nEvent 1'');

Delay_ms(20);

I2C_Send7bitAddress(I2C1, 0x52, I2C_Direction_Transmitter);

myprint2(''\r\n7b Address'');

while ((!I2C_CheckEvent(I2C1,

I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && (!stop))

{

if(Timeout == 0)

{

lEvent = I2C_GetLastEvent(I2C1);

myprint2(''\r\n Error Occured: Code %u'', lEvent);

if(IS_I2C_EVENT(lEvent)){

myprint2(''\r\n Is I2C Event'');

}

stop = 1;

}

Timeout--;

}

stop = 0;

Timeout = 0xFFFF;

myprint2(''\r\nEvent 2'');

I2C_SendData(I2C1, 100);

myprint2(''\r\nSend Data'');

while ((!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) && (!stop))

{

if(Timeout == 0)

{

lEvent = I2C_GetLastEvent(I2C1);

myprint2(''\r\n Error Occured: Code %u'', lEvent);

if(IS_I2C_EVENT(lEvent)){

myprint2(''\r\n Is I2C Event'');

}

stop = 1;

}

Timeout--;

}

stop = 0;

Timeout = 0xFFFF;

myprint2(''\r\nEvent 3'');

I2C_GenerateSTOP(I2C1, ENABLE);

myprint2(''\r\nStop'');

_______

This is the code I'm using. The problem is though that the program hangs at the second I2C_CheckEvent function call. That's the way I saw it everywhere on the internet, but it just isn't working for me :(

This is the output I get from this code:

_______

Enter...

Start

Event 1

7b Address

Error Occured: Code 536870944

Event 2

Send Data

Error Occured: Code 536870944

Event 3

Stop

_______

I also read that LDRD is making some trouble, so I tried to add the fix to the compiler options, but that didn't help either. I even wrote my own I²C interface - which is somewhat working - but that isn't the best solution; it is pretty unreliable. I hope someone will be able to help me.

I'm looking forward to your replies.

Best regards,

tdk29

#i²c

4 REPLIES 4
Posted on June 02, 2011 at 03:21

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

Well it's certainly not going to work with Push-Pull drivers, you need Open Drain, with external pull-ups.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
wolfram2
Associate II
Posted on June 02, 2011 at 03:50

Hello clive,

first, thanks for your fast reply.

Yap, we already tried that and we're using pull up resistors. Unfortunately that didn't help anything either.

Best Regards,

BB

Posted on June 02, 2011 at 18:17

Have you examined the SCL,SDA on a scope or logic analyzer?

Have you tried something lower that 400 KHz, have you confirmed the rate generated is 400 KHz?

The other things to look at, are clock enables, and initialization order. You might also need spin loops before the START or after the STOP, to confirm the I2C peripheral (STM32) is in the correct state.

The following is probably how I'd test this first :

/* GPIOB Periph clock enable */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

/* I2C1 Periph clock enable */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

/* I2C1 SDA and SCL configuration */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;

GPIO_Init(GPIOB, &GPIO_InitStructure);

I2C_Cmd(I2C1, ENABLE); /* All examples enable, then configure */

I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

I2C_InitStructure.I2C_OwnAddress1 = 0x52;

I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

I2C_InitStructure.I2C_ClockSpeed = 400000;

I2C_Init(I2C1, &I2C_InitStructure);

  /* Send I2C1 START condition */

  I2C_GenerateSTART(I2C1, ENABLE);

  /* Test on I2C1 EV5 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

  /* Send slave Address for write */

  I2C_Send7bitAddress(I2C1, 0x52, I2C_Direction_Transmitter);

  /* Test on I2C1 EV6 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

  /* Send I2C1 data */

  I2C_SendData(I2C1, 100);

  /* Test on I2C1 EV8 and clear it */

  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

  /* Send I2C1 STOP Condition */

  I2C_GenerateSTOP(I2C1, ENABLE);

Confirming the bus sequencing, and ACK's were occurring properly.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
philipp239955_stm1
Associate
Posted on June 05, 2011 at 14:19

Your're a programming god! 

With this code it works perfect.

Really weird that only one line of code was responsible for the whole i2c bus locking up.

Thanks really much

best regards

Phil/Wolfram