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.
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.
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
> 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?
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
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?
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
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
Heimo G. schrieb: > Kannst u mir hier ein Codebeispiel geben? > Z.B. mit 2 Interrupts? Selber link, weiter oben. Oliver
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); |
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.