AnsweredAssumed Answered

I2C slave clock stretching

Question asked by chang.khai_yuan on Jul 21, 2014
Hi everyone I am Khai.

Currently I am working with STM32F103ZE. I would like to test on clock stretching by using a delay()-function. But seems like it doesn't work. Any advice or suggestion on how to make a test for clock stretching?

Belows are my written code:
INIT
void I2C_Initi (I2C_TypeDef *i2cx, int OwnAddress, I2C_Callback_t *callWr, I2C_Callback_t *callRd) {
    I2C_InitTypeDef  I2C_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    uint32_t clock_en;

    callbackWr = callWr;
    callbackRd = callRd;

    switch((unsigned int)i2cx) {
    case (unsigned int)I2C1: clock_en = RCC_APB1Periph_I2C1; break;
    case (unsigned int)I2C2: clock_en = RCC_APB1Periph_I2C2; break;
    default:
        printf("I2C_Initi bad i2cx %p",i2cx );
        return;
        break;
    }
    RCC_APB1PeriphClockCmd(clock_en, ENABLE);

    I2C_StructInit(&I2C_InitStructure);

    I2C_InitStructure.I2C_ClockSpeed = 100000;
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = OwnAddress;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

    I2C_Init(i2cx, &I2C_InitStructure);

    I2C_ITConfig(i2cx, I2C_IT_BUF|I2C_IT_EVT|I2C_IT_ERR, ENABLE);

    I2C_Cmd(i2cx, ENABLE);
    I2C_StretchClockCmd(i2cx, ENABLE);

    // configure NVIC I2C interrupt
    NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = I2C2_ER_IRQn;
    NVIC_Init(&NVIC_InitStructure);
}

INTERRUPT HANDLER

void I2C2_EV_IRQHandler(void) {
    uint32_t event;

    //I2C_StretchClockCmd(I2C2, ENABLE);
    //delay_us(I2C_Delay);
    event = I2C_GetLastEvent(I2C2);

    switch(event) {
    // sending to MASTER
    case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
        I2C_SendData(I2C2, i2c_buf_tx[0]);
        tx_count=1;
        break;
    case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:
        I2C_SendData(I2C2, i2c_buf_tx[tx_count]);
        tx_count++;
        if(tx_count>=i2c_send_len-1)
            GPIO_S(gpios+GPO_HOOK_PTT, 0);
        break;
    case I2C_EVENT_SLAVE_ACK_FAILURE:
        /// tell main loop it is done, for example setting i2c_send_len to 0
        if(callbackRd)
            callbackRd(tx_count, (uint8_t*)i2c_buf_tx);
        tx_count=0;
        break;

        // receiving from MASTER
    case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
        I2C_StretchClockCmd(I2C2, ENABLE);
       delay_us(I2C_Delay) ; // delay 20 us
        //i2c_buf_rx[0]=I2C_ReceiveData(I2C2);
        //rx_count=1;
        break;
    case I2C_EVENT_SLAVE_BYTE_RECEIVED:
        delay_us(I2C_Delay); // delay 20 us
        //I2C_StretchClockCmd(I2C2, ENABLE);
        i2c_buf_rx[rx_count]=I2C_ReceiveData(I2C2);
        rx_count++;
        break;
    case I2C_EVENT_SLAVE_STOP_DETECTED:
          delay_us(I2C_Delay); // delay 20 us
        //I2C_StretchClockCmd(I2C2, ENABLE);
        if(callbackWr)
            callbackWr(rx_count, (uint8_t*)i2c_buf_rx);
        I2C_AcknowledgeConfig(I2C2, ENABLE);
        rx_count=0;
        break;
    default:
        err_count++;
        err_event = event;
        break;
    }
    last_event = event;
}

Thank you.

Outcomes