AnsweredAssumed Answered

I2C checkevent hang

Question asked by Luke on Apr 21, 2016
Hi all,
I am writing a program on the STM32F446 in which I am trying to talk with a PCM sound module via I2C. I am attempting to read its registers, which involves sending the register number and then reading the value back. Unfortunately my program cannot get past the sending of the register request as it seems to be hanging whilst waiting for I2C_EVENT_MASTER_BYTE_TRANSMITTED event to occur. Looking at the scope everything appears to be fine - the module acknowledges its address, my program sends the byte to indicate the register to read, then the module holds data low to acknowledge the byte, however my program does not seem to pick up the successful transfer of the byte and hangs on the while condition. My code is below... when calling I2C_readreg() we successfully start the transaction and then call I2C_write(), in which we hang on
  while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

So apparently byte transmission event is never being acknowledge, even though the scope shows that it has been put onto the line. Does anybody have any ideas what could be going wrong here?



void I2C_init(void) {
     I2C_InitTypeDef  I2C_InitStructure;


     GPIO_InitTypeDef GPIO_InitStructure;
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // I2C CLK
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//NOPULL;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; // I2C DATA
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//NOPULL;
     GPIO_Init(GPIOC, &GPIO_InitStructure);
     GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C_CLK);
     GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_I2C_DATA);

    //Reset
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);

     I2C_InitStructure.I2C_ClockSpeed = 250000;
     I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

    I2C_Init(I2C2, &I2C_InitStructure);
    I2C_Cmd(I2C2, ENABLE);
}

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));
     //while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
}


void I2C_readreg() {
     uint8_t received_data[2];

     I2C_start(I2C2, RTC_address, I2C_Direction_Transmitter); 
     I2C_write(I2C2, 0x12); // register
//PROGRAM HANGS IN THIS WRITE

     I2C_start(I2C2, RTC_address, I2C_Direction_Receiver); // start a transmission in Master receiver mode
     //received_data[0] = I2C_read_ack(I2C2); // read one byte and request another byte
     received_data[0] = I2C_read_nack(I2C2); // read one byte and don't request another byte, stop transmission

     I2C_stop(I2C2); // stop the transmission
}


Outcomes