Forum: Mikrocontroller und Digitale Elektronik STM32L Interrupt wird blockiert


von R Griesser (Gast)


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);
}

von bubi_00 (Gast)


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...

von R Griesser (Gast)


Lesenswert?

Problem gelöst. Habe den Code aus der IR exportiert und nun funktioneirt 
es!

von R Griesser (Gast)


Lesenswert?

Danke dir ich werd das nochmal überarbeiten...
PS: Die Variable ist global

von bubi_00 (Gast)


Lesenswert?

Hab eher an volatile gedacht ;)

Aber zumindest gehts jetzt mal :) optimieren kannst ja dann noch

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.