stm32f4上的I2C从接收器

时间:2012-03-26 10:02:34

标签: embedded interrupt-handling i2c stm32 slave

我尝试在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现在很低。参考手册说如果我清除地址标志,时钟将继续,数据将被发送(Page 579 - 从属接收器)。在我看来,如果有任何数据到达,中断总是被调用,下一个状态将是I2C_EVENT_SLAVE_BYTE_RECEIVED。

我无法从stm或google找到任何示例。任何人都可以帮助我或给我一个例子。

2 个答案:

答案 0 :(得分: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;
  }
}

答案 1 :(得分:0)

硬件正在进行时钟延长,以确保从机跟上主机。奴隶首先等待获得地址匹配。然后在SCL保持低电平时中断。这允许从站基本上为主站提供流量控制。主设备检测到SCL被从设备保持为低电平,并且它将在主设备发送更多数据之前等待它被释放。因此,在接收数据时,您不会获得额外的中断,因为在您让SCL变高之前,主服务器不会再发送任何数据。您可以在此处阅读有关时钟延长的信息http://en.wikipedia.org/wiki/I%C2%B2C