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

Re: Interrupt-Problem? - Nachtrag Kategorie: Programmierung C (von Wolfgang - 31.03.2009 21:57)
Als Antwort auf Re: Interrupt-Problem? von Wolfgang - 31.03.2009 21:08
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
>

Nachtrag: ich habe mittlerweile als Gegenprobe den 10ms-IRQ wieder zugelassen und bekomme auch
prompt wieder die Ausreisser. Es scheint, als kämen sie ca. alle 11 Minuten, d.h. 660s = 66000*10ms.
Meine These: es geschieht bei 65536ms, also dann, wenn der Tick_Count überläuft!?!?

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


    Antwort schreiben


Antworten: