Zur Übersicht - INFO - Neueste 50 Beiträge - Neuer Beitrag - Suchen - Zum C-Control-I-Forum - Zum C-Control-II-Forum

Re: Interrupt-Problem? Kategorie: Programmierung C (von Wolfgang - 31.03.2009 21:08)
Als Antwort auf Re: Interrupt-Problem? von PeterS - 31.03.2009 13:29
Ich nutze:
C-Control Pro Mega128
> > Hallo Peter,
> >
> > in meinem eigenen Board wird von externer Logik alle 20ms ein Interrupt an IRQ1 erzeugt, bei dem
> > meine Schaltung darauf angewiesen ist, dass er innerhalb 10ms zwei ADC-Werte ausliest, die später
> > nicht mehr korrekt anstehen. Das klappt auch fast immer, aber etwa alle 700s (!) geht es mehrmals
> > hintereinander (für länger als 1s) schief.
> >
> > Zur �berprüfung ziehe ich einen Pin high, sobald ich in der ISR-Routine bin, und setze den Pin
> > wieder runter, nachdem ich die AD-Wandler gelesen habe. Dann kann ich auf einem Oszilloskop
> > ansehen, wie lange es vom Ziehen des IRQ-Pins bis zum Eintritt in die ISR-Routine dauert. Meine
> > Beobachtung: während es normalerweise ca. 50..55µs sind, sind es bei den Ausreissern ziemlich
> > genau 10ms, also stolze 200-mal so lange! Mir scheint, das kann nicht mit der Bearbeitungsdauer
> > des gerade bearbeiteten Befehles zu erklären sein, oder?
> >
> > In meinem kompletten Programm habe ich einen weiteren externen IRQ zu bearbeiten (auf IRQ5) sowie
> > beide serielle Schnittstellen im Interrupt-Modus laufen, aber das habe ich zur Fehlersuche alles
> > abgeschaltet/weggelassen, ohne dass sich am Fehlerbild irgendetwas geändert hätte.
> >
> > Meine Einrichtung des IRQ1 lautet folgendermassen:
> >
> > #define IRQ1     25
> > #define In  0
> > #define negEdge   2                                         // IRQ bei fallender Flanke
> >  ...
> >   Port_DataDirBit(IRQ1, In);
> >   Irq_SetVect(INT_1,Waage_IRQ);                     // Interrupt-Routine zum Auslesen der ADCs
> >   Ext_IntEnable(1, negEdge);                            // Enable IRQ_1 mit Mode=2: 'falling Edge'
> >
> >
> > Die ISR-Routine sieht so aus:
> >
> > #define EXP_PA6   6                                       // Marker für regelnden 10ms-IRQ
> > #define Low    0
> > #define High   1
> > ...
> > void Waage_IRQ(void)
> > { Port_WriteBit(EXP_PA6, High);                      // Marker setzen
> >
> >   ADC_Set(ADC_VREF_VCC, ADC_An_B); An_B = ADC_Read();
> >   ADC_Set(ADC_VREF_VCC, ADC_A_Bn); A_Bn = ADC_Read();
> >
> >   Port_WriteBit(EXP_PA6, Low);                       // Marker löschen
> >   ...
> >   Irq_GetCount(INT_1);
> > }
> >
> > (An_B und A_Bn sind globale Integer-Variablen)
> >
> >
> > Mir schleicht der Verdacht im Hinterkopf herum, dass das vielleicht etwas mit dem eingebauten Timer-
> > Interrupt zu tun haben könnte, der ja 10ms-Ticks liefern soll - kann der gelegentlich vielleicht so lange
> > brauchen? Oder kann ich den irgendwie komplett abschalten?
> >
> > Fällt Dir sonst irgendetwas ein, was ich prüfen oder ändern sollte? Erledigt Dein System gelegentlich
> > irgendeine nach aussen nicht sichtbare Sonderaufgabe (zumindest früher war mal 'Garbage Collect'
> > so ein Kandidat)? Bin für jeden Tip dankbar, nachdem ich schon ziemlich lange gesucht habe, bis ich
> > wenigstens das Phänomen soweit beschreiben konnte.
>
> Alle 700s sind schon ein merkwürdiger Wert. Kann meines Wissens nichts mit dem 10ms Interrupt
> zu tun haben. Langwierige Flie�komma Operationen können so lang innerhalb eines Bytecodes dauern.
> Man kann zu Testzwecken mit den Direct Access Befehlen den Timer 2 Interrupt ausschalten.
> Siehe Mega128 Refernzhandbuch.
>
> Gruss Peter
>
Danke für die schnelle Antwort!

Deinem Vorschlag folgend habe ich zunächst in meine (von einem externen IRQ5 angestossene)
sekündlichen ISR-Routine eingebaut, dass das Ergebnis von Timer_TickCount() ausgegeben wird,
um erkennen zu können, ob er Timer-IRQ noch läuft.

Im normalen Betrieb bekomme ich stets eine 100 gemeldet. Nach spätestens 15 Minuten (ganz genau
hab' ich es einstweilen nicht ausgemessen) sehe ich auf dem Oszilloskop verspätet ausgeführte
ISR-Routinen.

Ich habe dann per

  DirAcc_Write(0x57, 0);

den Timer2-IRQ stillgestellt (diese zusätzliche Anweisung, die nur einmal beim Programmstart aus-
geführt wird, ist wirklich die einzige �nderung am Programm!). Meine sekündliche ISR-Routine meldet
passen stets 0 als Timer-Fortschritt.

Das Programm läuft jetzt seit über einer halben Stunde fehlerfrei - mir scheint, das deutet auf einen
Zusammenhang hin, auch wenn das erstmal schwer zu verstehen ist!

Was tun?

GruÃ?,
Wolfgang

> >
> > besten GruÃ?,
> > Wolfgang
> >
> >


    Antwort schreiben


Antworten:

Re: Interrupt-Problem? - Nachtrag (von Wolfgang - 31.03.2009 21:57)