AnsweredAssumed Answered

STM32F407VG I2C slave not getting I2C_EVENT_SLAVE_BYTE_TRANSMITTED event

Question asked by ellis.andrew.001 on Jul 4, 2016

I am working on a project where I have got an STM32F407VG set up as an I2C slave. I'm able to receive incoming bytes correctly, and I'm able to send one byte without issue. However I need to be able to send multiple bytes to the mast, but I'm unable to do so.

The I2C interface is initialised with:

void init_i2c_slave()
    I2C_InitTypeDef I2C_InitStructure;
    NVIC_InitTypeDef    NVIC_InitStructure;
    /* I2C configuration ---------------------------------------------------------*/
    /* Initialize I2C peripheral */
    /* I2C Init */
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DUTYCYCLE;
    I2C_InitStructure.I2C_OwnAddress1 = SLAVE_ADDRESS;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init(I2Cx, &I2C_InitStructure);
    // I2C1 interrupts
    NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_BUF | I2C_IT_ERR, ENABLE);
    I2C_StretchClockCmd(I2Cx, ENABLE);
    I2C_Cmd(I2Cx, ENABLE);

And I have the following to handle event interrupts:

//Clear ADDR by reading SR1, then SR2
void I2C_clear_ADDR()
    I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR);
//Clear STOPF by reading SR1, then writing CR1
void I2C_clear_STOPF()
    I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF);
    I2C_Cmd(I2Cx, ENABLE);
void I2C1_BUF_IRQHandler()
    buf[0] = I2C_ReceiveData(I2C1);
    I2C_ClearITPendingBit(I2Cx, I2C_IT_BUF);
void I2C1_EV_IRQHandler(void)
    char num_msg = 0;
    if(I2C_GetITStatus(I2Cx, I2C_IT_AF)) I2C_ClearITPendingBit(I2Cx, I2C_IT_AF);
    switch (I2C_GetLastEvent(I2Cx))
            I2C_Regs[reg_idx++] = I2C_ReceiveData(I2Cx);
            //Decode command
            switch (I2C_Regs[0])
                case 0x03: // read gennum register previously selected
                    I2C_SendData(I2Cx, I2C_Regs[reg_idx++]);                   
                        I2C_SendData(I2Cx, I2C_Regs[reg_idx++]);   
        case I2C_EVENT_SLAVE_ACK_FAILURE://End of transmission EV3_2           
            I2C_ClearITPendingBit(I2Cx, I2C_IT_AF);
void I2C1_ER_IRQHandler(void)
        //GPIO_SetBits(GPIOD, RED);
        //Can't use nice switch statement, because no fxn available
        if(I2C_GetITStatus(I2Cx,        I2C_IT_SMBALERT)) {
        } else if(I2C_GetITStatus(I2Cx, I2C_IT_TIMEOUT)) {
        } else if(I2C_GetITStatus(I2Cx, I2C_IT_PECERR)) {
        } else if(I2C_GetITStatus(I2Cx, I2C_IT_OVR)) {
            //CLK stretch disabled and receiving
            //DR has not been read, b4 next byte comes in
            //effect: lose byte
            //should:clear RxNE and transmitter should retransmit
            //CLK stretch disabled and I2C transmitting
            //haven't updated DR since new clock
            //effect: same byte resent
            //should: make sure discarded, and write next
        } else if(I2C_GetITStatus(I2Cx, I2C_IT_AF)) {
            //Detected NACK
            //Transmitter must reset com
                //Slave: lines released
                //Master: Stop or repeated Start must must be generated
                //Master = MSL bit
            I2C_ClearITPendingBit(I2Cx, I2C_IT_AF);
        } else if(I2C_GetITStatus(I2Cx, I2C_IT_ARLO)) {
            //Arbitration Lost
            //Goes to slave mode, but can't ack slave address in same transfer
            //Can after repeat Start though
        } else if(I2C_GetITStatus(I2Cx, I2C_IT_BERR)) {
            //Bus Error
            //In slave mode: data discarded, lines released, acts like restart
            //In master mode: current transmission continues

I have spent a lot of time searching for an answer to this issue, and have studied the reference manual, but I can't see what I've missed in the I2C set up which means that I dodn't get the I2C_EVENT_SLAVE_BYTE_TRANSMITTED. I have watched the trace from master to slave on a logic analyser and can see the the transmitter is generating clocks, but the mcu is not sending anything.

Can someone please give me a hint as to what I've missed

Thank you