Hallo Leute, brauche Hilfe bei der Programmierung. Wie kann man einen Interrupt in der ISR deaktivieren? Habe ein Programm mit zwei ISR`s (INT0 und INT1). In der ersten ISR0 (Start) wird der Timerwert von Timer 1 in eine Variable geschrieben. In der zweiten ISR1 (Stopp) wird wieder der Timerwert von Timer 1 in eine andere Variable geschrieben. Im Loop werden die Timerwerte dann subtrahiert. Wie kann ich jetzt in der ISR0 (Start) den Interrupt, für diese ISR0 und in der ISR1 (Stopp) den Interrupt für diese ISR1, deaktivieren? Habe schon alles Mögliche ausprobiert. Leider hat nichts so wirklich funktioniert. Hoffe jemand kann helfen. Danke! Gruß, bastler
bastler 9. schrieb: > Wie kann ich jetzt in der ISR0 (Start) den Interrupt, für diese ISR0 und > in der ISR1 (Stopp) den Interrupt für diese ISR1, deaktivieren? Indem du die relevanten Timer-Interrupt-Enable-Flags in den zugehörigen Timer-Registern löschst. Steht im Datenblatt. Wenn du "Arduino" machst dann suche bei arduino.cc in der Hilfe nach.
Die ISR0 und ISR1 sind externe Interrupts, an Pin 2 und 3 des Controllers. Also keine Timer Interrupts!
Dabla Leser schrieb: > Wenn du "Arduino" machst dann suche bei arduino.cc in der > Hilfe nach. Da steht leider nicht viel dazu... Die Doku ist nicht AVR fixiert. Aber dennoch ist der andere Teile deiner Antwort goldrichtig! Im Datenblatt des µC steht, wie man die ganzen Interrupts einzeln ein und abschalten kann.
bastler 9. schrieb: > Wie kann man einen Interrupt in der ISR deaktivieren? Wie meinst du das. Normalerweise sind Interrupts in der ISR immer gesperrt, solange du daran nichts änderst.
Bsp.: ISR0 wird ausgelöst und abgearbeitet. Anschließend gehts zurück ins Hauptprogramm. Jetzt kann es in meiner Anwendung passieren, dass ISR0 nochmal ausgelöst wird, bevor der PULS für das Auslösen von ISR1 kommt. Genau das soll aber nicht passieren. Sprich ISR0 soll sofort nach dem abarbeiten deaktiviert werden.
bastler 9. schrieb: > ISR0 wird ausgelöst und abgearbeitet. Anschließend gehts zurück ins > Hauptprogramm. > Jetzt kann es in meiner Anwendung passieren, dass ISR0 nochmal ausgelöst > wird, bevor der PULS für das Auslösen von ISR1 kommt. Du zeigst kein Programm und sagst uns auch nicht ob du Arduino machst oder deine Programmierumgebung deine "eigene" ist, wie soll dir da geholfen werden? Im Datenblatt unter 13.2.2 und 13.2.3 ist das Interrupt Register Handling genau beschrieben. Also hilf dir selbst.
bastler 9. schrieb: > Wie kann man einen Interrupt in der ISR deaktivieren? Genauso wie außerhalb. > Habe ein Programm mit zwei ISR`s (INT0 und INT1). > > In der ersten ISR0 (Start) wird der Timerwert von Timer 1 in eine > Variable geschrieben. In der zweiten ISR1 (Stopp) wird wieder der > Timerwert von Timer 1 in eine andere Variable geschrieben. > > Im Loop werden die Timerwerte dann subtrahiert. Kann man sicher so machen. Viel cleverer wäre es allerdings, wenn man die input capture Funktion des Timers dafür nutzen würde. Nur mal so als Denkanstoß. > Wie kann ich jetzt in der ISR0 (Start) den Interrupt, für diese ISR0 und > in der ISR1 (Stopp) den Interrupt für diese ISR1, deaktivieren? Wenn du gelernt hast, wie du den Interrupt einschaltest, wirst du ja auch wissen, wie du ihn wieder ausschaltest. Es ist vollkommen irrelevant, ob das innerhalb einer ISR oder außerhalb passiert. > Habe schon alles Mögliche ausprobiert. Leider hat nichts so wirklich > funktioniert. Dann hast du es wohl falsch gemacht. Eine detaillierte Antwort willst du wohl gar nicht haben, sonst hättest du gezeigt, was genau du versucht hast.
Hallo, danke für die Antworten und sorry für die unklaren Infos. Habe leider erst vor kurzem mit Arduino angefagen. Programmierumgebung: Arduino IDE Controller: ATmega328/P Mein bisheriges Programm:
1 | volatile int start_value = 0; |
2 | volatile int stop_value = 0; |
3 | volatile int flag = 0; |
4 | volatile int messung = 0; |
5 | |
6 | int dif_value = 0; |
7 | |
8 | |
9 | #define distance 1
|
10 | |
11 | |
12 | void setup() { |
13 | // put your setup code here, to run once:
|
14 | |
15 | pinMode(2,INPUT); |
16 | pinMode(3,INPUT); |
17 | |
18 | attachInterrupt(0, isr_start, RISING); |
19 | attachInterrupt(1, isr_stopp, RISING); |
20 | |
21 | Serial.begin(9600); |
22 | |
23 | TCCR1A = 0; |
24 | TCCR1B = 0; |
25 | TCCR1B |= (1 << CS10); |
26 | TCNT1 = 0; |
27 | |
28 | }
|
29 | |
30 | void loop() { |
31 | // put your main code here, to run repeatedly:
|
32 | |
33 | dif_value = ((stop_value - start_value) * 62.5)/1000000; |
34 | |
35 | if( flag == 1) |
36 | {
|
37 | |
38 | Serial.print ("Messung "); |
39 | Serial.print (messung); |
40 | Serial.print (": "); |
41 | Serial.print (dif_value,2); |
42 | Serial.println (" s"); |
43 | |
44 | flag = 0; |
45 | |
46 | }
|
47 | |
48 | }
|
49 | |
50 | void isr_start () |
51 | {
|
52 | |
53 | TCNT1 = 0; |
54 | start_value = TCNT1; |
55 | |
56 | EIMSK &= ~(1<< INT0); |
57 | |
58 | }
|
59 | |
60 | void isr_stopp () |
61 | {
|
62 | |
63 | stop_value = TCNT1; |
64 | |
65 | flag = 1; |
66 | |
67 | messung ++; |
68 | |
69 | EIMSK &= ~(1<< INT1); |
70 | |
71 | }
|
Bei steigender Flanke an Pin 2 wird ISR0 ausgelöst. Darin wird der Timerwert auf 0 gesetzt und in die start_value Variable geschrieben. Danach soll die ISR0 mit dem Enable Bit (EIMSK &= ~(1<< INT0))gesperrt werden. Bei steigender Flanke an Pin 3 wird ISR1 ausgelöst. Darin wird der aktuelle Timerwert in die stop_value Variable geschrieben. Danach soll die ISR1 mit dem Enable Bit (EIMSK &= ~(1<< INT1))gesperrt werden. Das Deaktivieren funktionert auch soweit, doch leider steht in den beiden start_value und stop_value Variablen dann immer der Wert 0. Löscht man die Enable Befehle funktionert die Messung. Leider fehlt mir aber dann die Sicherheit! In die Input capture Funktion vom Timer1 habe ich mich in den letzten Stunden eingelesen. Habe ich auch soweit mit der Programmierung hin bekommen. Da der Controller aber nur einen Input Capture Pin hat ist diese Funktion dafür auch nicht geeignet. Hoffe jemand kann helfen. Sorry für die evtl. schlechte Programmierung (bin noch am üben) :)
bastler 9. schrieb: > Da der Controller aber nur einen Input Capture Pin hat ist > diese Funktion dafür auch nicht geeignet. Reicht doch... Der Start-input startet den Timer, der Stop-input löst das capture aus.
Habe mich nochmal mit dem Input Capture versucht. Hier der Code:
1 | volatile unsigned int startwert = 0; |
2 | volatile unsigned int stoppwert = 0; |
3 | volatile unsigned int edge = 0; |
4 | volatile unsigned int flag = 0; |
5 | |
6 | |
7 | unsigned int differenz = 0; |
8 | |
9 | |
10 | void setup() { |
11 | // put your setup code here, to run once:
|
12 | |
13 | |
14 | pinMode(8, INPUT); |
15 | |
16 | cli(); // alle Interrupts aus |
17 | |
18 | TCCR1A = 0; // TCCR1A Register auf 0 setzten |
19 | |
20 | //TCCR1B |= (1 << ICNC1); // Rauschunterdrückung
|
21 | TIMSK1 = (1<<ICIE1); // Input Capture Interrupt an |
22 | |
23 | TCCR1B &= ~(1 << ICES1); // Input Capture Edge (fallende Flanke) |
24 | TCCR1B |= (1 << CS10); // Kein Frequenzteilung |
25 | |
26 | TCNT1 = 0; // mit 0 initialisieren |
27 | |
28 | //TIMSK2 &= ~(1<<OCIE2A); // disable Timer2 Interrupt, millis
|
29 | |
30 | sei(); // alle Interrupts an |
31 | |
32 | Serial.begin(9600); |
33 | |
34 | |
35 | }
|
36 | |
37 | void loop() |
38 | {
|
39 | |
40 | if(flag == 1) |
41 | {
|
42 | |
43 | TCCR1B = 0; |
44 | |
45 | Serial.println(startwert); |
46 | Serial.println(stoppwert); |
47 | |
48 | flag = 0; |
49 | |
50 | TIMSK1 = (1<<ICIE1); |
51 | |
52 | }
|
53 | }
|
54 | |
55 | |
56 | ISR(TIMER1_CAPT_vect) |
57 | {
|
58 | TIMSK1 = 0; |
59 | |
60 | edge++; |
61 | |
62 | if( edge == 1) { |
63 | startwert = ICR1; |
64 | TIMSK1 = (1<<ICIE1); |
65 | }
|
66 | if( edge == 2){ |
67 | stoppwert = ICR1; |
68 | edge = 0; |
69 | flag = 1; |
70 | }
|
71 | |
72 | }
|
Leider steht in der startwert und stoppwert Variable immer der gleiche Wert. Komme nicht dahinter warum! Vielleicht kann jemand helfen? Bei der ersten fallenden Flanke springt das Programm doch in die ISR und setzt die Variable edge auf 1. Somit wird die erste if ausgeführt und der Zählerwert in die startwert Variable geschrieben. Bei der zweiten fallenden Flanke springt das Programm wieder in die ISR und setzt edge auf 2. Somit wird die zweite if ausgeführt und der Zählerwert wird in die stoppwert Variable geschrieben. Die zwei Lichtschranken könnte ich dann über ein ODER-Glied an den ICP Pin des Controllers anschließen und somit die Zeit messen. Das zu messende Objekt wird vermutlich schneller als 4ms sein. Somit brauche ich dann auch keinen Überlauf des Zählers beachten oder?
In loop wird Timer1 mit TCCR1B = 0 abgeschaltet - wo wieder ein?
bastler 9. schrieb: > Wie kann man einen Interrupt in der ISR deaktivieren? Mit dem Enable-Bit, welches im Datenblatt in der Registerbeschreibung des jeweiligen Kapitels beschrieben ist. Vor erneuter Freigabe ist es oft angeraten, zuvor das Pending-Bit zu löschen, indem man es setzt.
bastler 9. schrieb: > Programmierumgebung: Arduino IDE > Controller: ATmega328/P attachInterrupt() detachInterrupt()
bastler 9. schrieb: > Sprich ISR0 soll sofort nach dem abarbeiten deaktiviert werden. Was hindert dich daran. Lösche z.B. gleich am Anfang deiner ISR0-Routine das ISR0-Interrupt enable Bit - und Ruhe is.
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.