Arduino Nano Interrupt deaktivieren

Gast #5366412
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
Gast #5366420
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.
Gast #5366424
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.
Gast #5366443
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.
Gast #5366461
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.
#5366473
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.
Gast #5367663
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) :)
Gast #5368387
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren