Forum: Mikrocontroller und Digitale Elektronik Taster maskieren


von Jens1993 (Gast)


Lesenswert?

Mal wieder eine unbeliebte Anfängerfrage....
Ich benutze ein STK500.
Unten sind Auszüge eines Programms. Zum einen die Init und zum anderen 
dass eigentliche Programm.
Die LED0 am PORTB soll bei tastendruck leuchten, bei wiederloslassen 
soll sie wieder ausgehen.
Mein Problem liegt bei der "if" Anweisung.

Es wird ja PIND mit (1<<PD0) "verundet". D.h, der taster PD0 wird 
maskiert. Ich verstehe nun nicht, auf was die "if" anweisung "abfragt". 
Seither kenne ich nur if Anweisung, wie z.B.

    if(a = 1)
      {
      }

hier wird ja klar abgefragt, ob a = 1 ist. Aber auf was fragt die if 
Anweisung in meim Programm ab?
Ich glaub, meine frage ist nicht leicht zu verstehen, aber vllt kann mir 
ja jemand helfen.
Danke!

        DDRA = 0xFF;
  DDRB = 0xFF;
  DDRC = 0xFF;
  DDRD = 0xFE;

  PORTA = 0xFF;
  PORTB = 0xFF;
  PORTC = 0xFF;
  PORTD = 0xFF;


while(1)
  {
    if(!(PIND & (1<<PD0)))
    {
      PORTB = ~1;
    }
    else
    {
      PORTB = 0xFF;
    }


  }

  return(0);

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Jens1993 schrieb:

>     if(a = 1)
>       {
>       }
>
> hier wird ja klar abgefragt, ob a = 1 ist.

Nein. Klassischer Programmierfehler.

Rest: Bitmanipulation

von Jens1993 (Gast)


Lesenswert?

ups sorry

meinte natürlich

    if(a == 1)
    {
    }

von Stefan B. (stefan) Benutzerseite


Lesenswert?

>     if(!(PIND & (1<<PD0)))

ist identisch

    if( (PIND & (1<<PD0)) == 0 )

PIND ist ein 8-bittiges SFR special function register bei AVR µCs.
& (1<<PD0) bildet eine Bitmaske für das PD0.te Bit.
Die Bedingung testet also ob das PD0.te Bit in PIND nicht gesetzt ist.

von Ulf R. (roolf)


Lesenswert?

Jens1993 schrieb:

> Aber auf was fragt die if Anweisung in meim Programm ab?

In C ist 0 false und alles andere true, also sind
1
if (FOO)
2
if (FOO != 0)

äquivalent.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

PD0 ist auf 0 definiert (#define)
x sei 0 oder 1

Wenn PIND gleich xxxxxxx0 binär dann ist das Ergebnis der Berechnung 
00000000 binär bzw. 0 dezimal und die if-Bedingung wahr

wenn PIND gleich xxxxxxx1 binär dann ist das Ergebnis der Berechnung 
00000001 binär bzw. 1 dezimal und die if-Bedingung falsch

von Jens1993 (Gast)


Lesenswert?

ok danke erstmal!

dann versuch ich das mal als Bitmuster darzustellen

     if( (PIND & (1<<PD0)) == 0 )

wenn PD0 gedrückt ergibt sich folgendes  Muster

PIND     =     11111110
                  &
(1<<PD0) =     00000001

ergebnis =     00000000

wenn also      ergebnis == 0

dann           PORTB = ~1


so müsste es doch dann aussehen?!?

von Barny (Gast)


Lesenswert?

Ich würde mir außerdem diverse Aktionen zum entprellen der Tasten 
überlegen.
http://www.mikrocontroller.net/articles/Entprellung

Ein kleiner Tipp am Rande:
Ich verwende Bitoperationen wie (PIND & (1<<PD0)) nur beim 
Initialisieren des Prozessors um eine bessere Übersichtlichkeit zu 
haben.

Im Programm selbst verwende ich Deffinitionen der Bitmuster.
Denn wenn einmal nicht optimiert werden sollte, gehen bei jedem 
Durchgang ein Takt für's shiften und einer für's verunden drauf.

Dass steht zum Beispiel in meinen Deffinitionsheader:

Generelle Deffiniton der Bitmuster:
1
//StdDefEx.h
2
#ifndef stddefex_h
3
#define stddefex_h
4
5
#define Bit0    0x01
6
#define Bit1    0x02
7
#define Bit2    0x04
8
#define Bit3    0x08
9
#define Bit4    0x10
10
#define Bit5    0x20
11
#define Bit6    0x40
12
#define Bit7    0x80
13
14
#define Clear_Bit0    0xFE
15
#define Clear_Bit1    0xFD
16
#define Clear_Bit2    0xFB
17
#define Clear_Bit3    0xF7
18
#define Clear_Bit4    0xEF
19
#define Clear_Bit5    0xDF
20
#define Clear_Bit6    0xBF
21
#define Clear_Bit7    0x7F
22
23
#ifndef NULL
24
#define NULL    0x00
25
#endif
26
27
#ifndef TRUE
28
#define TRUE    0x01
29
#endif
30
31
#ifndef FALSE
32
#define FALSE   0x00
33
#endif
34
35
typedef union {
36
        unsigned short us;
37
        struct
38
    {
39
                unsigned char uch_l;
40
                unsigned char uch_h;
41
        };
42
} split_short;
43
#endif /*stddefex_h*/
Und zum Beispiel dass im Projektheader;
1
//Main.h
2
#ifndef main_h
3
#define main_h
4
5
    //////////////////////
6
  //  Port Deffinition // 
7
////////////////////////
8
9
#define DEF_PORT_LED        PORTA
10
11
#define DEF_PIN_LED         Bit0
12
#define DEF_PIN_LED_CLEAR   Clear_Bit0
13
14
    ////////////////////////////////////
15
  //  Deffinition für LED-Steuerung // 
16
/////////////////////////////////////
17
18
#define LEDan   (DEF_PORT_LED &= DEF_PIN_LED_CLEAR) // LED an   -> invertierte logik 
19
#define LEDaus  (DEF_PORT_LED |= DEF_PIN_LED)       // LED aus  -> invertierte logik 
20
#define IsLEDaus    ((DEF_PORT_LED & DEF_PIN_LED)==DEF_PIN_LED) //Überprüfen ob die LED aus ist -> if(IsLEDaus)
21
#define IsLEDan  ((DEF_PORT_LED & DEF_PIN_LED)==0) //Überprüfen ob die LED an ist -> if(IsLEDan)
22
#endif /*main_h*/

Damit kann ich im Projekt über LEDan; und LEDaus; die LED an und aus 
schalten, ohne mich groß um Bitmanipulationen sorgen machen zu müssen.
Außerdem hat man den Vorteil, dass wenn sich etwas an der Hardware 
ändert, die Änderungen_ nur _ein mal_ an _einer Stelle durchgeführt 
werden müssen.
Man muß also nicht gleich den gesammten Quellcode durchsuchen war zu 
Fehler führen kann.
Dass gleiche Prinzip kannst du auch bei der Auswertung der Tasten 
anwenden.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Exaktemente.

[Goldwaageauspackmodus an]
> wenn PD0 gedrückt ergibt sich folgendes  Muster
> PIND     =     11111110

NUR, wenn es ein active-low angeschlossener Taster ist. Was das ist, 
steht im AVR-GCC-Tutorial

Gleich merken: Fragen zu Sourcecode sind im µC-Bereich meist von der 
Schaltung abhängig. Deshalb lieber Schaltplan einmal zu oft an die Frage 
anhängen als einmal zu wenig...
[Goldwaageauspackmodus aus]

von Jens1993 (Gast)


Lesenswert?

Ok, dann wär ein weiteres meiner Rätsel gelöst!
Danke an alle!
Gruß

von Barny (Gast)


Lesenswert?

@ Jens1993

Fast richtig.

~1 ist quasi ein "Wechselschalter"
Wenn Bit0 gerade 0 ist, wird es 1, wenn es gerade 1 ist, wird es 0.

Wenn du gezielt, unabhängig vom aktuellen Zustand schalten willst, 
verwende:
PORTB |= 0x01;
und
PORTB  &= 0xFE;

von Barny (Gast)


Lesenswert?

Ich habe vergessen zu schreiben dass der angefügte Code nur aus 
Codeausschnitten besteht.
Im eigentlichen Projekt sind ein paar Includes und Deffinitonen mehr 
drinnen ;)

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.