PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Interrupt waehrend Interrupt



thomas05
04.11.2005, 15:00
Hallo,

Moechte konstant meine Zeit mittels timer overflow interrupts messen. Waehrend dessen startet aber ab und zu eine andere interruptroutine die bis zu 10msec dauert.
Wie kann ich einstellen dass ich waehrend dessen noch timer interrupts bekomme. Habe schon versucht einfach das GIE Bit am anfang der anderen interruptroutine zu setzen. Dann geht mein Zaehler auch weiter, aber die lange interruptroutine hoert dafuer gar nicht mehr auf.

Danke fuers posten!

mfg Thomas

PicNick
04.11.2005, 16:01
Wahrscheinlich verstrickst du dich irgendwo.
Generell: Eine Interruptroutine mit 10 mS ist absolut verschärft. In der Zeit veralten Betriebssysteme und es gibt drei Sicherheitsupdates für XP
Da solltest du dir was einfallen lassen.

Fritzli
04.11.2005, 17:52
Hallo

1) wie schon gesagt, 10ms sind viel zu lang. Für Quick&Dirty gehts mal, aber sonst ist das schlecht.
2) Interrupt-in-Interrupt benötigt ziemlich viel Aufmerksamkeit beim Programmieren (Stichwort "reentrant code"). Ich würde das sein lassen. Macht auch praktisch kein Mensch, eben weils ziemlich kritisch ist und es sich (meist) vermeiden lässt.
Z.B. kann man in der ISR ein Flag setzen und diese dann wieder verlassen. Falls während des Flag-Setzens weitere INT's generiert werden, werden die ja vom PIC gespeichert und beim Verlassen der ersten ISR, wird dann gleich die nächste getriggert. Das Hauptprogramm kann sich dann um das Flag und die dazugehörigen Abläufe kümmern.

Kannst Du den Code bzw. Teile davon posten?


Gruess
Fritzli

th
07.11.2005, 07:46
Erst mal danke fuers posten, hier unten findest du meine ir-routinen. Der rote Quelltext (SQRT) braucht die 10ms. Vielleicht kann man dass ja auch irgendwie anders machen. PIC ist uebrigens PIC16F628A.

Danke fuer die Hilfe

Thomas

#int_RTCC
RTCC_isr()
{
int_count++;
}

#int_RB
portb()
{
if(test == 0)
{
// Check for 1 because only PIN B0 has the low_to_high detection
if(INFRA == 1)
{
set_timer0(0);
int_count = 0;
test = 1;
}
}

else
{
if(ULTRA == 1)
{

time = int_count * INT_TIME + get_timer0() * MIN_TIME;
// time_in_sec = time * E-6

d = sqrt((time / 1000 * SONIC_SPEED) * (time / 1000 * SONIC_SPEED) - h_2);

// *E-6 that it x is also in mm, the SQRT needs about 10 MS. ONly with 1 Sender is this long time acceptable => d is in mm

if(left == 1)
dist = START_DIST - d;

// dist = distance away from start position

else
dist = START_DIST + d;

if(aim > dist)
output_high(SPEED); // Compare Aim

if(aim <= dist)
{
output_low(SPEED);
end = 1;
}

if(dist > START_DIST)
left = 0;

test = 0;

disable_interrupts(INT_RB);
// Disable Prot B interrupts because ervery interrupt in the next 300ms is wrong
}
}
}

Fritzli
07.11.2005, 09:40
Hallo

Erstmal: Ich weiss, der Compiler kann floats, aber Fliesskommazahlen auf nem PIC sind ein Verbrechen. Nur einsetzen, wenn's gar nicht anders geht. Meist kann man mit Integer-Arithmetik dasselbe erreichen, es laeuft aber viel(!) schneller.
Die ganze float-Berechnung in der ISR gehoert nicht dorthin. Ich kenn zwar Deine Problemstellung nicht, aber da koennte man in der ISR die timerstaende retten, ein Flag setzen, und die ganze Berechnung (falls wirklich noetig) in main machen.

Sieht irgendwie nach Ultraschall-Messung aus. Kannst Du nicht intern mit den direkten Timerwerten, statt in mm messen?

Gruess
Fritzli

SprinterSB
07.11.2005, 10:56
Falls nur die Wurzel die Wurzel des Übels ist, geht so was:
aim > dist
=
aim-START_DIST > d
=
(aim-START_DIST)² > d² AND aim-START_DIST > 0

zuzüglich der anderen Fälle, die auftreten können.

Du führst also alle Vergleiche gegen d auf Vergleiche gegen d² zurück. Evtl muss man etwas Obacht auf die Vorzeichen geben oder aufpassen, ob Lösungen dazukommen/wegfallen können. Wenn du den Wert für d nicht explizit brauchst, sollte es reichen, d² zu kennen, was ja der Fall ist.

Felix G
07.11.2005, 16:59
Grundsätzlich sollte man in einer ISR wirklich nur die notwendigsten Berechnungen durchführen.
(Funktionen wie sqrt() o.ä. haben dort nichts zu suchen)

Normalerweise geht man vor wie von Fritzli beschrieben.
Man schreibt in der ISR nur die relevanten Daten (Timerstände z.B.) in irgendwelche Variablen, und setzt irgendein Flag.
(damit man in main() sehen kann daß neue Daten da sind die verarbeitet werden müssen)

th
08.11.2005, 07:13
Hallo,

danke fuer die vielen Antworten. Denke damit kann ich dann mein Interrupt in Interrupt sein lassen da es mir zu kompliziert erscheint.


mfg Thomas