Forum: Mikrocontroller und Digitale Elektronik Nach Interrupt kein Sprung zurück nach while(1)


von Juerg F. (juerg_f)


Lesenswert?

Stehe bei meinem "Versuchs-Code" wieder mal auf dem Schlauch. Immer wenn 
ein Ext. Interrupt abgearbeitet wurde, springt mir der Code wieder zu 
main Schleife. Aber warum? Warum nicht zurück zu while(1) ??

Achtung: reiner Testcode ohne praktischem Sinn! Und der Code wird leider 
in html fast unleserlich nach dem Kopieren - keine Ahnung wie man sowas 
besser posten kann.
1
# define F_CPU 16000000UL
2
3
#include <avr/io.h>
4
#include <stdlib.h>
5
#include <util/delay.h>
6
#include <avr/interrupt.h>
7
#include "lcd-routines.h"
8
9
volatile int zahl;
10
11
int main(void)
12
{
13
  lcd_init();
14
  lcd_string("hallo");
15
  _delay_ms(10);
16
    
17
  int a = 235;
18
  lcd_dezimal(a);
19
  
20
  //Rotary Initialisieren:
21
22
  DDRD &=~ (1 << DDRD2);
23
  DDRD &=~ (1 << DDRD3);        
24
  PORTD |= (1 << PORTD2)|(1 << PORTD3);
25
26
  EIMSK |= (1<<INT0)|(1<<INT1);
27
  EICRA |= (1<<ISC01)|(1<<ISC11)|(1<<ISC10); 
28
  
29
  sei();
30
  
31
  
32
  while(1) 
33
    {
34
    lcd_home();
35
    lcd_dezimal(zahl);
36
    _delay_ms(5);
37
    }
38
  return 0;
39
}
40
41
ISR(INT0_vect ) 
42
{ 
43
  if(!(PIND, PIND3)) 
44
  { 
45
    zahl++;
46
  } 
47
  else 
48
  { 
49
    zahl--; 
50
  } 
51
}

von leo (Gast)


Lesenswert?

Juerg F. schrieb:
> if(!(PIND, PIND3))

Was willst du damit erreichen?

leo

von Teo D. (teoderix)


Lesenswert?

Juerg F. schrieb:
> Rotary Initialisieren:

Prellen!
Die ISR wird so oft aufgerufen, das es zu einem Stack-Überlauf führt -> 
Reset!?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Juerg F. schrieb:
> Und der Code wird leider in html fast unleserlich nach dem Kopieren -
> keine Ahnung wie man sowas besser posten kann.
Lies die kurze Bedienungsanleitung, die über jeder Texteingabebox 
steht und so beginnt:
1
Antwort schreiben
2
Wichtige Regeln - erst lesen, dann posten!
Spätestens bei den [c] Tags sollte der Groschen fallen...

leo schrieb:
> Juerg F. schrieb:
>> if(!(PIND, PIND3))
> Was willst du damit erreichen?
Und welche Warnung bringt der Compiler zu dieser Zeile?

von Juerg F. (juerg_f)


Lesenswert?

Werde es lesen...

Der Code bringt noch nicht viel. Beim debugging sehe ich das der Code in 
der while schleife landet. Wenn ich einen Interrupt auslöse gehts in die 
Interrupt Routine aber von da nicht zurück in die while Schleife sondern 
wieder zurück nach main...

Aber danke für den Hinweis zum Stack Überlauf - muss ich morgen mal 
genauer anschauen!

Danke euch ;-)

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


Lesenswert?

Juerg F. schrieb:
> Immer wenn
> ein Ext. Interrupt abgearbeitet wurde, springt mir der Code wieder zu
> main Schleife.

Es gibt keine "main Schleife". Was immer du damit meinst. Was es gibt, 
ist die main() Funktion. Du erkennst den Unterschied?

> Aber warum? Warum nicht zurück zu while(1) ??

Wenn ich raten müßte, würde ich sagen daß du einen Interrupt auslöst, 
für den keine ISR installiert ist. Der avr-gcc erzeugt für alle 
Interrupts, denen du selber keine ISR zugewiesen hast, einen Sprung zum 
RESET Vektor. Sprich: dein Programm wird von vorn ausgeführt. Von weitem 
sieht das so aus, als würde main() aufgerufen.

von Juerg F. (juerg_f)


Lesenswert?

Ach ja; wird momentan nur der else Teil in der if Verzweigung ausgeführt 
- auch daran muss ich noch arbeiten. Dies wird aber aber einfacher zu 
lösen sein. Habe mich nur nicht darauf konzentriert in diesem Beispiel.

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


Lesenswert?

Axel S. schrieb:
> Wenn ich raten müßte, würde ich sagen daß du einen Interrupt auslöst,
> für den keine ISR installiert ist.

Und guckstu:
1
> EIMSK |= (1<<INT0)|(1<<INT1);

Du aktivierst INT0 und INT1, hast aber nur für INT0 eine ISR.

von Juerg F. (juerg_f)


Lesenswert?

Axel S. schrieb:
> Juerg F. schrieb:
>> Immer wenn
>> ein Ext. Interrupt abgearbeitet wurde, springt mir der Code wieder zu
>> main Schleife.
>
> Es gibt keine "main Schleife". Was immer du damit meinst. Was es gibt,
> ist die main() Funktion. Du erkennst den Unterschied?
>
>> Aber warum? Warum nicht zurück zu while(1) ??
>
> Wenn ich raten müßte, würde ich sagen daß du einen Interrupt auslöst,
> für den keine ISR installiert ist. Der avr-gcc erzeugt für alle
> Interrupts, denen du selber keine ISR zugewiesen hast, einen Sprung zum
> RESET Vektor. Sprich: dein Programm wird von vorn ausgeführt. Von weitem
> sieht das so aus, als würde main() aufgerufen.

Ach so! Das tönt für mich grad am plausiebelsten aber das dann ein reset 
ausgelöst wird, wusste ich nicht. Das würde auch einiges erklären wenn 
ich zum Versuchsaufbau zurück blicke.

Also da werde ich morgen zuerst reinhacken. Vielen Dank für diese Info!

von Juerg F. (juerg_f)


Lesenswert?

Axel S. schrieb:
> Axel S. schrieb:
>> Wenn ich raten müßte, würde ich sagen daß du einen Interrupt auslöst,
>> für den keine ISR installiert ist.
>
> Und guckstu:
>
>
1
>> EIMSK |= (1<<INT0)|(1<<INT1);
2
>
>
> Du aktivierst INT0 und INT1, hast aber nur für INT0 eine ISR.

Ja weiss ich - habe den zweiten ISR nicht mit im Code untergebracht. Wie 
gesagt, geht mir NUR um diesen Rücksprung.

von Juerg F. (juerg_f)


Lesenswert?

Juerg F. schrieb:
> Axel S. schrieb:
>> Axel S. schrieb:
>>> Wenn ich raten müßte, würde ich sagen daß du einen Interrupt auslöst,
>>> für den keine ISR installiert ist.
>>
>> Und guckstu:
>>
>>
1
>>> EIMSK |= (1<<INT0)|(1<<INT1);
2
>>
>>
>> Du aktivierst INT0 und INT1, hast aber nur für INT0 eine ISR.
>
> Ja weiss ich - habe den zweiten ISR nicht mit im Code untergebracht. Wie
> gesagt, geht mir NUR um diesen Rücksprung.

Sorry, jetzt schnall ich es!! Hat grad klick gemacht in meiner Birne! 
Alles klar :-)

von MaWin (Gast)


Lesenswert?

Juerg F. schrieb:
> //Rotary Initialisieren:
>   EICRA |= (1<<ISC01)|(1<<ISC11)|(1<<ISC10);

Wie kommt man auf die irrwitzige Idee, einen Incrementalencoder per 
Flankenwechselinterrupts erkennen zu wollen ? Wenn das keine per 
Hardware entprellten Signale sind, übersieht man welche und zählt 
falsch.

Nie Grundlagen gelesen ?

http://www.dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Juerg F. schrieb:
> Ach ja; wird momentan nur der else Teil in der if Verzweigung ausgeführt
> - auch daran muss ich noch arbeiten.
Lies den zweiten Post des Threads und denk ausführlich darüber nach.

Das was du da hast, ist ein Komma-Operator. Und sei sicher: das willst 
du nicht. Denn im Falle von (PIND, PIND3) wird zuerst PIND ausgewertet, 
dann das Ergebnis dieser Auswertung verworfen, danach wird PIND3 
ausgewertet und weil das die letzte "Anweisung" in der Komma-Liste ist, 
wird der Wert des define von PIN3, also die Zahl 3 zurückgegeben. Also 
steht dort kurz&knackig
if(!(3))

Und !(3) ist nie der Fall, deshalb wird immer die else der Abfrage 
ausgeführt.

von Juerg F. (juerg_f)


Lesenswert?

Besser wäre vermutlich:

if (!(PIND & (1<<PIND3))

Den Encoder habe ich natürlich entprellt. Aber die Qudratur des Encoders 
scheint auch logisch. Auch dort möchte ich mich noch rein hängen.

Ich bedanke mich bei euch für die sinnvollen Inputs!

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.