I2C подчиненный приемник на stm32f4 - PullRequest
4 голосов
/ 26 марта 2012

Я пытаюсь реализовать подпрограмму обслуживания прерываний подчиненного приемника i2c на stm32f4. Вот мой умный кусок кода.

void I2C2_EV_IRQHandler()
  {
    switch (I2C_GetLastEvent(I2C2))
    {
    //The address sent by the master matches the own address of the peripheral
    case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
        //The slave stretches SCL low until ADDR is
        //cleared and DR filled with the data to be sent
        I2C_ClearFlag(I2C2,I2C_FLAG_ADDR);
        break;

    //The application is expecting a data byte to be received
    case I2C_EVENT_SLAVE_BYTE_RECEIVED:
        I2C_ReceiveData(I2C2);
        break;

    //The application is expecting the end of the communication
    //Make sure that both ADDR and STOPF flags are cleared
    //if both are found set.
    case I2C_EVENT_SLAVE_STOP_DETECTED:
        if(I2C_GetFlagStatus(I2C2,I2C_FLAG_ADDR) == SET)
            I2C_ClearFlag(I2C2,I2C_FLAG_ADDR);
        if(I2C_GetFlagStatus(I2C2,I2C_FLAG_STOPF) == SET)
            I2C_ClearFlag(I2C2,I2C_FLAG_STOPF);
}

}

Прерывание становится вызванным, и вводится случай I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED. SCL сейчас низкий. В справочном руководстве сказано, что если я сниму флажок адреса, часы продолжатся, и данные будут отправлены (Страница 579 - Подчиненный приемник). По моему мнению, прерывание всегда вызывается, если поступают какие-либо данные, и следующее состояние будет I2C_EVENT_SLAVE_BYTE_RECEIVED.

Не могу найти ни одного примера из stm или через гугл. Кто-нибудь может мне помочь или показать мне пример.

Ответы [ 2 ]

2 голосов
/ 29 марта 2012

теперь это работает.Моя проблема заключалась в том, что я не смог сбросить ADDR и регистр STOPF с данными командами из справочного руководства.Но если сделать это в цикле, он прекрасно работает для меня.Здесь моя рабочая программа прерываний.

 void I2C3_EV_IRQHandler()
 {
     switch (I2C_GetLastEvent(I2C3))
     {

    case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
        STM_EVAL_LEDOn(LED3);
        STM_EVAL_LEDOff(LED5);
        break;

    case I2C_EVENT_SLAVE_BYTE_RECEIVED:
        STM_EVAL_LEDToggle(LED4);
        STM_EVAL_LEDOff(LED3);
        I2C_InputBuffer[I2C_InputBufferIndex++] = I2C_ReceiveData(I2C3);
        break;

    case I2C_EVENT_SLAVE_STOP_DETECTED:
        STM_EVAL_LEDOn(LED6);
        STM_EVAL_LEDOff(LED4);
        break;
    }

    I2C_CleanADDRandSTOPF();

    if(I2C_InputBufferIndex > MOTOR_PACKAGE_SIZE-1)
    {
      motorHandleEvent(I2C_InputBuffer);
      I2C_InputBufferIndex = 0;
      uint8_t resetIndex;
      for(resetIndex = 0; resetIndex < MOTOR_PACKAGE_SIZE; resetIndex ++)
        I2C_InputBuffer[resetIndex] = 0;
    }
}

inline void I2C_CleanADDRandSTOPF()
{
  while ((I2C3->SR1 & I2C_SR1_ADDR) == I2C_SR1_ADDR)
  {
    volatile uint32_t temp;
    temp=I2C3->SR1;
    temp=I2C3->SR2;
  }
  while ((I2C3->SR1&I2C_SR1_STOPF) == I2C_SR1_STOPF)
  {
    volatile uint32_t temp;
    temp=I2C3->SR1;
    I2C3->CR1 |= 0x1;
  }
}
0 голосов
/ 26 марта 2012

Аппаратное обеспечение выполняет растяжение часов, чтобы убедиться, что ведомое устройство идет в ногу с ведущим. Раб сначала ожидает совпадения адресов. Затем вы получаете прерывание, пока SCL удерживается на низком уровне. Это позволяет ведомому в основном обеспечивать управление потоком ведущему устройству. Ведущий обнаруживает, что ведомый уровень удерживает низкий уровень вероятности нежелательной почты, и будет ожидать его освобождения, прежде чем мастер отправит больше данных. Таким образом, вы не получите дополнительных прерываний при получении данных, потому что мастер не будет отправлять больше данных, пока вы не позволите SCL повыситься. О растяжке часов вы можете прочитать здесь http://en.wikipedia.org/wiki/I%C2%B2C

...