Forum: Mikrocontroller und Digitale Elektronik Arduino Nano Interrupt deaktivieren


von bastler 9. (Gast)


Lesenswert?

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

von Dabla Leser (Gast)


Lesenswert?

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.

von bastler 9. (Gast)


Lesenswert?

Die ISR0 und ISR1 sind externe Interrupts, an Pin 2 und 3 des 
Controllers.
Also keine Timer Interrupts!

von Einer K. (Gast)


Lesenswert?

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.

von Wolfgang (Gast)


Lesenswert?

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.

von bastler 9. (Gast)


Lesenswert?

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.

von Dabla Leser (Gast)


Lesenswert?

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.

von Axel S. (a-za-z0-9)


Lesenswert?

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.

von bastler 9. (Gast)


Lesenswert?

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) :)

von Schwarzseher (Gast)


Lesenswert?

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.

von bastler 9. (Gast)


Lesenswert?

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?

von S. Landolt (Gast)


Lesenswert?

In loop wird Timer1 mit
TCCR1B = 0
abgeschaltet - wo wieder ein?

von Peter D. (peda)


Lesenswert?

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.

von Georg M. (g_m)


Lesenswert?

bastler 9. schrieb:
> Programmierumgebung: Arduino IDE
> Controller: ATmega328/P

attachInterrupt()
detachInterrupt()

von Wolfgang (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.