Forum: Mikrocontroller und Digitale Elektronik Port einlesen und IF abfrage


von Bernd H. (bernd79)


Lesenswert?

Atmega32, AVR studio.

Würde gerne PortA Port 4-7 als Eingang / 0-3 als Ausgang verwenden.
Mein kleines Testprogramm läuft noch nicht, habe noch Probleme mit der 
Synthax. Der Befehle "PORTA = 1<<PA0;" bzw "PORTA = 0<<PA0;" alleine 
läuft. Nur das "IF" macht wohl Probleme. Möchte wenn PA7 "Low" ist, soll 
PA0 auch low sein bzw umgekehrt.


#include <avr/io.h>

int main (void)
{
DDRA = 0x0F;      // 0-3 Ausgang & 4-7 Eingang
PORTA = 0xF0;    //  4-7 high (soll dann runtergezogen werden)

while(1)
{

  if (PORTA & (1<<PA7)) // geht nicht
// if (PA7 == 1) geht auch nicht

  {PORTA = 1<<PA0;}

  else

  {PORTA = 0<<PA0;}

}

}

von Peter II (Gast)


Lesenswert?

Bernd H. schrieb:
> {PORTA = 1<<PA0;}

hiermit überschreibst du dir die PullUps ( PORTA = 0xF0; )

von Karl H. (kbuchegg)


Lesenswert?

Bernd H. schrieb:

> #include <avr/io.h>
>
> int main (void)
> {
> DDRA = 0x0F;      // 0-3 Ausgang & 4-7 Eingang
> PORTA = 0xF0;    //  4-7 high (soll dann runtergezogen werden)
>
> while(1)
> {
>
>   if (PORTA & (1<<PA7)) // geht nicht


syntaktisch ist das in Ordnung.
Nur:
Du willst das PIN Register auslesen

    if( PINA & ( 1 << PA7 ) )


PORTx    -> Ausgänge
PINx     -> Eingänge

>   {PORTA = 1<<PA0;}

Das ist zwar nicht ganz falsch, aber solange du am Anfang stehst, 
solltest du dir abgewöhnen an einen Port als ganzes rundumschlagmässig 
etwas zuzuweisen. Ein einzelnes  Bit setzen schreibt sich

    PORTA |= ( 1 << PA0 );

>
>   else
>
>   {PORTA = 0<<PA0;}


und da hättest du auch gleich
     PORTA = 0;

schreiben können, denn genau das steht da.
Ein einzelnes Bit löschen geht so

     PORTA &= ~( 1 << PA0 );


AVR-GCC-Tutorial

von praxisfremd (Gast)


Lesenswert?

1
int main (void){
2
DDRA = 0x0F;      // 0-3 Ausgang & 4-7 Eingang
3
PORTA = 0xF0;    //  4-7 high (soll dann runtergezogen werden)
4
5
while(1)
6
{
7
8
  if (PINA & (1<<PA7)){
9
     PORTA |= (1<<PA0);
10
  } else{
11
    PORTA &= ~(1<<PA0);
12
  }
13
14
}
15
}

von Bernd H. (bernd79)


Lesenswert?

Gibt es eigentlich eine kürzere Schreibweise, um die Eingangsbits 
abzufragen als:

if( PINA & (( 1 << PA0 )|( 1 << PA1 )))

Sowas wie ....
if (PINA & (0x2F<<PINA))

Hab da nicht viel Tutorial gefunden

von praxisfremd (Gast)


Lesenswert?

Mit (( 1 << PA0 )|( 1 << PA1 )) erzeugst du dir eigentlich nur ein 
Bitfeld, nämlich 0b00000011. Folglich kannst du statt (( 1 << PA0 )|( 1 
<< PA1 )) z.B. auch 0x03 schreiben.

Auch sollte dir klar sein, dass ( PINA & (( 1 << PA0 )|( 1 << PA1 ))) 
schon true wird, wenn nur einer der beiden Pins high ist. Wenn 
stattdessen beide high sein sollen, müsstest du schreiben(( PINA & ( 1 
<< PA0 )) && (PINA & ( 1 << PA1 )))

Auf Dauer ist das natürlich aufwändig und fehleranfällig. Deswegen würde 
ich mir am Anfang ein paar Sachen definieren und dann damit 
weiterarbeiten. Das kann dann so aussehen.
1
#define DOWNBUTTONPRESSED ((~PINA) &(1<<PA4))
2
#define MIDBUTTONPRESSED ((~PINA) & (1<<PA5))
3
#define UPBUTTONPRESSED ((~PINA) & (1<<PA6))
4
5
//die if Abfragen können dann z.B. so aussehen
6
7
if (MIDBUTTONPRESSED){
8
//
9
}
10
11
if (DOWNBUTTONPRESSED | UPBOTTONPRESSED){
12
//
13
}

Das ist aus meiner Sicht die einfachste und sauberste Lösung.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Bernd H. schrieb:
> Gibt es eigentlich eine kürzere Schreibweise, um die Eingangsbits
> abzufragen als:
>
> if( PINA & (( 1 << PA0 )|( 1 << PA1 )))
>
> Sowas wie ....
> if (PINA & (0x2F<<PINA))
>
> Hab da nicht viel Tutorial gefunden

Dazu wirst du möglicherweise auch nicht so viel im AVR-Tutorial finden, 
denn das ist C-Grundwissen. Da gibts nur eines: Sprache lernen – 
wirklich lernen.

Oder eben in Assembler programmieren, für manche Menschen ist das 
einfacher als C. Musst du für dich selbst rausfinden.

Zu deiner Frage:
1
if( PINA & 0b00000011 )

In Standard-C:
1
if( PINA & 0x03 )

von Karl H. (kbuchegg)


Lesenswert?

Bernd H. schrieb:
> Gibt es eigentlich eine kürzere Schreibweise, um die Eingangsbits
> abzufragen als:
>
> if( PINA & (( 1 << PA0 )|( 1 << PA1 )))
>
> Sowas wie ....
> if (PINA & (0x2F<<PINA))
>
> Hab da nicht viel Tutorial gefunden

Ein weiterer springender Punkt ist, dass das gar nicht so da stehen 
sollte. Denn PA0 bzw. PA1 und auch PINA sollten eigentlich im Code in 
der Form gar nicht vorkommen.

Am PA0 hängt ja irgendwas. zb ein Fenster-Kontakt und an PA1 hängt ja 
auch etwas zb. die Übertemperturwarnung. Beide Eingänge hängen an einem 
Port den man vielleicht als die Sensordaten vom Tresorraum nennen 
könnte.

D.h. im Code sollte da eigentlich stehen
1
   if( TRESOR_SENSORS & ( ( 1 << WINDOW ) | ( 1 << OVERTEMPERATURE ) ) )
und mittels Makros wird die 'Zuordnung' zu den Ports und Pins gemacht
1
#define TRESOR_SONSORS   PINA
2
#define WINDOW           PA0
3
#define OVERTEMPERATURE  PA1
Der unterschied zum obigen ist ganz klar. Während im Original nur von 
PA0 und PA1 die Rede ist und man beim Codelesen ständig wissen muss, was 
denn eigentlich hinter PA0 steckt, ist in der letzten Variante direkt im 
Code ersichtlich, dass hier Fensterkontakt und Übertemperaturwarnung vom 
Trsorraum untersucht werden. Das steht da so direkt im Code. Die 
C-spezifischen Dinge kann man noch ein wenig in die Makros verschieben
1
#define TRESOR_SONSORS   PINA
2
#define WINDOW           (1<<PA0)
3
#define OVERTEMPERATURE  (1<<PA1)
4
5
...
6
7
   if( TRESOR_SENSORS & ( WINDOW | OVERTEMPERATURE ) )

und dann lässt sich die Anweisung schon ganz gut lesen und verstehen, 
bei moderatem Tippaufwand.

Eine Programmzeile schreibt man 1 mal, korrigiert sie vielleicht ein 
paar mal. Aber man liest sie viele viele male während der 
Entwicklungszeit und auch noch danach. D.h. der Tippaufwand zum 
Schreiben ist zu vernachlässigen. Der spielt nicht wirklich die große 
Rolle. Viel wichtiger ist es, dass da etwas rauskommt, was man leicht 
lesen, erfassen und verstehen kann! Darin unterscheiden sich gute 
Programme von schlecht geschriebenen (unter anderem).

von Ralph (Gast)


Lesenswert?

Markus W. schrieb:
> denn das ist C-Grundwissen. Da gibts nur eines: Sprache lernen –
> wirklich lernen.
>
> Oder eben in Assembler programmieren, für manche Menschen ist das
> einfacher als C. Musst du für dich selbst rausfinden.

Also Assembler muss man nicht lernen ?

Bernd H. schrieb:
> if( PINA & (( 1 << PA0 )|( 1 << PA1 )))
>
> Sowas wie ....
> if (PINA & (0x2F<<PINA))
>
> Hab da nicht viel Tutorial gefunden

Les mal das Kapitel zu Bitmanipulation

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

praxisfremd schrieb:
> Auch sollte dir klar sein, dass
> ( PINA & (( 1 << PA0 )|( 1 << PA1 )))
> schon true wird, wenn nur einer der beiden Pins high ist. Wenn
> stattdessen beide high sein sollen, müsstest du schreiben
> ( (PINA & ( 1 << PA0 )) && (PINA & ( 1 << PA1 )) )
Oder auch so:
 ( PINA & (( 1 << PA0 )|( 1 << PA1 ))) == (( 1 << PA0 )|( 1 << PA1 ))
Oder so, dass es jeder sofort kapiert:
 ((PINA&3)==3)

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.