STM32L Interrupt wird blockiert

Gast #1975051
Lesenswert?

Hi,

Ich benutze den I2C2 des STM32L mit dem SMBus bzw PMBus Protokoll. Um 
die Adressen am Bus herauszufinden Frage ich jede Adresse ab und warte 
auf einen Timeout. Wenn dieser nicht stattfindet ist die Address gültig 
und wird gespeichert.

In meinem Code hab ich das ganze mit einer for-Schleife über alle 
Adressen von 0x01 - 0x7F gelöst. Da die I2C Routine Event Abhängig ist 
musste ich aber ein paar warte schleifen Einbauen. Als erstes Warte ich 
bis meine Bytes versendet werden, dann warte ich bis das I2C Busy Flag 
gelöscht ist und als letztes warte ich bis die hardware das Stopbit Flag 
gelöscht hat. Sollte von der Theorie her funktionieren. Jedoch springt 
der controller seit dem ich die Schleifen implementiert habe nicht mehr 
in die Interrupt Routine sonder pollt nur noch die Bytes die noch 
versendet werden sollen (erste Schleife), die jedoch nie versendet 
werden können, da die Interrupt Routine nicht startet.

Für Infos und Tips würde ich mich sehr freuen und bedanke mich bereits 
dafür.

Gruß R. Griesser

Code:

for - Schleife:

extern "C" void EXTI1_IRQHandler(void)
{
  int i;
  GPIO_SetBits(GPIOA,GPIO_Pin_12);
  for (i=0;i<100000;i++);  // wait a bit
  GPIO_ResetBits(GPIOA,GPIO_Pin_12);
  for (i=0;i<100000;i++);  // wait a bit


  int bufferPointer = 0;
  data[0] = 0x01;
  data[1] = 0x80;

  for (i=0x01;i<0x7F;i++)
  {
    address = i;
    success = 0;
    bytes = 2;
    transmitted = 0;

    //enable I2C2 interrupts
    I2C_ITConfig(I2C2, (I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF), ENABLE);

    //transfer data
    I2C_GenerateSTART(I2C2,ENABLE);

    //wait until all bytes are transmitted
    while (bytes > 0);
    //wait until I2C Busy flag is cleared
    while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));
    //Wait until Stop bit is cleared by hardware
    while ((I2C2->CR1 & I2C_CR1_STOP) == I2C_CR1_STOP);

    if (success == 0)
    {
      addressBuffer[bufferPointer] = address;
      bufferPointer++;
    }
  }

  EXTI_ClearITPendingBit(EXTI_Line1);
}

I2C Interrupt Routine:

extern "C" void I2C2_EV_IRQHandler(void)    //I2C2 event interrupt
{

  Event = I2C_GetLastEvent(I2C2);

  switch (Event)
  {
    case I2C_EVENT_MASTER_MODE_SELECT:
      I2C_Send7bitAddress(I2C2,address,I2C_Direction_Transmitter);
      break;

    case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED:
      I2C_SendData(I2C2,data[transmitted]);
      transmitted++;
      bytes--;
      if(bytes == 0)
      {
        I2C_ITConfig(I2C2, I2C_IT_BUF, DISABLE);
      }
      break;

    case I2C_EVENT_MASTER_BYTE_TRANSMITTING:
      I2C_SendData(I2C2,data[transmitted]);
      transmitted++;
      bytes--;
      if(bytes == 0)
      {
        I2C_ITConfig(I2C2, I2C_IT_BUF, DISABLE);
      }
      break;

      case I2C_EVENT_MASTER_BYTE_TRANSMITTED:
          I2C_GenerateSTOP(I2C2, ENABLE);
          transmitted = 0;
          I2C_ITConfig(I2C2, I2C_IT_EVT, DISABLE);
          break;

    default:
      break;
  }
    I2C_ClearFlag(I2C2,I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF);
    I2C_ClearITPendingBit(I2C2,I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF);
}
Gast #1975093
Lesenswert?

1. dir ist bewusst das du da in einem Interrupt Warteschleifen einbaust? 
Und das nedmal wenige?

2. Wie hast du deine Variablen definiert? Insbesondere "byte"

3. Du schickst im falschen "Event" das nächste Byte raus.. Erst schicken 
wenn "BYTE_TRANSMITTED" auftritt, checken ob noch mehr Daten notwendig 
sind, wenn ja schicken, wenn nein Stop.

Überdenke nochmal deine Idee...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren