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.
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
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.
mfg robert
Wer glaubt zu wissen, muß wissen, er glaubt.
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
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
}
}
}
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
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.
Disclaimer: none. Sue me.
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)
So viele Treppen und so wenig Zeit!
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
Lesezeichen