AnsweredAssumed Answered

Unable to see why I2C3 is not functioning?

Question asked by roofie01 on May 3, 2015
Hi,

I have been looking at this for hours, but cannot determine why I cannot get the I2C3 operating, even getting a pulse from the SCK line. I am using an STM32F4 device, with an ST LIS3DML sensor.
Both SCK and SDA are physically pulled to Vdd with a  10K resistor.

GPIO and call to I2C init is below:

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 pin
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    // enable clock for SDA pin
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);    

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;           
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;        
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    
    GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;        
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;    
    GPIO_Init(GPIOA, &GPIO_InitStruct);                

    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;          
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;        
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;    
    GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;        
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;    
    GPIO_Init(GPIOC, &GPIO_InitStruct);                
    
    // Connect I2C3 pins to AF  
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_I2C3);    // SCL
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_I2C3); // SDA
    
    // configure I2C3
    I2C_InitStruct.I2C_ClockSpeed = 100000;         // 100kHz
    I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;        
    I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStruct.I2C_OwnAddress1 = 0x00;            
    I2C_InitStruct.I2C_Ack = I2C_Ack_Disable;        
    I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init(I2C3, &I2C_InitStruct);                
    
    // enable I2C3
    I2C_Cmd(I2C3, ENABLE);
}

Below is the I2C start, and the I2C send:

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));
    }
}

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));
}

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;
}

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;
}

From main, I call:

#define LIS3MDL_ADDRESS      0x1C
#define LIS3MDL_WHO_AM_I     0x0F  // should return 0x3D

    init_I2C3();
    I2C_start(I2C3, LIS3MDL_ADDRESS<<1, I2C_Direction_Transmitter);
    I2C_write(I2C3, LIS3MDL_WHO_AM_I);
    //I2C_read_nack(I2C3);
    I2C_read_ack(I2C3);

However, when scoping the SCK line, there is never a clock burst from the STM32F4. In fact, it hangs the processor if I try to use either read call above.

Any idea of what the problem might be?

Thank you for any help...




Outcomes