Forum: Compiler & IDEs Zusammenfassen von 3 externen Interrupts?


von H. G. (ledi)


Angehängte Dateien:

Lesenswert?

Hallo!

Ich programmiere gerade eine Anwendung, bei der ich eine 
3x4-Tastenmatrix auf wert = 1 bis 12 abfrage.

Im Hauptprogramm stehen die Initialisierungen und die Endlosschleife.

Sobald eine Taste gedrückt wird soll der Prozessor aufwachen, die Taste 
die gedrückt wurde feststellen und dann entsprechend eine Aktion 
ausführen.

Da ich jede Spalte der Tastenmatrix auf einen ext. Interruptpin des 
Prozessors (ATMEL 90PWM316) hänge, möchte ich den Programmteil der 
Abfrage usw. nur einmal verwenden.

Meine Frage:
Geht das? Kann ich die Interrupts vor Beginn der Tastenabfrage 
zusammenfassen, oder muss ich das gleiche Programm in jede einzelne 
Interruptroutine einbinden?

Oder gibt es hier vielleicht generell eine bessere Lösung?

Im Anhang das Struktogramm des Hauptprogrammes sowie der Interrupts.

von Karl H. (kbuchegg)


Lesenswert?

Heimo G. schrieb:

> Sobald eine Taste gedrückt wird soll der Prozessor aufwachen, die Taste
> die gedrückt wurde feststellen und dann entsprechend eine Aktion
> ausführen.
>
> Da ich jede Spalte der Tastenmatrix auf einen ext. Interruptpin des
> Prozessors (ATMEL 90PWM316) hänge, möchte ich den Programmteil der
> Abfrage usw. nur einmal verwenden.

Keine gute Idee.
Tasten wertet man grundsätzlich nicht mittels Interrupt aus, sondern 
indem man die Tasten ein paar mal pollt. Damit wird man dann auch das 
Tastenprellen los.

Wenn der Prozessor durch Tastendruck aufwachen soll, dann hängt man die 
Tasten elektrisch auf einen einzigen INterrupteingang. Kommt dort ein 
Interrupt wacht der Prozessor auf und beginnt damit die Tastatur mittels 
Pollen abzuscannen.

> Meine Frage:
> Geht das? Kann ich die Interrupts vor Beginn der Tastenabfrage
> zusammenfassen, oder muss ich das gleiche Programm in jede einzelne
> Interruptroutine einbinden?

Es steht dir natürlich frei aus einer ISR eine Funktion aufzurufen.
Das kann natürlich aus 3 verschiedenen ISR immer dieselbe Funktion sein.

Allerdings erhebt sich die Frage, warum du dann nicht gleich elektrisch 
dafür sorgst, dass bei jeglichem Tastendruck immer derselbe INterrupt 
ausgelöst wird und daher von Haus aus nur 1 ISR notwendig ist.

von Hauke C. (Gast)


Lesenswert?

Wenn ich mich recht erinner gibts bei manchen anderen µC's von Atmel 
auch die Option "Pin Change Interrupt", der wird dann bei auslösen von 
einem der betroffenen Eingänge ausgelöst. Ansonsten: In den Routinen 
eine Bearbeitungsroutine aufrufen.

Mfg Hauke

von H. G. (ledi)


Lesenswert?

> Wenn der Prozessor durch Tastendruck aufwachen soll, dann hängt man die
> Tasten elektrisch auf einen einzigen INterrupteingang. Kommt dort ein
> Interrupt wacht der Prozessor auf und beginnt damit die Tastatur mittels
> Pollen abzuscannen.

Wie hänge ich die Tasten el. auf einen Interrupt?

Wenn ich z.B. ein Oder-Gatter verwende, kann ich ja die Tasten nicht 
mehr abfragen. Oder?

von Oliver (Gast)


Lesenswert?

Heimo G. schrieb:
> Meine Frage:
> Geht das? Kann ich die Interrupts vor Beginn der Tastenabfrage
> zusammenfassen, oder muss ich das gleiche Programm in jede einzelne
> Interruptroutine einbinden?

Unabhängig davon, ob das für deine Anwendung sinnvoll ist, geht das.

Sofern du avr-gcc benutzt:

http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html#gaa87c0c624b62f40a17539be6946c3e26

Oliver

von H. G. (ledi)


Lesenswert?

Oliver schrieb:
> Heimo G. schrieb:
>> Meine Frage:
>> Geht das? Kann ich die Interrupts vor Beginn der Tastenabfrage
>> zusammenfassen, oder muss ich das gleiche Programm in jede einzelne
>> Interruptroutine einbinden?
>
> Unabhängig davon, ob das für deine Anwendung sinnvoll ist, geht das.
>
> Sofern du avr-gcc benutzt:
>
> 
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html#gaa87c0c624b62f40a17539be6946c3e26
>
> Oliver

Kannst u mir hier ein Codebeispiel geben?
Z.B. mit 2 Interrupts?

von Peter D. (peda)


Lesenswert?

Karl heinz Buchegger schrieb:
> Allerdings erhebt sich die Frage, warum du dann nicht gleich elektrisch
> dafür sorgst, dass bei jeglichem Tastendruck immer derselbe INterrupt
> ausgelöst wird und daher von Haus aus nur 1 ISR notwendig ist.

Wozu unnütz Hardware verschwenden?

Da dieser AVR keinen Pin-Change-Int hat, muß man die 3 externen Ints zum 
Aufwachen nehmen.
Und mit ISR_ALIASOF() kann man mehrere Vektoren auf denselben Handler 
hinbiegen.

Ich würds allerdings so machen, daß nur eine Taste (ON/OFF) zum 
Aufwachen freigegeben ist. Dann kann man nicht versehentlich ne 
Betätigung auslösen.


Peter

von Peter D. (peda)


Lesenswert?

P.S.:

Wenn ich das Bild richtig verstehe, handelt es sich nicht um 
Batteriebetrieb und es muß eine PWM aktiv sein.
D.h. Tiefschlaf ist weder nötig noch möglich.

Damit ist Idle-Mode und Abfrage im Timerinterrupt (~10ms) die einfachste 
und sicherste Lösung.


Peter

von Oliver (Gast)


Lesenswert?

Heimo G. schrieb:
> Kannst u mir hier ein Codebeispiel geben?
> Z.B. mit 2 Interrupts?

Selber link, weiter oben.

Oliver

von H. G. (ledi)


Lesenswert?

Oliver schrieb:
> Heimo G. schrieb:
>> Kannst u mir hier ein Codebeispiel geben?
>> Z.B. mit 2 Interrupts?
>
> Selber link, weiter oben.
>
> Oliver

Danke!

Ich hab das jetzt versucht.
Fehlermeldung erhalte ich keine, aber ich erkenne keinen Unterschied zu 
vorher!

Anbei der C-Code:
1
/****************************************************************
2
* TASTATURMATRIX - Interrupt                  *
3
* Funktion:    Auslösen eines Interrupts (Int.0,1,2) über eine *
4
*        3x4 Tastenmatrix und toggeln einer LED am PORTC *
5
* Portanschlüsse der Tastenmatrix:                *
6
*         Spalten:  PD6, PB2, PB5            *
7
*         Zeilen:    PB4, PB3, PB1, PB0          *
8
* Controller:   ATMEL 90PWM316, Oszillator intern 8MHz      *
9
****************************************************************/
10
11
#include <avr/io.h>
12
#include <util/delay.h>
13
#include <avr/interrupt.h>
14
#define ISR_ALIAS(INT1_vect, INT0_vect)
15
16
int main (void)
17
{
18
  DDRC    =   0x0F;          // PORTC = Ausgang
19
  DDRB   =  0xFF;          // PORTB = Ausgang
20
  PORTB   =  0x00;          // PORTB = low
21
  DDRB   &=   ~((1<<PB2)|(1<<PB5));  // PB2, PB5 = input
22
  PORTB   |=    (1<<PB2)|(1<<PB5);  // PB2, PB5 = pull up
23
  DDRD   &=  ~ (1<<PD6);        // PD6 = input
24
  PORTD   |=    (1<<PD6);        // PD6 = pull up
25
26
  //***** Init Interrupts *****  
27
  EIMSK |=  (1<<INT0) |  (1<<INT1) |  (1<<INT2);    // Enable Int.0-2
28
  EICRA |=  (1<<ISC01) | (1<<ISC11) |(1<<ISC21);  // Set Int.0-2 on falling edge
29
  sei();                        // Enable all Interrupts
30
      
31
  while(1)
32
  {
33
  }
34
}
35
36
ISR(INT2_vect)          // INT2 on PB5
37
{    
38
  PORTC ^=  0x04;           
39
  _delay_ms(500);  
40
  EIFR |=  (1<<INTF2);      // Clear Int.-Flag
41
}
42
43
ISR(INT1_vect)          // INT1 on PB2
44
{
45
  PORTC ^=  0x02;           
46
  _delay_ms(500);  
47
  EIFR |=  (1<<INTF1);      // Clear Int.-Flag  
48
}
49
50
ISR(INT0_vect)          // INT2 on PB5
51
{
52
  PORTC ^=  0x01;           
53
  _delay_ms(500);  
54
  EIFR |=  (1<<INTF0);      // Clear Int.-Flag
55
}
56
57
ISR_ALIAS (INT1_vect, INT0_vect);

von Peter D. (peda)


Lesenswert?

Schmeiß das define raus, das ist falsch!
Und dann:
1
ISR(INT0_vect)
2
{
3
  PORTC ^=  0x01;
4
}
5
6
ISR( INT1_vect, ISR_ALIASOF(INT0_vect));
7
ISR( INT2_vect, ISR_ALIASOF(INT0_vect));


Peter

von H. G. (ledi)


Lesenswert?

Funktioniert PERFEKT!!!

Danke!

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.