2017-06-08 06:59 PM
I am using STM32Fxx library. I am not using STMCubemx. Issue I am facing is that the first time I run I2C communication after turning on MCU, the busy flag timeout occurs.
while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)) {if (++timeout > 2000) return; }
I2C_GenerateSTART(I2C1, ENABLE);
what could be the reason for I2C_FLAG_BUSY flag to be set although the line is free ?
I have also initialized GPIO pins while initializing
On running I2C communication after that, on transmitting 7 bit address using
'I2C_Send7bitAddress(I2C2, 0x34<<1, I2C_Direction_Transmitter);'
the device timeouts every time. Do I need to add any other function before the above function ?
Timeout function is below
'while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))'
On doing this operation repeatedly, both of my I2C1 and I2C2 ports are damaged. The MCU is unable to pull them low after issuing I2C start command. (3.3V on SCL, SDA pins after I2C Start.)
Is the 7-bit address timeout occurring because of Nack or some other reasons ?
Do I need to initialize GPIO pins for I2C initialization ?
SCL and SDA pins are pulled up using 3.3k ohm resistors. I doubt if I2C initialization part is correct. I have tried most options to initialize I2C Initialization structure. I tried using GPIO_OType as GPIO_OType_PP and GPIO_OType_OD but there is no difference. Because of this, my I2C1 and I2C2 ports are also damaged. I have been unable to locate the problem. When I2C1 and I2C2 pins were OK, timeout occurred every time after sending 7-bit address.
Using bit banging for I2C with same 7-bit address, it works fine.[before sda and scl pins are responsive]
My code is below:
/********************************* I2C code ********************************/
void I2C_initialize(void)
{ GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStruct;RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); // enable APB1 peripheral clock for I2C2
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // enable clock for SCL and SDA pins 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; GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // enable pull up resistors GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOB, &GPIO_InitStruct); // init GPIOB GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11; GPIO_Init(GPIOB, &GPIO_InitStruct); // init GPIOB// Connect I2C2 pins to AF
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2); // SCL GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2); // SDAI2C_DeInit(I2C2);
//I2C_Cmd(I2C2, ENABLE);// configure I2C2
I2C_InitStruct.I2C_ClockSpeed = 50000; // 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_Disable; // 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 I2C2I2C_Cmd(I2C2, ENABLE);// enable I2C2
} void I2C_write(uint8_t data) { I2C_SendData(I2C2, data); // wait for I2C2 EV8_2 --> byte has been transmitted while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); } uint8_t I2C_read_nack(I2C_TypeDef* I2Cx) { uint8_t data; // Disable acknowledge of received data I2C_AcknowledgeConfig(I2Cx, DISABLE); I2C_GenerateSTOP(I2Cx, ENABLE);// wait until one byte has been received
while( !I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED) ); // read data from I2C data register and return data byte data = I2C_ReceiveData(I2Cx); return data; } void get_data(void) { uint8_t state = 0, data; uint16_t timeout = 0;Uart1_Printf('Start\n');
while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)) { if (++timeout > 2000){Uart1_Printf('Busy\n'); return
; } } I2C_GenerateSTART(I2C2, ENABLE); Delay_us(10);Uart1_Printf('check start event\n');
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)) { Delay_us(1); if (++timeout >= 2000) { Uart1_Printf('Stop\n'); I2C_GenerateSTOP(I2C2, ENABLE); return; } } Delay_us(10);Uart1_Printf('master transmit\n');
I2C_Send7bitAddress(I2C2, 0x34<<1, I2C_Direction_Transmitter); // send device I2C address Delay_ms(10);while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{ if (timeout++ >= 2000) /****** timeout occurring here every time hence unable to proceed *****/ { Uart1_Printf('master transmit event timeout\n'); I2C_GenerateSTOP(I2C2, ENABLE); return; } } Delay_us(10); Uart1_Printf('TX 00\n'); I2C_write(0x00); Uart1_Printf('TX 01\n'); I2C_write(0x01);Uart1_Printf('Stop\n');
I2C_GenerateSTOP(I2C2, ENABLE);Uart1_Printf('Restart\n');
while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY)) { if (++timeout > 2000) {Uart1_Printf('Restart timeout\n'); break; }} I2C_GenerateSTART(I2C2, ENABLE); Delay_us(10);Uart1_Printf('check restart event\n');
while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT)) { Delay_us(1); if (++timeout >= 2000) { Uart1_Printf('Stop\n'); I2C_GenerateSTOP(I2C2, ENABLE); //I2C_engine_stop(); return; } } Delay_us(10);Uart1_Printf('master receive\n');
I2C_Send7bitAddress(I2C2, 0x34<<1, I2C_Direction_Receiver); // send device I2C address Delay_us(10);while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{ if (timeout++ >= 2000) { Uart1_Printf('master receive event timeout\n'); I2C_GenerateSTOP(I2C2, ENABLE); //I2C_engine_stop(); return; } }data = I2C_read_nack(I2C2);
Uart1_Printf('data: %d\n', data); } /********************************* Main code ******************************* /int main(void)
{ // other initializations I2C_initialize(); while (1) { if (switch) { get_data(); } } }/********************************* Output ********************************* /
Start
Busy
Start
check start event master transmit master transmit timeoutevent Stop #i2c-hardware #i2c-master