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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Christian M. (krusti)


Angehängte Dateien:

Bewertung
-1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
initInterrupt() auskommentiert

von Peter II (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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 Arduino Fanboy D. (ufuf)


Bewertung
0 lesenswert
nicht 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.

: Bearbeitet durch User
von Peter II (Gast)


Bewertung
0 lesenswert
nicht 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:

Bewertung
0 lesenswert
nicht 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)


Bewertung
1 lesenswert
nicht lesenswert
initInterrupt ist doch immer noch aus kommentiert.

von Arduino Fanboy D. (ufuf)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Peter II schrieb:
> initInterrupt ist doch immer noch aus kommentiert.

So ist es.

von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Welcher µC wird benutzt?

von Christian M. (krusti)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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 Arduino Fanboy D. (ufuf)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.