Pin-Change-Interrupt/ATmega328p

Gast #4766175
Lesenswert?

Hallo, Ich habe folgendes Problem: Ich habe eine ATmega328p und habe an 
den PINS PINB0,PINB1,PIND6,PIND7 jeweils einen Taster gegen Masse 
hängen.Wenn ich jetzt einen der Taster betätige, soll eine LED leuchten. 
Wenn ich ihn ein zweites mal betätige, soll die LED wieder ausgehen. (Es 
ist übrigens immer die gleiche LED (1 Stück) zu testzwecken).
Wenn ich die Taster von PINB0 oder PINB1 drücke, dann funktioniert alles 
klaglos. Wenn ich allerdings die Taster von PIND6 oder PIND7 drücke, 
fängt meine LED nicht zu leuchten an. Wenn Sie aber, bevor ich einen der 
2 Taster von PORTD drücke, bereits eingeschalten ist, dann geht sie aus. 
Aber wie gesagt, ich kann sie nicht einschalten.
Hier ist mal mein Code...
Danke vielmals schon im Voraus,
1
#define F_CPU 8000000UL
2
#include <avr/io.h>
3
#include <util/delay.h>
4
#include <avr/interrupt.h>
5
 
6
 
7
 
8
void init_PinChangeInterrupts(void);
9
 
10
bool t1_pressed = false;
11
bool t2_pressed = false;
12
bool t3_pressed = false;
13
bool t4_pressed = false;
14
 
15
 
16
int main(void)
17
{
18
DDRD = 0b00100000;                                        //PIND5 = Ausgang für LED, PIND6 und PIND7 sind 2 Taster-Eingänge
19
DDRB = 0b00000000;                                        //PINB0 und PINB1 sind zwei weitere Taster-Eingänge
20
 
21
PORTB = (1<<PINB0) | (1<<PINB1);                        //Hier werden die PULLUPS aktiviert
22
PORTD = (1<<PIND6) | (1<<PIND7);                        //Hier werden die PULLUPS aktiviert
23
 
24
init_PinChangeInterrupts();                                //Hier werden die Interrupts initialisiert          
25
sei();                                                    //Aktivieren der Interrupts
26
                                                       
27
while (1);
28
}
29
 
30
 
31
ISR(PCINT0_vect)
32
{  
33
    if (!(PIND & (1<<PIND7)))                //Taster von PIND7 wurde gedrückt
34
    {
35
        if (t1_pressed == false)            //Wenn die LED zuvor ausgeschalten war
36
            {  
37
                PORTD |= (1<<PIND5);
38
                t1_pressed = true;
39
                _delay_ms(100);
40
            }
41
        else if (t1_pressed == true)        //Wenn die LED zuvor eingeschalten war
42
            {
43
                PORTD &= ~(1<<PIND5);
44
                t1_pressed = false;
45
                _delay_ms(100);
46
            }
47
    }
48
 
49
    if (!(PIND & (1<<PIND6)))                //Taster von PIND6 wurde gedrückt
50
    {
51
        if (t2_pressed == false)            //Wenn die LED zuvor ausgeschalten war
52
            {
53
                PORTD |= (1<<PIND5);
54
                t2_pressed = true;
55
                _delay_ms(100);
56
            }
57
        else if (t2_pressed == true)        //Wenn die LED zuvor eingeschalten war
58
            {
59
                PORTD &= ~(1<<PIND5);
60
                t2_pressed = false;
61
                _delay_ms(100);
62
            }
63
    }
64
 
65
    if (!(PINB & (1<<PINB0)))                //Taster von PIND6 wurde gedrückt
66
    {
67
        if (t3_pressed == false)            //Wenn die LED zuvor ausgeschalten war
68
            {
69
                PORTD |= (1<<PIND5);
70
                t3_pressed = true;
71
                _delay_ms(100);
72
            }
73
        else if (t3_pressed == true)        //Wenn die LED zuvor eingeschalten war
74
            {
75
                PORTD &= ~(1<<PIND5);
76
                t3_pressed = false;
77
                _delay_ms(100);
78
            }
79
    }
80
 
81
    if (!(PINB & (1<<PINB1)))                //Taster von PINDB1 wurde gedrückt
82
    {
83
        if (t4_pressed == false)            //Wenn die LED zuvor ausgeschalten war
84
            {  
85
                PORTD |= (1<<PIND5);
86
                t4_pressed = true;
87
                _delay_ms(100);
88
            }
89
        else if (t4_pressed == true)        //Wenn die LED zuvor eingeschalten war
90
            {
91
                PORTD &= ~(1<<PIND5);
92
                t4_pressed = false;
93
                _delay_ms(100);
94
            }
95
    }
96
}
97
 
98
void init_PinChangeInterrupts(void)
99
{
100
    PCICR  |= (1<<PCIE2) | (1<<PCIE0);            //Die Pins 23 bis 16 werden als Interrupts hergenommen, als auch die pins 0 bis 7
101
    PCMSK2 |= (1<<PCINT23) | (1<<PCINT22);        //Hier werden die Interrupts für die jeweiligen Pins enabled
102
    PCMSK0 |= (1<<PCINT0) | (1<<PCINT1);        //Hier das gleiche wie obige Zeile
103
}
Gast #4766198
Lesenswert?

Wie (um Himmels willen) kommt man auf die Idee "_delay_ms()" in einer 
ISR zu verwenden? Ist Dir der Sinn und Zweck einer ISR bekannt?

Wenn das Programm nix anderes tut, als ein paar Taster abzufragen, dann 
kannst Du Dir die Interrupts sparen und das gleich per "polling" lösen.
Dann kannst Du auch die delay-Funktion verwenden.

Bei deinem Code würde es mich wundern, wenn es überhaupt tut und der uC 
nicht beim Drücken der "falschen" Taste einen Reset ausführt.
Dir fehlt mindestzens ein ISR(PCINT2_vect) Block mit den entsprrechenden 
Tasten drin. Die 8-Bit AVR haben für jeden PORT[A,B,C,....] einen 
eigenen "Sammel-IRQ" für Pinchange. Daher brauchst Du auch für jeden 
Port eine ISR.

Der Compiler, den ich normalerweise verwende, hat für alle IRQs, für die 
keine ISR definiert wurde eine Dummy-Funktion, die zu einem Reset führt.
Glaub der AVR-GCC macht das ähnlich (hab mit dem schon lange nix mehr 
gemacht).
Gast #4766244
Lesenswert?

Supi, danke Matthias, hat echt geholfen, hab nicht daran gedacht, dass 
jeder Port über eine extra ISR-Routine verfügt...Ps: Das mit dem Delay 
in der ISR hab ich nur zu Testzwecken drinnen, wollte damit eigentlich 
Tasterprellen verhindern.
Danke vielmals, LG
#4766278
Lesenswert?

Felix schrieb:
> Ps: Das mit dem Delay
> in der ISR hab ich nur zu Testzwecken drinnen, wollte damit eigentlich
> Tasterprellen verhindern.

Das einzige was man so testet ist die Widerstandsfägigkeit der Tastatur 
gegen Reinbeissen.

Rule of thumb: Deine ISR's solletn so wenig Zeit verbrauchen wie irgend 
möglich. Denn IN der ISR werden neue IRQs evtl. anders behandelt als in 
der normalen Programmausführung. Und die dabei entstehenden Fehler sind 
schwer zu debuggen.

/regards

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren