2011-06-01 06:12 PM
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²c2011-06-01 06:21 PM
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.2011-06-01 06:50 PM
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, BB2011-06-02 09:17 AM
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.2011-06-05 05:19 AM
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