Variable für PIN-Input und Interrupt richtig definieren

Gast #2264193
Lesenswert?

Variable für PIN-Input und Interrupt richtig definieren

Ich programmiere einen Atmel-Controller in C mit AVRStudio 5.0 und 
möchte gerne vier Werte über Interrupteingänge einlesen, die mit 
Schaltern/Tastern bedient werden. Jeweils zwei Öffner und zwei 
Schließer.
Wenn sich an einem Pin ein Wert ändert (Pin-Change Interrupt) möchte ich 
aber alle vier Werte einlesen um daraus Aktionen abzuleiten.

Meine Vorgehensweise ist zur zeit folgende:
1
#define _S_aus        0x01  //PD0 / SCL/INT0    // Schalter "aus"
2
#define _T_ein        0x02  //PD1 / SDA/INT1    // Taster "ein"
3
#define _NA2          0x04  //PD2 / RXD1/INT2   // NOT-Aus 2
4
#define _NA1          0x08  //PD3 / TXD1/INT3   // NOT-Aus 1
5

6

7
/*globale Variablen */
8

9
volatile uint8_t _ein_aus = (_NA1|_NA2|_T_ein|_S_aus);
10

11
/* Interrupts */
12

13
ISR(INT0_vect)    // Interrupt Vector INT0 
14
{
15
  // keine Aktion erforderlich???
16
}
17

18
int main (void)
19
{
20
if ((_ein_aus <= 0xB) & (_ein_aus >= 4)
21
  {
22
    //Fehlerfall
23
    // Code hier
24
  }
25
  else
26
  {
27
    switch (_ein_aus)
28
    {
29
    case 0:
30
    case 1:
31
    case 2:
32
    case 3:
33
      //NOT-AUS FAll
34
    //Code hier
35
    break;
36
    case 0xD:
37
      // etwas ausschalten
38
    break;
39
    case 0xE:
40
      // etwas einschalten
41
    break;
42
    default:
43
      // nicht definiert, keine Aktion
44
    break;
45
      //       
46
    }
47
  }  
48
}

- In der Interrupt - Routine muss ich nichts hineinschreiben, da ich in 
der main nur meine Variablen auswerten möchte und meine Variable 
(_ein_aus) als volatile deklariert ist - richtig?
- Muss ich alle ISRs (INT1...INT3) definieren, wie INT0 oben?
- Ist die globale Variable für diesen Fall richtig definiert? als 
Volatile?
- Ist die globale Variable richtig verknüpft? (_NA1|_NA2|_T_ein|_S_aus) 
?

Natürlich werde ich noch die Interrupt-Register setzen, das fehlt hier 
im Code.
Gast #2264271
Lesenswert?

Das ist mir klar.
Der Interrupt wird ausgelöst, wenn sich ein Signal am entsprechendem 
Eingang ändert (PIN-Change an INT0...INT3)
Die Variable _ein_aus wird automatisch angepasst (geändert) weil Sie ja 
als volatile deklariert wurde.

Soweit so theoretisch...
Gast #2264312
Lesenswert?

Man, ich depp!

Vermutlich muss in die Interrrupt Routine folgendes ergänzt werden:
1
Zustand = 0x0F & (PIND)

Und "Zustand" dann als globale volatile Variable definieren.
die defines brauche ich dann ja prinzipiell nicht mehr.

Also hier mal abgeändert:
1
#define _S_aus        0x01  //PD0 / SCL/INT0    // Schalter "aus"
2
#define _T_ein        0x02  //PD1 / SDA/INT1    // Taster "ein"
3
#define _NA2          0x04  //PD2 / RXD1/INT2   // NOT-Aus 2
4
#define _NA1          0x08  //PD3 / TXD1/INT3   // NOT-Aus 1
5

6

7
/*globale Variablen */
8

9
volatile uint8_t Zustand;
10

11
/* Interrupts */
12

13
ISR(INT0_vect)    // Interrupt Vector INT0 
14
{
15
  Zustand = 0x0F & (PIND);
16
}
17

18
int main (void)
19
{
20
if ((Zustand <= 0xB) & (Zustand >= 4)
21
  {
22
    //Fehlerfall
23
    // Code hier
24
  }
25
  else
26
  {
27
    switch (Zustand)
28
    {
29
    case 0:
30
    case 1:
31
    case 2:
32
    case 3:
33
      //NOT-AUS FAll
34
    //Code hier
35
    break;
36
    case 0xD:
37
      // etwas ausschalten
38
    break;
39
    case 0xE:
40
      // etwas einschalten
41
    break;
42
    default:
43
      // nicht definiert, keine Aktion
44
    break;
45
      //       
46
    }
47
  }  
48
}
Gast #2264350
Lesenswert?

J.-u. G. schrieb:
> INT_vect0 ist der Interruptvektor für den externen Interrupt INT0.
>
> Du benötigst aber den Vektor für den Pinchange-Interrupt von PIND.
> Vermutlich:ISR(PCINT3_vect)


INT_vect0 ist in der Tat der Interruptvector für den Externen Interupt 
INT0 der sich an PIN D0 befindet. In den Registern kann ich einstellen 
wann er ausgelöst wird.
Low Level  Pin change  falling edge  und rising edge.
Gast #2264377
Lesenswert?

J.-u. G. schrieb:
> Basti schrieb:
>> INT_vect0 ist in der Tat der Interruptvector für den Externen Interupt
>> INT0 der sich an PIN D0 befindet. In den Registern kann ich einstellen
>> wann er ausgelöst wird.
>> Low Level  Pin change  falling edge  und rising edge.
>
> Dann wird aber beim Betätigen der Taster PD1, PD2 und PD3 kein Interrupt
> ausgelöst.

Ja klar, wird analog zu INT0 auch bei INT1, INT2 und INT3 gemacht, 
selber Inhalt wie bei INT0
Gast #2264684
Lesenswert?

Was ist an dieser Konbination falsch?
1
[...]
2
#define A-Zustand 2;
3
#define B-Zustand 3;
4
[...]
5
uint16_t Shut_Down (uint8_t Auszustand)
6
{
7
  switch (Auszustand)
8
  {
9
    case 1: // normal
10
      return(60);
11
    case 2: // A-Zustand
12
      return(10);
13
    case 3: // B-Zustand
14
      return(1200);
15
    default: //alles Andere gibt es nicht
16
      return(0);
17
      break;
18
  } 
19
}
20
[...]
21
uint16_t = time_off = 0xFFFF;
22
[...]
23
time_off = Shut_Down(A-Zustand);
24
[...]
Gast #2269228
Lesenswert?

Hallo, ich wollte eine kurze Rückmeldung geben, ich habs gefunden.

J.-u. G. schrieb:
>> uint16_t = time_off = 0xFFFF;
>
> Mach mal des erste Gleichheitszeichen weg.

Im Code ist es weg, war nur ein Schreibfehler hier im Forum.

Der fehler liegt am Semikolon hinter dem define! Das gehört dort 
natürlich nicht hin:
Falsch:
1
#define A-Zustand 2;

Richtig:
1
#define A-Zustand 2

Ich hatte nur im Code geschaut und nicht in den defines, daher ist es 
mir auch erst später aufgefallen.
#2269255
Lesenswert?

Und jetzt überlegst du noch wie dein Compiler wohl

int A;
int Zustand;
int c;

   c = A-Zustand;


von deinem

A-Zustand

auseinanderhalten soll.


Kauf dir doch ein C-Buch und arbeite das erst mal durch. So wie du dir 
das vorstellst, durch Raten, wirst du das nie lernen.

Und das man Taster nicht per Interrut auswertet hat auch einen guten 
Grund. Zum einen kann kein Mensch einen Taster schnell genug drücken und 
loslassen, ohne dass es durch Polling in der Hauptschleife nicht 
registriert werden würde, zum anderen prellen Taster.
Gast #2269305
Lesenswert?

Karl Heinz Buchegger schrieb:
> Und das man Taster nicht per Interrut auswertet hat auch einen guten
> Grund. Zum einen kann kein Mensch einen Taster schnell genug drücken und
> loslassen, ohne dass es durch Polling in der Hauptschleife nicht
> registriert werden würde, zum anderen prellen Taster.

Also reicht es aus, wenn ich die Entprell-Routine von P.Danegger einbaue 
und in der Hauptschleife einmal den Status abfrage?
Dann entfällt die Sache mit Interrupt auf Flankenwechsel?

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