Forum: Mikrocontroller und Digitale Elektronik Interrupt Routine


von Taddus (Gast)


Lesenswert?

Hallo habe in meinem Programmcode folgegende ISR:
1
ISR(INT1_vect)
2
{
3
  if (~PINB & (1<<PB4)) 
4
  {
5
    Eingang=Spieler_1;
6
    a++;
7
  }
8
  switch (Eingang)
9
  {
10
    case Spieler_1:
11
    switch (a)
12
    {
13
      case 1:
14
      PORTA = (PORTA | (1 << PA4)) & ~(1 << PA0);
15
      case 2:
16
      PORTA &= ~(1<<PA4);
17
      PORTC |= (1<<PC1);
18
      case 3:
19
      PORTC &= (1<<PC1);
20
    }
21
    }
22
  } 
23
  }
Wenn diese nun abläuft bei einem Signal am INT1, schaltet er mir zwar 
den PIN im ersten case auf low, allerdings nicht gleichzeitig den 
anderen PIN auf high. Ich komm einfach nicht darauf warum er den anderen 
nicht auf high schaltet.

Habe die anderen Switches der Übersicht halber einmal weg gelassen, wäre 
über Hilfe sehr dankbar!

Grüße
Taddus

: Bearbeitet durch User
von chris (Gast)


Lesenswert?

Taddus schrieb:
> case 1:
>       PORTA = (PORTA | (1 << PA4)) & ~(1 << PA0);
>       case 2:
>       PORTA &= ~(1<<PA4);


PA4 wird auf high gesetzt und anschließend in case 2 wieder auf low 
gesetzt.
Du musst aus den einzelnen case mit einem break; raus, sonst werden alle 
durchgelaufen.

case 1:   // .. mach was
break;

case 2:   //... mach was anderes
break;

von Taddus (Gast)


Lesenswert?

Ohhhhhhhhh man, merci dir.
Vielleicht mal genau denken beim proggen :D

von Taddus (Gast)


Lesenswert?

Hab das mit dem break jetzt eingefügt, allerdings besteht das Problem 
weiterhin :/

von Thomas E. (thomase)


Lesenswert?

Taddus schrieb:
> Hab das mit dem break jetzt eingefügt, allerdings besteht das Problem
> weiterhin :/
Dann zeig deinen ganzen Code.
Wo ist deine Entprellung?

mfg.

: Bearbeitet durch User
von Taddus (Gast)


Lesenswert?

Der komplette Code ist:
1
#include <avr/io.h> 
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
volatile uint8_t a=0;
6
volatile uint8_t b=0;
7
volatile uint8_t c=0;
8
volatile uint8_t d=0;
9
volatile uint8_t Eingang;
10
11
enum {Spieler_1,Spieler_2,Spieler_3,Spieler_4};
12
13
void set_output(void) 
14
{ 
15
  
16
  DDRB = 0x08; 
17
  TCCR0 |= (1<<WGM00)|(1<<WGM01) |(1<<COM01)|(1<<CS00);
18
   
19
   }
20
   
21
ISR(INT1_vect)
22
{
23
  if (~PINB & (1<<PB4)) 
24
  {
25
    Eingang=Spieler_1;
26
    a++;
27
  }
28
  if (~PINB & (1<<PB5))
29
  {
30
     Eingang=Spieler_2;
31
     b++;
32
  }
33
  if (~PINB & (1<<PB6))
34
  {
35
     Eingang=Spieler_3;
36
     c++;
37
  }
38
  if (~PINB & (1<<PB7))
39
  {
40
     Eingang=Spieler_4;
41
     d++;
42
  }
43
  switch (Eingang)
44
  {
45
    case Spieler_1:
46
    switch (a)
47
    {
48
      case 1:
49
      PORTA = (PORTA | (1 << PA4)) & ~(1 << PA0);
50
      break;
51
      case 2:
52
      PORTA &= ~(1<<PA4);
53
      PORTC |= (1<<PC1);
54
      break;
55
      case 3:
56
      PORTC &= (1<<PC1);
57
      break;
58
      default:
59
      break;
60
    }
61
    case Spieler_2:
62
    switch (b)
63
    {
64
      case 1:
65
      PORTA = (PORTA | (1 << PA5)) & ~(1 << PA1);
66
      break;
67
      case 2:
68
      PORTA &= ~(1<<PA5);
69
      PORTC |= (1<<PC1);
70
      break;
71
      case 3:
72
      PORTC &= (1<<PC1);
73
      break;
74
      default:
75
      break;
76
    }
77
    case Spieler_3:
78
    switch (c)
79
    {
80
      case 1:
81
      PORTA = (PORTA | (1 << PA6)) & ~(1 << PA2);
82
      break;
83
      case 2:
84
      PORTA &= ~(1<<PA6);
85
      PORTC |= (1<<PC2);
86
      break;
87
      case 3:
88
      PORTC &= (1<<PC2);
89
      break;
90
      default:
91
      break;
92
    }
93
    case Spieler_4:
94
    switch (d)
95
    {
96
      case 1:
97
      PORTA = (PORTA | (1 << PA7)) & ~(1 << PA3);
98
      break;
99
      case 2:
100
      PORTA &= ~(1<<PA7);
101
      PORTC |= (1<<PC3);
102
      break;
103
      case 3:
104
      PORTC &= (1<<PC3);
105
      break;
106
      default:
107
      break;
108
    }
109
  }
110
  }
111
112
int main(void)
113
 { 
114
   MCUCR |= (1<<ISC10)|(1<<ISC11);
115
   GICR |= (1<<INT1);
116
   DDRB = 0x00;
117
   DDRA = 0xFF;
118
   DDRC = 0x0F;
119
   PORTA = 0x0F;
120
   int max_value=5; 
121
   int value = 0;
122
   int max_value_2=5;
123
   int value_2 = 0;
124
   sei ();
125
126
  while(1) 
127
  { 
128
    value = (rand()%max_value); 
129
    
130
    switch (value) 
131
    { 
132
      
133
    case 1: set_output();
134
    OCR0 = 64; 
135
    break; 
136
    
137
    case 2: set_output(); 
138
    OCR0 = 128;
139
    break; 
140
    
141
    case 3: set_output(); 
142
    OCR0 = 192; 
143
    break; 
144
    
145
    case 4: set_output(); 
146
    OCR0 = 255; 
147
    break;
148
    
149
    default: 
150
    break;
151
     
152
    }
153
     
154
     value_2 = (rand()%max_value_2);
155
     
156
     switch (value_2)
157
     {
158
       case 1:
159
       _delay_ms(1000);
160
       break;
161
       
162
       case 2:
163
       _delay_ms(2000);
164
       break;
165
       
166
       case 3:
167
       _delay_ms(3000);
168
       break;
169
       
170
       case 4:
171
       _delay_ms(4000);
172
       break;
173
       
174
       default:
175
       _delay_ms(2500);
176
       break;
177
     }
178
  }
179
 }
Er schaltet den PIN immer astrein auf low, allerdings den anderen nur 
für einen Wimpernschlag auf high und dann sofort wieder auf low.

: Bearbeitet durch User
von tictactoe (Gast)


Lesenswert?

Jetzt sind da zwar breaks in den inneren switches, aber wo sind die, die 
zu den äußeren switches gehören? ;)

von Taddus (Gast)


Lesenswert?

Alles klar, das müsste dann also so aussehen oder?
1
ISR(INT1_vect)
2
{
3
  if (~PINB & (1<<PB4)) 
4
  {
5
    Eingang=Spieler_1;
6
    a++;
7
  }
8
  if (~PINB & (1<<PB5))
9
  {
10
     Eingang=Spieler_2;
11
     b++;
12
  }
13
  if (~PINB & (1<<PB6))
14
  {
15
     Eingang=Spieler_3;
16
     c++;
17
  }
18
  if (~PINB & (1<<PB7))
19
  {
20
     Eingang=Spieler_4;
21
     d++;
22
  }
23
  switch (Eingang)
24
  {
25
    case Spieler_1:
26
    switch (a)
27
    {
28
      case 1:
29
      PORTA = (PORTA | (1 << PA4)) & ~(1 << PA0);
30
      break;
31
      case 2:
32
      PORTA &= ~(1<<PA4);
33
      PORTC |= (1<<PC7);
34
      break;
35
      case 3:
36
      PORTC &= (1<<PC7);
37
      break;
38
      default:
39
      break;
40
    }
41
    break;
42
    case Spieler_2:
43
    switch (b)
44
    {
45
      case 1:
46
      PORTA = (PORTA | (1 << PA5)) & ~(1 << PA1);
47
      break;
48
      case 2:
49
      PORTA &= ~(1<<PA5);
50
      PORTC |= (1<<PC6);
51
      break;
52
      case 3:
53
      PORTC &= (1<<PC6);
54
      break;
55
      default:
56
      break;
57
    }
58
    break;
59
    case Spieler_3:
60
    switch (c)
61
    {
62
      case 1:
63
      PORTA = (PORTA | (1 << PA6)) & ~(1 << PA2);
64
      break;
65
      case 2:
66
      PORTA &= ~(1<<PA6);
67
      PORTC |= (1<<PC5);
68
      break;
69
      case 3:
70
      PORTC &= (1<<PC5);
71
      break;
72
      default:
73
      break;
74
    }
75
    break;
76
    case Spieler_4:
77
    switch (d)
78
    {
79
      case 1:
80
      PORTA = (PORTA | (1 << PA7)) & ~(1 << PA3);
81
      break;
82
      case 2:
83
      PORTA &= ~(1<<PA7);
84
      PORTC |= (1<<PC4);
85
      break;
86
      case 3:
87
      PORTC &= (1<<PC4);
88
      break;
89
      default:
90
      break;
91
    }
92
    break;
93
  }
94
  }
Allerdings ändert das mein Problem noch nicht :/

: Bearbeitet durch User
von Thomas E. (thomase)


Lesenswert?

Taddus schrieb:
> Der komplette Code ist:
Na immerhin. Praktischer ist es allerdings, den Code als Datei 
anzuhängen.
Was spendierst du demjenigen, der als erstes errät, um welchen 
Controller es sich handelt?
Wer oder was löst wie, wann und warum INT1 aus?
Was ist auf PB4-PB7? Taster?

mfg.

von Taddus (Gast)


Lesenswert?

Stimmt, werde ich nächstes mal besser anhängen. Sorry!

Es handelt sich um den AtMega 16.
An die Eingänge PB4-7 ist jeweils eine Lichtschranke angeschlossen, die 
auch den externen Interupt ansteuern über ein Logik IC. Heisst also 
sobald der Interrupt auslöst liegt an einem Eingang low an, der Rest ist 
high. So soll über die If Abfrage geklärt werden welche Lichtschranke 
den Interrupt ausgelöst hat.

Grüße

von Taddus (Gast)


Lesenswert?

Das ganze Programm nochmal mit Kommentaren für bessere Verstädnnis:
1
#include <avr/io.h> 
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
volatile uint8_t a=0;                      // Variablen für den Spielchipstand
6
volatile uint8_t b=0;
7
volatile uint8_t c=0;
8
volatile uint8_t d=0;
9
volatile uint8_t Eingang;                    // Variable welche Lichtschranke ausgelöst hat
10
11
enum {Spieler_1,Spieler_2,Spieler_3,Spieler_4};
12
13
void set_output(void)                      // Funktion für die PWM
14
{ 
15
  
16
  DDRB = 0x08;                      // PB3 auf Ausgang
17
  TCCR0 |= (1<<WGM00)|(1<<WGM01) |(1<<COM01)|(1<<CS00);  // Timer Einstellungen
18
   
19
   }
20
   
21
ISR(INT1_vect)                        // Interrupt Routine
22
23
  if (~PINB & (1<<PB4))                  // Abfrage Lichtschranke 1
24
  {
25
    Eingang=Spieler_1;
26
    a++;                        // Chipstand aktualisieren
27
  }
28
  if (~PINB & (1<<PB5))                  // Abfrage Lichtschranke 2
29
  {
30
     Eingang=Spieler_2;
31
     b++;                      // Chipstand aktualisieren
32
  
33
  if (~PINB & (1<<PB6))                  // Abfrage Lichtschrane 3
34
  {
35
     Eingang=Spieler_3;
36
     c++;                      // Chipstand aktualisieren
37
  }
38
  if (~PINB & (1<<PB7))                  // Abfrage Lichtschranke 4
39
  {
40
     Eingang=Spieler_4;
41
     d++;                      // Aktueller Chipstand
42
  }
43
  switch (Eingang)
44
  {
45
    case Spieler_1:
46
    switch (a)
47
    {
48
      case 1:                    // 1 Spielchip verloren
49
      PORTA = (PORTA | (1 << PA4)) & ~(1 << PA0);      // LED gruen aus und LED gelb an
50
      break;
51
      case 2:                    // 2 Spielchip verloren
52
      PORTA &= ~(1<<PA4);              // LED gelb aus
53
      PORTC |= (1<<PC7);                // LED rot ein
54
      break;
55
      case 3:                    // 3 Spielchip
56
      PORTC &= (1<<PC7);                // LED rot aus
57
      break;
58
      default:
59
      break;
60
    }
61
    break;
62
    case Spieler_2:
63
    switch (b)
64
    {
65
      case 1:                    // 1 Spielchip verloren
66
      PORTA = (PORTA | (1 << PA5)) & ~(1 << PA1);      // LED gruen aus und LED gelb an
67
      break;
68
      case 2:                    // 2 Spielchip verloren
69
      PORTA &= ~(1<<PA5);              // LED gelb aus
70
      PORTC |= (1<<PC6);                // LED rot ein
71
      break;
72
      case 3:                    // 3 Spielchip verloren
73
      PORTC &= (1<<PC6);                // LED rot aus
74
      break;
75
      default:
76
      break;
77
    }
78
    break;
79
    case Spieler_3:
80
    switch (c)
81
    {
82
      case 1:                           // 1 Spielchip verloren
83
      PORTA = (PORTA | (1 << PA6)) & ~(1 << PA2);      // LED gruen aus und LED gelb ein
84
      break;
85
      case 2:                    // 2 Spielchip verloren
86
      PORTA &= ~(1<<PA6);              // LED gelb aus
87
      PORTC |= (1<<PC5);                // LED rot ein
88
      break;
89
      case 3:                    // 3 Spielchip verloren
90
      PORTC &= (1<<PC5);                // LED rot aus
91
      break;    
92
      default:
93
      break;
94
    }
95
    break;
96
    case Spieler_4:                
97
    switch (d)
98
    {
99
      case 1:                    // 1 Spielchip verloren
100
      PORTA = (PORTA | (1 << PA7)) & ~(1 << PA3);      // LED gruen aus und LED gelb ein
101
      break;
102
      case 2:                    // 2 Spielchip verloren
103
      PORTA &= ~(1<<PA7);              // LED gelb aus
104
      PORTC |= (1<<PC4);                // LED rot ein
105
      break;
106
      case 3:                    // 3 Spielchip verloren
107
      PORTC &= (1<<PC4);                // LED rot aus
108
      break;
109
      default:
110
      break;
111
    }
112
    break;
113
  }
114
  }
115
116
int main(void)                        // Hauptprogramm
117
 { 
118
   MCUCR |= (1<<ISC10)|(1<<ISC11);              // Steigende Flanke an INT1 erzeugt Interrupt
119
   GICR |= (1<<INT1);                    // INT 1 erlaube Interrupt Request
120
   DDRB = 0x00;                      // PortB auf Eingang
121
   DDRA = 0xFF;                      // PortA auf Ausgang
122
   DDRC = 0xF0;                      // PC4-PC7 auf Ausgang
123
   PORTA = 0x0F;                      // PA0-PA3 auf "high"
124
   PORTC = 0x00;                      // PortC auf "low"
125
   int max_value=5;                    // Max. Variable für rand Funktion
126
   int value = 0;                      // Min. Variable für rand Funktion
127
   int max_value_2=5;                    // Max. Variable für rand Funktion
128
   int value_2 = 0;                    // Min. Variable für rand Funktion
129
   sei ();                        // Globale Interruptfreigabe
130
131
  while(1)                        // Hauptschleife
132
  { 
133
    value = (rand()%max_value);              // Zufallsauswahl für Geschwindigkeit
134
    
135
    switch (value) 
136
    { 
137
      
138
    case 1: set_output();                        // Geschwindigkeitsstufe 1 (Langsamste)
139
    OCR0 = 64; 
140
    break; 
141
    
142
    case 2: set_output();                  // Geschwindigkeitsstufe 2 
143
    OCR0 = 128;
144
    break; 
145
    
146
    case 3: set_output();                  // Geschwindigkeitsstufe 3
147
    OCR0 = 192; 
148
    break; 
149
    
150
    case 4: set_output();                  // Geschwindigkeitsstufe 4 (Schnellste)
151
    OCR0 = 255; 
152
    break;
153
    
154
    default: 
155
    break;
156
     
157
    }
158
     
159
     value_2 = (rand()%max_value_2);            // Zufallsauswahl für Wartezeit
160
     
161
     switch (value_2)
162
     {
163
       case 1:                    // Wartezeit zum nächsten Wechsel 1 Sekunde
164
       _delay_ms(1000);
165
       break;
166
       
167
       case 2:                    // Wartezeit zum nächsten Wechsel 2 Sekunde
168
       _delay_ms(2000);
169
       break;
170
       
171
       case 3:
172
       _delay_ms(3000);                // Wartezeit zum nächsten Wechsel 3 Sekunde
173
       break;
174
       
175
       case 4:
176
       _delay_ms(4000);                // Wartezeit zum nächsten Wechsel 4 Sekunde
177
       break;
178
       
179
       default:
180
       _delay_ms(2500);                // Wartezeit zum nächsten Wechsel 2,5 Sekunde
181
       break;
182
     }
183
  }
184
 }

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

@ Taddus (Gast)

>Das ganze Programm nochmal mit Kommentaren für bessere Verstädnnis:

Lange Quelltexte gehören in den Anhang, siehe Netiquette.

von Karl H. (kbuchegg)


Lesenswert?

Ich frag mich ja schon die ganze Zeit, was dieser Quatsch mit der 
Variablen 'Eingang' und den vielen switch-cases soll.

Der ganze Code wäre doch viel einfacher, wenn man ihn so schreibt
1
ISR(INT1_vect)                        // Interrupt Routine
2
{
3
  uint8_t input = ~PINB;
4
5
  if ( input & (1<<PB4) )            // Abfrage Lichtschranke 1
6
  {
7
    a++;                              // Chipstand aktualisieren
8
9
    if( a == 1 )
10
      PORTA = (PORTA | (1 << PA4)) & ~(1 << PA0);      // LED gruen aus und  
11
12
    else if( a == 2 )
13
    {
14
      PORTA &= ~(1<<PA4);              // LED gelb aus
15
      PORTC |= (1<<PC7);                // LED rot ein
16
    }
17
18
    else if( a == 3 )
19
      PORTC &= (1<<PC7);                // LED rot aus
20
  }
21
22
  else if ( input & (1<<PB5) )
23
  {
24
     b++;                      // Chipstand aktualisieren
25
26
     ...

da würde schon mal die Hälfte des ganzen Codes wegfallen, was der 
Übersicht mehr als zu gute kommen würde. Und wenn man dann auch noch 
vernünftige Variablennamen benutzen würde und sich für die LED ein paar 
Makros zurecht legt, dann kann man sich auch die 'Kommentierung' sparen.

Zum Fehler:
Ich werd immer noch nicht schlau, was das hier ...
> Wenn diese nun abläuft bei einem Signal am INT1, schaltet er
> mir zwar den PIN im ersten case auf low, allerdings nicht
> gleichzeitig den anderen PIN auf high. Ich komm einfach nicht
> darauf warum er den anderen nicht auf high schaltet.
... bedeuten soll.
Wer ist 'der Pin'? Und was ist 'der andere Pin'?

: Bearbeitet durch User
von Thomas E. (thomase)


Lesenswert?

Taddus schrieb:
> Es handelt sich um den AtMega 16.
> An die Eingänge PB4-7 ist jeweils eine Lichtschranke angeschlossen, die
> auch den externen Interupt ansteuern über ein Logik IC. Heisst also
> sobald der Interrupt auslöst liegt an einem Eingang low an, der Rest ist
> high.
Ist zwar von hinten durch die Brust ins Auge. Aber egal.
> So soll über die If Abfrage geklärt werden welche Lichtschranke
> den Interrupt ausgelöst hat.
Prellen sollte dann ja nicht das Problem sein.

An den Fehler musst du dich Schritt für Schritt rantasten.
Reduziere dein Programm einmal soweit, daß nur eine Lichtschranke ein 
Pin-Paar schaltet.

mfg.

von Taddus (Gast)


Lesenswert?

Karl Heinz schrieb:
> Wer ist 'der Pin'? Und was ist 'der andere Pin'?

PA0 schaltet auf Low
PA4 schaltetet für einen Wimpernschlag auf high und dann sofort wieder 
auf Low

von Karl H. (kbuchegg)


Lesenswert?

Taddus schrieb:
> Karl Heinz schrieb:
>> Wer ist 'der Pin'? Und was ist 'der andere Pin'?
>
> PA0 schaltet auf Low
> PA4 schaltetet für einen Wimpernschlag auf high und dann sofort wieder
> auf Low

Da würde ich dann mal der Hypothese nachgehen, dass da ein zweiter 
Interrupt am selben Portpin reinkommt.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> Da würde ich dann mal der Hypothese nachgehen, dass da ein zweiter
> Interrupt am selben Portpin reinkommt.


rein nur zu Testzwecken

Mit dieser Modifikation
1
ISR(INT1_vect)                        // Interrupt Routine
2
{
3
....
4
  _delay_ms( 500 );
5
}

verlängert sich dann dein 'Wimpernschlag' auf ca. eine halbe Sekunde?
Wenn ja, dann hast du ein Problem mit deinen Lichtschranken. Du kriegst 
mehrere Interrupts pro 'Betätigung'.
Wie werden die eigentlich betätigt?
Denn eine Lichtschranke prellt zwar selber nicht, wenn aber der 
Lichtstrahl mehrmals hintereinander entsprechend unterbrochen wird, dann 
kommt das einem Prellen auch schon sehr nahe.

von Taddus (Gast)


Lesenswert?

Mit diesem delay schaltet er mir die Ports einwandfrei durch, allerdings 
lediglich am STK500 und nicht an meiner eigentlichen Schaltung.
Komischerweise funzt es allerdings auch am STK500 nicht sauber ohne das 
delay.
Aber daraus schliesse ich mal das es jetzt nur noch ein Fehler an meiner 
Schaltung ist und nicht am Programm selbst.

Die Lichtschranke ist unterbrochen wird dann freigegeben ca. eine halbe 
Sekunde bis sie wieder unterbrochen wird.

Grüße

von Oliver S. (oliverso)


Lesenswert?

Taddus schrieb:
> Aber daraus schliesse ich mal das es jetzt nur noch ein Fehler an meiner
> Schaltung ist und nicht am Programm selbst.

Je nun, ein Programm, daß mit der realen Welt nicht klarkommt, mag zwar 
syntaktisch richtig sein, fehlerhaft ist es trotzdem.

Oliver

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.