2012-03-26 20 views
4

私はstm32f4でi2cスレーブレシーバ割り込みサービスルーチンを実装しようとしています。 ここに私のスマートなコードがあります。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から例が見つかりません。誰かが私を助けたり、私に例を示すことができます。

+0

上記のコードの1つのエラーは、いずれの場合も肯定応答がありません。私の場合、マスターと通信する他のスレーブもあります。だから私のスレーブを初期化した後、バスで聴く。私は私のコミュニケーションの一部ではないストップビットを受け取ります。だから私はストップビットを削除することができません。また、私が思ったほどADDRフラグをリセットするのは簡単ではありません。 –

答えて

2

これは動作します。私の問題は、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

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

+0

H TJDあなたの答えに感謝します。しかし、私の推薦で述べたように、私は、ADDRレジスタが読み込まれて空になるまで、スレーブがSCLをローに保持していることを知っています。これは問題ではありません –

+0

私はあなたの実際の質問が何であるか混乱していると思います。 – TJD