Forum: Mikrocontroller und Digitale Elektronik Interrupt löst nicht aus?


von Christian M. (krusti)


Angehängte Dateien:

Lesenswert?

Hallo,
ich sitze nun schon seit Stunden am externen Interrupt und sehe langsam 
den Wald vor lauter Bäumen nicht.
Mein Interrupt soll einfach nur bei steigender Flanke auslösen, einen 
Wert hoch zählen und dann wie den Rest auch auf meinem Display bzw UART 
ausgeben.
Ich habe das Gefühl der Interrupt löst nicht aus oder ich mache etwas 
grundlegendes bei der weiteren Verarbeitung falsch. Das Signal kommt am 
Pin an. Das habe ich mit dem Oszi gecheckt.

von Johnny B. (johnnyb)


Lesenswert?

initInterrupt() auskommentiert

von Peter II (Gast)


Lesenswert?

wo wird denn initInterrupt aufgerufen?

was soll das darstellen?
1
ISR (INT0_vect);

und cli() und  sei() habe auch nichts in einer ISR zu suchen.

: Bearbeitet durch Moderator
von Christian M. (krusti)


Lesenswert?

Johnny B. schrieb:
> initInterrupt() auskommentiert

Die ist inzwischen leer, deswegen auch auskommentiert. Das findet 
derzeit in der normalen init() statt.

von Johnny B. (johnnyb)


Lesenswert?

Christian M. schrieb:
> Johnny B. schrieb:
>> initInterrupt() auskommentiert
>
> Die ist inzwischen leer, deswegen auch auskommentiert. Das findet
> derzeit in der normalen init() statt.

Na dann bitte den aktuellen Code wieder reinstellen, ist ja kein Quiz 
zum Zeitvertreib hier.

von Einer K. (Gast)


Lesenswert?

Peter II schrieb:
> und cli() und  sei() habe auch nichts in einer ISR zu suchen
Das wird in diesem konkreten Fall richtig sein, ist aber in dieser 
allgemeinen Form/Ansage falsch.


Wobei, ich würde dann, wenn es nötig ist, sicherlich auf die atomic 
Macros zurückgreifen, aber die mache im Grunde ja das gleiche.

von Peter II (Gast)


Lesenswert?

Arduino F. schrieb:
> Das wird in diesem konkreten Fall richtig sein, ist aber in dieser
> allgemeinen Form/Ansage falsch.
ok, gilt für die Atmels ( 8bitter).

> Wobei, ich würde da sicherlich auf die atomic Macros zurückgreifen, aber
> die mache im Grunde ja das gleiche.

auch das mach in einer ISR keine sinn.

von Christian M. (krusti)


Angehängte Dateien:

Lesenswert?

Johnny B. schrieb:
> Christian M. schrieb:
>> Johnny B. schrieb:
>>> initInterrupt() auskommentiert
>>
>> Die ist inzwischen leer, deswegen auch auskommentiert. Das findet
>> derzeit in der normalen init() statt.
>
> Na dann bitte den aktuellen Code wieder reinstellen, ist ja kein Quiz
> zum Zeitvertreib hier.
Gerne auch wenn es keine Änderung am ausgeführten Code gibt.

Peter II schrieb:
> wo wird denn initInterrupt aufgerufen?
>
> was soll das darstellen?
>
>
1
> ISR (INT0_vect);
2
>
Ein Überbleibsel meiner vielen Versuche. Ist entfernt
>
> und cli() und  sei() habe auch nichts in einer ISR zu suchen.
Ebenso entfernt

von Peter II (Gast)


Lesenswert?

initInterrupt ist doch immer noch aus kommentiert.

von Einer K. (Gast)


Lesenswert?

Peter II schrieb:
> auch das mach in einer ISR keine sinn.
Du bist zu absolut.

Macht selten Sinn, da stimme ich zu.
Man muss dann extrem aufpassen, da stimme ich auch zu.

Aber KEINEN Sinn?
Im Sinne von NIE?
Da gibts einen Einspruch!

von Markus F. (mfro)


Lesenswert?

Wenn ich das lese:


Christian M. schrieb:
> einen
> Wert hoch zählen und dann wie den Rest auch auf meinem Display bzw UART
> ausgeben.

und das lese:
1
//Interrupt 0 -> Pin PD2
2
ISR (INT0_vect)  {  
3
  
4
  way = 1;
5
  
6
}

dann scheint mir das Programm beim "hochzählen" nicht allzu weit zu 
kommen, selbst wenn der Interrupt triggert.

von Johnny B. (johnnyb)


Lesenswert?

Peter II schrieb:
> initInterrupt ist doch immer noch aus kommentiert.

So ist es.

von Thomas E. (thomase)


Lesenswert?

Christian M. schrieb:
> ich sitze nun schon seit Stunden am externen Interrupt und sehe langsam
> den Wald vor lauter Bäumen nicht.

Und warum fällst du die Bäume dann nicht?
1
int main(void)
2
{
3
  MCUCR |= ((1<< ISC01)| (1<< ISC00));
4
  GICR |= ((1<<INT0);
5
  sei();
6
7
  while(1)
8
  {
9
  }
10
}
11
12
ISR(INT0_vect)
13
{
14
  //Toggle irgendeinen freien Pin, weil da hängt der Oszi dran.
15
}

Wenn das geht, bist du schon mal nicht zu doof, den Interrupt 
einzuschalten. Vor allen Dingen erhärtet es den Verdacht, daß der Fehler 
ganz woanders liegt.

Arduino F. schrieb:
> Aber KEINEN Sinn?
> Im Sinne von NIE?
> Da gibts einen Einspruch!

Genau: Blödsinn, Unsinn, Schwachsinn,... Jede Menge Sinn.

von neugierig (Gast)


Lesenswert?

Welcher µC wird benutzt?

von Christian M. (krusti)


Lesenswert?

So, das war gestern nicht mehr mein Tag. Geistig war nicht nicht mehr so 
fit (wie man initInterrupt gesehen hat). Also habe ich alles weggelegt 
und gehe heute mit "leerem Kopf" wieder ran.

Zur Info, ich nutze einen Mega16.

Als erstes habe ich den Vorschlag umgesetzt:
Thomas E. schrieb:
> Christian M. schrieb:
> Und warum fällst du die Bäume dann nicht?

Ich habe alles raus geschmissen und folgenden Code geschrieben. Zuerst 
ohne Ausgabe auf dem Display, als das klappte mit dem Display:
1
#include "defines.h"
2
#include "global.h"
3
4
volatile int16_t way = 0;
5
char s[100];
6
7
int main(void)
8
{  
9
  lcd_init();
10
  
11
  DDRB |= (1 << DDB0);
12
  //Interrupt mit Erkennung von steigender Flanke
13
  MCUCR |= ((1<< ISC01)| (1<< ISC00));
14
  //Interrupt aktivieren
15
  GICR |= ((1<<INT0) /*| (1<<INT1)*/);
16
  sei();
17
  
18
    while (1) 
19
    {        
20
      //////////////////////////////////////////////////////////////////////////
21
      //Weg ausgeben
22
      uart_puts("Weg: ");
23
      uart_puts(itoa (way, s, 10));
24
      uart_putc('\0');
25
      lcd_setcursor(3,1);
26
      lcd_string("Weg : ");
27
      lcd_string(s);
28
      
29
      _delay_ms(1000);        
30
  }
31
}
32
33
//////////////////////////////////////////////////////////////////////////
34
//Interrupt 0 -> Pin PD2
35
ISR (INT0_vect)  {  
36
  
37
  way ++;
38
  PORTB ^= (1<<PB0);
39
}
Und siehe da. Es funktioniert. Also doch nicht ganz doof. Jetzt versuche 
ich Schritt für Schritt wieder den Rest einzubinden. Ich habe eine 
Ahnung an was es liegen könnte aber erklären werde ich es mir nicht 
können. Dazu fehlt mir das tiefer gehende Wissen.
Jetzt erst mal sehen wie weit ich komme.

von Peter II (Gast)


Lesenswert?

Christian M. schrieb:
> uart_puts(itoa (way, s, 10));

der zugriff auf way muss bei einer 16bit variabel Atomar sein.
1
int16_t tmp;
2
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
3
   tmp = way;
4
}
5
uart_puts(itoa (tmp , s, 10));

von Christian M. (krusti)


Lesenswert?

Peter II schrieb:
> Christian M. schrieb:
>> uart_puts(itoa (way, s, 10));
>
> der zugriff auf way muss bei einer 16bit variabel Atomar sein.
>
>
1
> int16_t tmp;
2
> ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
3
>    tmp = way;
4
> }
5
> uart_puts(itoa (tmp , s, 10));
6
>

Ok das sind jetzt Regionen über die ich schon was gelesen habe, aber 
mich nicht so gut auskenne.

Muss ich dass dann auch hier vorher machen? Also atomar?
1
tmp8 = convertWay(way);

: Bearbeitet durch User
von Einer K. (Gast)


Lesenswert?

Christian M. schrieb:
> Ok das sind jetzt Regionen über die ich schon was gelesen habe, aber
> mich nicht so gut auskenne.

Gute Gelegenheit da weiter zu machen...!!

Tipp:
Wenn du einmal das "Warum atomar?" verstanden hast, dann ist das "Was 
atomar?" leicht selber zu beantworten.
(vermute ich mal)

von Peter II (Gast)


Lesenswert?

Christian M. schrieb:
> Muss ich dass dann auch hier vorher machen? Also atomar?tmp8 =
> convertWay(way);

vermutlich, aber ich kann nicht wissen wo du das convertWay im Code 
hinschreibt. In dem letzten Quellcode gibt es das noch nicht.

von Christian M. (krusti)


Lesenswert?

Arduino F. schrieb:
> Christian M. schrieb:
>> Ok das sind jetzt Regionen über die ich schon was gelesen habe, aber
>> mich nicht so gut auskenne.
>
> Gute Gelegenheit da weiter zu machen...!!
>
> Tipp:
> Wenn du einmal das "Warum atomar?" verstanden hast, dann ist das "Was
> atomar?" leicht selber zu beantworten.
> (vermute ich mal)

Soweit ich das verstanden habe, wird bei der atomaren Schreibweise (kann 
man das so nennen?) verhindert, dass sich ein Wert aus dem Interrupt 
ändert, während dieser Wert weiter verarbeitet wird. Ganz grob gesagt, 
es ist ähnlich einem cli().
Gerade bei 16bit großen Zahlen, die in zwei 8bit-Paketen verarbeitet 
werden kann es sein, dass dann die einen 8bit (LSB, denke ich oder 
umgekehrt) zum alten Wert gehören während die anderen (MSB)bei einem 
inzwischen erfolgten Interrupt die neuen Werte haben könnten.

von Christian M. (krusti)


Lesenswert?

Peter II schrieb:
> Christian M. schrieb:
>> Muss ich dass dann auch hier vorher machen? Also atomar?tmp8 =
>> convertWay(way);
>
> vermutlich, aber ich kann nicht wissen wo du das convertWay im Code
> hinschreibt. In dem letzten Quellcode gibt es das noch nicht.

Habe hier meinen aktuellen Code. Läuft im groben und ganzen ganz gut. 
Habe die Variable way für einen anderen Wert genommen und die alte way 
in pulse umbenannt.
Jetzt stehe ich nur vor der Aufgabe meine UART- und Displayausgabe aus 
der main () zu bekommen bzw zu vereinfachen. Und das am Ende bei meiner 
Weganzeige die Nachkommastelle richtig angezeigt wird wenn die Zahl 
negativ ist.
1
#include "defines.h"
2
#include "global.h"
3
4
int main(void)
5
{  
6
  init();
7
  initADC();
8
  initUART();
9
  lcd_init();
10
  initInterrupt();
11
    /* Replace with your application code */
12
  
13
  char s[100];
14
  char t[100];
15
  uart_puts( "Test" );
16
  uart_putc('\0');
17
  
18
  uint8_t tmp8 = 0;
19
  int16_t tmp16 = 0;
20
  uint16_t adcValueOld = 0;
21
  
22
  sei();
23
  
24
    while (1) 
25
    {  
26
    adcValue = ADC_Read(ADC_CHANNEL);
27
    pressureValue = convertADC(adcValue);
28
    way = convertWay(pulse);
29
    
30
    
31
    if (adcValue != adcValueOld)  {
32
      adcValueOld = adcValue;
33
      //////////////////////////////////////////////////////////////////////////
34
      //ADC-Wert ausgeben
35
      uart_puts("ADC-Wert: ");
36
      uart_puts(utoa (adcValue, s, 10));
37
      uart_putc('\0');
38
          
39
      lcd_setcursor(1,1);
40
      lcd_string("ADC-Wert: ");
41
      lcd_string("      ");
42
      lcd_setcursor(1,11);
43
      lcd_string(s);
44
    
45
      //////////////////////////////////////////////////////////////////////////
46
      //Dezimaler Druckwert
47
      uart_puts("Druck: ");
48
      uart_puts(utoa (pressureValue / 10, s, 10));
49
      uart_puts(".");
50
      uart_puts(utoa (pressureValue % 10, t, 10));
51
      uart_puts(" bar");
52
      uart_putc('\0');
53
    
54
      lcd_setcursor(2,1);
55
      lcd_string("Druck : ");
56
      lcd_setcursor(2,9);
57
      lcd_string(s);
58
      lcd_string(".");
59
      lcd_string(t);
60
      lcd_string(" bar");
61
      
62
      //////////////////////////////////////////////////////////////////////////
63
      //Impulse ausgeben
64
      uart_puts("Impulse: ");
65
      uart_puts(itoa (pulse, s, 10));
66
      uart_putc('\0');
67
      
68
      lcd_setcursor(3,1);
69
      lcd_string("Impulse : ");
70
      lcd_string("          ");
71
      lcd_setcursor(3,11);
72
      lcd_string(s);
73
      
74
      //////////////////////////////////////////////////////////////////////////
75
      //Weg ausgeben
76
      uart_puts("Weg: ");
77
      uart_puts(itoa (way / 10, s, 10));
78
      uart_puts(".");
79
      uart_puts(utoa (way % 10, t, 10));
80
      uart_puts(" mm");
81
      uart_putc('\0');
82
      
83
      lcd_setcursor(4,1);
84
      lcd_string("Weg : ");
85
      lcd_string("          ");
86
      lcd_setcursor(4,7);
87
      lcd_string(s);
88
      lcd_string(".");
89
      lcd_string(t);
90
      lcd_string(" mm");
91
      uart_putc('\0');
92
      
93
      _delay_ms(1000);        
94
    }
95
  }
96
}
97
98
//////////////////////////////////////////////////////////////////////////
99
//Interrupt 0 -> Pin PD2
100
ISR (INT0_vect)  {  
101
  
102
  if (PIND & (1<<SENSOR1B))  {
103
    pulse ++;
104
  }
105
  if (!(PIND & (1<< SENSOR1B))) {
106
    pulse --;
107
  }
108
  
109
  PORTB ^= (1<<PB0);  //Für Testzwecke drin
110
}

von Peter II (Gast)


Lesenswert?

Christian M. schrieb:
> if (PIND & (1<<SENSOR1B))  {
>     pulse ++;
>   }
>   if (!(PIND & (1<< SENSOR1B))) {
>     pulse --;
>   }

das sieht doch stark nach einen Drehgeber aus, wenn ja ist es so nicht 
zu empfehlen.

https://www.mikrocontroller.net/articles/Drehgeber

von Christian M. (krusti)


Lesenswert?

Peter II schrieb:
> Christian M. schrieb:
>> if (PIND & (1<<SENSOR1B))  {
>>     pulse ++;
>>   }
>>   if (!(PIND & (1<< SENSOR1B))) {
>>     pulse --;
>>   }
>
> das sieht doch stark nach einen Drehgeber aus, wenn ja ist es so nicht
> zu empfehlen.
>
> https://www.mikrocontroller.net/articles/Drehgeber

Du meinst wegen dem Prellen? Ich habe hier einen bzw. später zwei 
Glasmaßstäbe, das sollte, falls du das prellen meinst, keine Rolle 
spielen.

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.