AnsweredAssumed Answered

STM 32 F4 Discovery I2C Hanging Up

Question asked by donaldson.kyle on Nov 21, 2013
Latest reply on Nov 23, 2013 by donaldson.kyle
Hi, I am having a problem with using the I2C on the STM 32 F4 discovery to read 3 DevanTech SRF-08 ultrasonic sensors, There was a previous post on this matter, but it was unresolved as far as I know, clive1 did indiacte that the problem was in addressing, 10 bit vs 7 bit but I dont know how to make it work never the less, please can you help me. 
I am pasting the Initialisation code for the I2C and the fucntions I am using the try and read the ultrasonics. (I am working in the free version of Atollic True Studio)

// Setup the IIC3 peripheral for the UltraSonic Sensors
void init_I2C3(void){


     GPIO_InitTypeDef GPIO_InitStruct;
     I2C_InitTypeDef I2C_InitStruct;


     // enable APB1 peripheral clock for I2C3
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C3, ENABLE);
     // enable clock for SCL and SDA pins
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
     /* setup SCL and SDA pins
       * 1. SCL on PA8 and SDA on PC9
     */
     // Configure the SCL pin
     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;                    // SCL is on PA8
     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;               // set output to open drain --> the line has to be only pulled low, not driven high
     GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;               // enable pull up resistors
     GPIO_Init(GPIOA, &GPIO_InitStruct);                         // initialize GPIOA
     // Configure the SDA pin
     GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;                    // SDA is on PC9
     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;               // set output to open drain --> the line has to be only pulled low, not driven high
     GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;               // enable pull up resistors
     GPIO_Init(GPIOC, &GPIO_InitStruct);                         // init GPIOC
     // Connect I2C3 pins to AF
     GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_I2C3);     // SCL
     GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_I2C3); // SDA
     // configure I2C3
     I2C_InitStruct.I2C_ClockSpeed = 100000;                // 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(I2C3, &I2C_InitStruct);                         // init I2C1
     // enable I2C3
     I2C_Cmd(I2C3, ENABLE);
}

/* Function to Start I2C communications with specific device */
void I2C_start(I2C_TypeDef* I2Cx, uint8_t address, uint8_t direction){
     // wait until I2C1 is not busy anymore
     while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
     // Send I2C1 START condition
     I2C_GenerateSTART(I2Cx, ENABLE);
     // wait for I2C1 EV5 --> Slave has acknowledged start condition
     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
     // Send slave Address for write
     I2C_Send7bitAddress(I2Cx, address, 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(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
     }
     else if(direction == I2C_Direction_Receiver){
          while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
     }
}
/* Function to write one byte to the I2C device */
void I2C_write(I2C_TypeDef* I2Cx, uint8_t data)
{
     I2C_SendData(I2Cx, data);
     // wait for I2C1 EV8_2 --> byte has been transmitted
     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
/* Function to read the first byte from the I2C device */
uint8_t I2C_read_ack(I2C_TypeDef* I2Cx){
     // enable acknowledge of recieved data
     I2C_AcknowledgeConfig(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
     uint8_t data = I2C_ReceiveData(I2Cx);
     return data;
}
/* Function to read a single byte from the I2C device */
uint8_t I2C_read_nack(I2C_TypeDef* I2Cx){
     // disabe acknowledge of received data
     // nack also generates stop condition after last byte received
     // see reference manual for more info
     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
     uint8_t data = I2C_ReceiveData(I2Cx);
     return data;
}
/* Function to stop communication with the I2C device */
void I2C_stop(I2C_TypeDef* I2Cx){
     // Send I2C1 STOP Condition
     I2C_GenerateSTOP(I2Cx, ENABLE);
}

/* Read all three light sensors and distance sensors and save to relevant state variables */
void Read_Ldr_Us(){
// For the left sensor.
     int HighByte=111;
     int LowByte=333;
     I2C_start(I2C3, USleftAddr>>1, I2C_Direction_Transmitter);
     I2C_write(I2C3,0x01);
     I2C_start(I2C3, USleftAddr>>1, I2C_Direction_Receiver);
     stLDRleft=I2C_read_ack(I2C3);
     HighByte=I2C_read_ack(I2C3);
     LowByte=I2C_read_nack(I2C3);
     stUSleft= ((unsigned int)HighByte <<  + LowByte);
     I2C_stop(I2C3);
// For the front sensor.
     I2C_start(I2C3, USfrontAddr>>1, I2C_Direction_Transmitter);
     I2C_write(I2C3,0x01);
     I2C_start(I2C3, USfrontAddr>>1, I2C_Direction_Receiver);
     stLDRfront=I2C_read_ack(I2C3);
     HighByte=I2C_read_ack(I2C3);
     LowByte=I2C_read_nack(I2C3);
     stUSfront= ((unsigned int)HighByte <<  + LowByte);
     I2C_stop(I2C3);
// For the right sensor.
     I2C_start(I2C3, USrightAddr>>1, I2C_Direction_Transmitter);
     I2C_write(I2C3,0x01);
     I2C_start(I2C3, USrightAddr>>1, I2C_Direction_Receiver);
     stLDRright=I2C_read_ack(I2C3);
     HighByte=I2C_read_ack(I2C3);
     LowByte=I2C_read_nack(I2C3);
     stUSright= ((unsigned int)HighByte <<  + LowByte);
     I2C_stop(I2C3);
}

Please can you have a look at this and tell me what is wrong, I am tearing my hair out! Please comment if I need to add any more information. 

Outcomes