www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik STM32L Interrupt wird blockiert


Autor: R Griesser (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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);
}

Autor: bubi_00 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: R Griesser (Gast)
Datum:

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

Autor: R Griesser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke dir ich werd das nochmal überarbeiten...
PS: Die Variable ist global

Autor: bubi_00 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab eher an volatile gedacht ;)

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.