5

stm32f4にi2cスレーブレシーバー割り込みサービスルーチンを実装しようとしています。これが私のスマートなコードです。

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またはgoogle経由で例を見つけることができません。誰かが私を助けたり、例を見せてくれますか?

4

2 に答える 2

3

今それは動作します。私の問題は、リファレンスマニュアルから与えられたコマンドで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;
  }
}
于 2012-03-29T11:33:23.087 に答える
0

ハードウェアは、スレーブがマスターに追いついていることを確認するためにクロックストレッチを実行しています。スレーブは最初にアドレスが一致するのを待ちます。次に、SCLがローに保持されている間に割り込みが発生します。これにより、スレーブは基本的にマスターにフロー制御を提供できます。マスターは、SCLがスレーブによってローに保持されていることを検出し、SCLが解放されるのを待ってから、マスターがそれ以上データを送信します。したがって、SCLをハイにするまでマスターはそれ以上データを送信しないため、受信中のデータに追加の割り込みが発生することはありません。クロックストレッチについては、 http://en.wikipedia.org/wiki/I%C2%B2Cで読むことができます。

于 2012-03-26T17:34:47.700 に答える