Hallo,
so langsam bin ich völlig am verzweifeln, stehe mit dem uC auf
"Kriegsfuss" ;=)
Bevor ich mit was großem weiter mache, muss ich erwst weiter Grundlagen
lernen. Was ein Interrupt ist, was er macht, wer wann die Steuerung
übernimmt ist mir soweit klar. Einzig und allein zur Implementierung
(in C) habe ich eine Frage. Meinetwegen habe ich so etwas:
void main (void)
{
// Schleife die immer läuft
while (1)
{
// Schleife die nur läuft wenn der Interrupt ausgelöst wurde
while (interrupt_ausgeloest)
{
// mach was :=)
pause
Ports lesen
Ports schreiben
usw.
[...]
interrupt_ausgeloest = 0;
}
}
}
void Interruptroutine (void)
{
interrupt_ausgeloest = 1;
}
Was den Interrupt auslöst ist erstmal egal. Was ich letztendlich haben
möchte: wenn der Interrupt ausgelöst wurde, soll im Hauptprogramm eine
"extra-Schleife" abgearbeitet werden und zwar immer (!) vom Beginn ab
an. Obiges macht das ja fast soweit, nur was passiert wenn der Interrupt
2 mal "schnell" hintereinander ausgelöst wird? Soweit ich das
verstehe, passiert da nichts weiter, die while (interrupt_ausgeloest)
Schleife läuft einfach an der alten Stelle weiter (ok, das
Hauptprogramm wird unterbrochen, die Interruptroutine wird abgearbeitet
und das Hauptprogramm wird an der alten (!) Stelle fortgesetzt (also
nicht wie gewünscht von Beginn an)). Sie beginnt also nicht so wie von
mir gewünscht von vorne.
Wie kann ich dieses Problem lösen? Soll die ganze Interrupt-Schleife in
die Interruptroutine (was passiert dann bei 2 "schnellen"
Interrupts?), kann man die while schleife immer von Anfang an beginnen
(wäre mir am liebsten)?
Freue mich über jeden Tipp, Link, Codeschnipsel...
Gruß,
Hans
if (interrupt_ausgeloest == 1) danach gleich die Variable auf 0 setzen und dann mit der Portmanipulation fortfahren. Wenn inzwischen der Interrupt noch einmal auftritt, wird im Hauptprogramm wieder in den Programmteil verzweigt.
Hi... Also wenn der Umgang mit Interrupts unter C wirklich so umständlich und kompliziert sein sollte, dann werde ich wohl für immer bei Assembler bleiben. Da kümmert mich der Int in der Hauptschleife nicht, denn jeder Int hat seine eigene ISR, die beim Aufruf abgearbeitet wird. Und in dieser kann man Flags (Bits in einem dafür reservierten Register) setzen, auf die die Hauptschleife reagieren kann... Bit- & Bytebruch... ...HanneS...
Ich hab das vor geraumer Zeit gelernt: Was bei einem IRQ passieren soll, gehört in den IRQ-Handler, nicht ins Main. Wäre es nicht also sinnvoller, die Schleife direkt im Interrupt-Handler ablaufen zu lassen (womit es dann keine Schleife mehr wäre)? Dann würde sich das Problem mit zwei schnell nacheinander auftretenden IRQ's nicht stellen (SEI vorausgesetzt). Darüber hinaus kann der IRQ-Handler ja noch immer ein Flag setzen, das das Hauptprogramm "wenn es Zeit hat" auswertet.
Hallo,
erst mal danke für die Antworten.
@Elektrolurch:
bist du dir da sicher? Wenn der Interrupt abgearbeitet wurde, kehrt der
uC doch an seine alte Stelle im Programm zurück, also mitten in die if
Schleife und nicht an den Anfang (bzw. sogar noch davor wo die
Bedingugn geprüft wurde), oder irre ich da gewaltig?
@...HanneS...
Keine Angst, das geht in C ja genauso. z.B. folgendes:
SIGNAL (SIG_INTERRUPT0)
{
// int 0 ausgelöst
}
SIGNAL (SIG_OVERFLOW1)
{
// Überlauf 1 ausgelöst
}
SIGNAL (SIG_UART_RECV)
{
// Empfangen
}
usw.
Es interessiert mich einzig und allein dein Satz "...auf die
die Hauptschleife reagieren kann...". Das ist mein "Problem".
@Olaf Stieleke:
Bis jetzt habe ich immer nur gelesen und gelernt, das eine Interrupt
Routine möglichst kurz/schnell fertig sein sollte. "Leider" muss ich
auch ein paar Takte bei der Abarbeitung warten.
Gruß,
Hans
Hi,
Interrupts werden durch bestimmte Ereignisse ausgelöst, z.B.
Timer-Überlauf (passiert, wenn bspw. der 8-Bit-Timer > 255 werden
würde). Auf diese Interrupts kann man reagieren, indem man bestimmte
ISR (Interrupt-Service-Routinen) in sein Programm einbaut, also z.B.
SIGNAL (SIG_OVERFLOW0)
{
}
um mal beim 8-Bit-Timer zu bleiben.
Der Sinn solcher Funktionen liegt nun darin, das gerade laufende
Programm zu unterbrechen (deshalb Interrupt = Unterbrechung), weil eben
was Wichtiges passiert ist und den in der ISR definierten Code
auszuführen. Anschliessend macht das Programm an der Stelle weiter, an
der es unterbrochen wurde.
Ein C-Programm sieht also dann in etwa so aus:
void main (void)
{
// Schleife die immer läuft
for (;;)
{
}
}
SIGNAL (interruptkennung)
{
// mach was :=)
Ports lesen
Ports schreiben
usw.
[...]
}
Pausen (respektive irgendwelche Zählschleifen) sollte man in seinem
Programm möglichst vermeiden. Der Prozessor hat meist genug zu tun, als
sich mit solchen (meist sinnlosen) Dingen aufzuhalten. Dann sind
plötzlich nämlich auch die kleineren unter ihnen ganz schnell. ;o)
Joline
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.