Forum: Mikrocontroller und Digitale Elektronik deklaration mit define,wie richtig, so doch nicht oder?


von Matthias H. (maethes26)


Angehängte Dateien:

Lesenswert?

Guten Morgen zusammen,

ich möchte gern meine externe lct_tools.c Datei so ändern, dass ich das 
LCD_Display an beliebige Ports anschließen kann.

Im Augenblick sieht es so aus, dass diese Routine für PORTD programmiert 
ist.
Ein umstecken des Display auf PORTB würde bedeuten die ganze Datei 
umzuschreiben.

Ich habe einen Lösungsansatz. Haltet ihr den für so richtig.
Hier ein kleines Beispielprogramm.


int main(void)
{

  DDRC=0x00; //als eingang setzen
  PORTC=0xff;  // Eingang auf High gesetzt

  DDRD=0xff; //als Ausgang setzen
  PORTD=0xff; //Ausgang auf High setzen  LED leuchtet

#define Eingabeport PINC  //hiermit kann ich an einer Stelle den PORT 
ändern
#define WARTEBIT0 PC0     diese müssen aber jedes Mal auch dennoch 
geändert werden, oder
#define WARTEBIT1 PC1
#define WARTEBIT2 PC2
#define WARTEBIT3 PC3
#define WARTEBIT4 PC4
#define WARTEBIT5 PC5
#define WARTEBIT6 PC6
#define WARTEBIT7 PC7


   while(1)
    {

alter Code, den man nicht flexibel ändern kann

/*  while( (!(PINA & (1<<PA6)))==0 && (!(PINA & (1<<PA7)))==0  && 
(!(PINA & (1<<PA5)))==0  && (!(PINA & (1<<PA4)))==0  && (!(PINA & 
(1<<PA3)))==0 && (!(PINA & (1<<PA2)))==0  && (!(PINA & (1<<PA1)))==0  && 
(!(PINA & (1<<PA0)))==0  );


  _delay_ms(1000);
   PORTD ^= ( 1 << PD6 );
   _delay_ms(1000);

  */

neuer Code, den man relativ flexibel ändern kann

    while( (!(Eingabeport & (1<<WARTEBIT0)))==0 && (!(Eingabeport & 
(1<<WARTEBIT1)))==0 && (!(Eingabeport & (1<<WARTEBIT2)))==0  && 
(!(Eingabeport & (1<<WARTEBIT3)))==0  && (!(Eingabeport & 
(1<<WARTEBIT4)))==0  && (!(Eingabeport & (1<<WARTEBIT5)))==0  && 
(!(Eingabeport & (1<<WARTEBIT6)))==0  && (!(Eingabeport & 
(1<<WARTEBIT7)))==0   );
     _delay_ms(1000);
   PORTD ^= ( 1 << PD6 );
   _delay_ms(1000);

    }
}

Einen schönen Tag wünscht Matthias.

von Julian B. (julinho)


Lesenswert?

Wenn du nur den Port wechseln willst, dann mußt du nur den eingabeport 
per define ändern.

1<<PC0  = 1<<0 = 1<<PD0

von Matthias H. (maethes26)


Lesenswert?

Julian Baugatz schrieb:
> Wenn du nur den Port wechseln willst, dann mußt du nur den eingabeport
> per define ändern.
>
> 1<<PC0  = 1<<0 = 1<<PD0

Hallo Julian,

danke für die Antwort.

achso 1<<PA6    muss ich dann nicht auch jedes Mal ersetzen. sondern ich 
schreibe gleich 1<<6 das steht dann für in diesem Fall PA6


vielen Dank für Deinen Tipp.

Dann kann ich mich jetzt ran machen und die Routine umschreiben.

Einen schönen Tag wünsche ich noch.

von Matthias H. (maethes26)


Lesenswert?

Julian Baugatz schrieb:
> Wenn du nur den Port wechseln willst, dann mußt du nur den eingabeport
> per define ändern.
>
> 1<<PC0  = 1<<0 = 1<<PD0

Hallo,

bei dem folgenden Beispiel habe ich Deinen Tipp umgesetzt und er hat 
funktioniert.
Die PORTrichtung muss ich dennoch jedes Mal umändern, wenn ich einen 
anderen PORT über #define Eingabeport definiere, oder?

DDRB=0x00;  muss ich dann dennoch in z.B. DDRA=0x00 ändern

Viele Grüße,

Matthias.



int main(void)
{
lcd_ini();

#define Eingabeport PINB
DDRB=0x00;    //als Eingang
PORTB=0xff;    // auf high gesetzt

lcd_gotoline(2);lcd_writezahl(result);

  while(1)
  {
  if (!(Eingabeport &(1<<0)))      //Wenn PIN low wird, dann erhöhe um 1 
und gib das Ergebnis aus
  {
  result=result+1;
  lcd_gotoline(2);lcd_writezahl(result);
  }
}

von M2 (Gast)


Lesenswert?

Matthias H. schrieb:
> schreibe gleich 1<<6 das steht dann für in diesem

Das ist doch eine Konstante, dann kannst du doch gleich 0x40 oder 
0b01000000 schreiben. Der Kompiler sollte das aber eh erkennen und genau 
das daraus machen. Warum vergleichst du alle Bits einzeln? Das geht auch 
mit einem 10tel des Codes und übersichtlicher wird es dann auch.

von M2 (Gast)


Lesenswert?

Matthias H. schrieb:
> Eingabeport &(1<<0)

Was soll das (1<<0) den bewirken?

von Matthias H. (maethes26)


Lesenswert?

M2 schrieb:
> Matthias H. schrieb:
>> schreibe gleich 1<<6 das steht dann für in diesem
>
> Das ist doch eine Konstante, dann kannst du doch gleich 0x40 oder
> 0b01000000 schreiben. Der Kompiler sollte das aber eh erkennen und genau
> das daraus machen. Warum vergleichst du alle Bits einzeln? Das geht auch
> mit einem 10tel des Codes und übersichtlicher wird es dann auch.

Hallo,

danke für Deine Hilfe. Ja, ich war mir auhc unsicher, ob es so elegant 
ist.

Leider verstehe ich nicht ganz was Du meinst, nicht das wir gleich 
aneinander vorbei reden.



Was soll das (1<<0) den bewirken?

Prüfung, ob der PIN1 von z.B. PORT B gedrückt wurde. Und da ich alle 
PINs( oder manchmal auch nur bestimmte) prüfen möchte,
frage ich alle so in einer Zeile ab. so wie hier.

 while( (!(Eingabeport & (1<<0)))==0 && (!(Eingabeport & (1<<1)))==0 && 
(!(Eingabeport & (1<<2)))==0  && (!(Eingabeport & (1<<3)))==0  && 
(!(Eingabeport & (1<<4)))==0  && (!(Eingabeport & (1<<5)))==0  && 
(!(Eingabeport & (1<<6)))==0  && (!(Eingabeport & (1<<7)))==0);

das geht bestimmt noch besser, habe aber Deine Ausführungen nicht so 
verstanden
Matthias H. schrieb:
> schreibe gleich 1<<6 das steht dann für in diesem

Das ist doch eine Konstante, dann kannst du doch gleich 0x40 oder
0b01000000 schreiben. Der Kompiler sollte das aber eh erkennen und genau
das daraus machen. Warum vergleichst du alle Bits einzeln? Das geht auch
mit einem 10tel des Codes und übersichtlicher wird es dann auch.

Kannst du das bitte nochmal ..

Viele Grüße,

MAtthias.

von M2 (Gast)


Lesenswert?

Matthias H. schrieb:
> Was soll das (1<<0) den bewirken?
>
> Prüfung, ob der PIN1 von z.B. PORT B gedrückt wurde. Und da ich alle
> PINs( oder manchmal auch nur bestimmte) prüfen möchte,
> frage ich alle so in einer Zeile ab. so wie hier.

Das << bewirkt eine Bitverschiebung also werden bei 1<<0 alle Bit um 
Null stellen nach links geschoben. Somit wird aus 1 (Binär 0b00000001) 
genau 1^(Binär 0b00000001).

Bei 1<<4 werden alle Bits um 4 stellen nach links geschoben so wird aus
0b00000001 eben 0b00010000 und das entspricht Hexadezimal 0x10 oder 
Dezimal 16.

> while( (!(Eingabeport & (1<<0)))==0 && (!(Eingabeport & (1<<1)))==0 &&
>(!(Eingabeport & (1<<2)))==0  && (!(Eingabeport & (1<<3)))==0  &&
>(!(Eingabeport & (1<<4)))==0  && (!(Eingabeport & (1<<5)))==0  &&
>(!(Eingabeport & (1<<6)))==0  && (!(Eingabeport & (1<<7)))==0);

Wenn ich das richtig sehe, willst du hier wissen ob alle Bits vom 
Eingabeport 0 sind. Bei mir sehe das so aus:

while(!Eingabeport)

oder wolltest du wissten ob alle Bits 1 sind dann so

while(Eingabeport == 0b11111111)

von Matthias H. (maethes26)


Lesenswert?

Hallo,

while(!Eingabeport)

oder wolltest du wissten ob alle Bits 1 sind dann so

while(Eingabeport == 0b11111111)

ja das wollte ich beides wissen.

ich habe das dank deines vorherigen Tipps so gelöst.

 while(!(Eingabeport==0xff))

damit ist mir jetzt geholfen.


Viele Grüße und noch einen schönen Tag wünscht,

Matthias.

von M2 (Gast)


Lesenswert?

Nochmal zu deinem Code

>(!(Eingabeport & (1<<2)))==0

Kürzen wir das mal

(!(Eigabeport & 0b00000100))==0

(Eigabeport & 0b00000100)==1

PS: Schau dir auch mal die XOR Verknüpfungen an, damit bann man auch 
schöne Bitvergleich erstellen. Versuche mal raus zu finden was dieser 
Code macht:

while (!(Eigabeport ^ 0b01010100))

von M2 (Gast)


Lesenswert?

Entschuldige meine Tippfehler ;)

von Matthias H. (maethes26)


Lesenswert?

ok, mache ich heute noch.

habe ja auch ein C-Buch Mikrocomputertechnik mit Controllern der Atmel 
AVR RISC-Familie

Da steht auhc einiges drüber drin.

So nebenbei gefragt, ich beschäftige mich ja gerade mit Tastern ein und 
Ausgabe.

Ist es normal, dass sich der Atmega32 am PORTC nicht ganz normal 
verhält?

Wenn ich die Datenrichtung auf high und ausgang setze, dann sind dennoch 
nciht alle auf high,

genauso, wenn ich die auf Eingang setze, alle scheinen nicht zu 
funktionieren.

hier eine konkrete messung

Alle auf low geschaltet, eingang oder Ausgang kann ich jetzt nciht mehr 
sagen
PC2,3 ist auf high
PC4 schwankt,
PC5 ist auf high

Das ist doch merkwürdig. Hast Du eine Ahnung?  Ich habe gehört man kann 
den Atmel konfigurieren (Fuse) und somit die Pins ändern..

Ich kann mich jetzt erst später wieder melden. Würde mich aber dennoch 
über eine Antwort freuen.

Viele Grüße,

Matthias.

von Matthias H. (maethes26)


Lesenswert?

M2 schrieb:
> Entschuldige meine Tippfehler ;)

das ist mir doch egal. Du hilfst mir ja. Musst Du nicht arbeiten? Ich 
habe Urlaub.

von M2 (Gast)


Lesenswert?

Da kann ich dir nicht weiter helfen, bin kein AVRler ;)

von Julian B. (julinho)


Lesenswert?

Könnte sein, dass beim Atmega32 auf PORTC die JTAG-Pins liegen.
Mal über die Fuses den JTAG ausschalten.

von Fridolin (Gast)


Lesenswert?

Eventuell unqualifiziert da ich gerade nur oberflächlich ins Datenblatt 
geschaut habe:
Im Kapitel "Alternate Functions of Port C" des Atmega32 Datenblatts 
steht in Tabelle 29, dass PC7 bis PC4 scheinbar für JTAG genutzt werden, 
wenn die Fuse JTAGEN gesetzt ist. Nachschauen ob das so ist, kannst du 
einfach über das entsprechende Tab in AVR-Studio wenn du dich auf den 
Controller (ich denke mal über die ISP-Schnittstelle) verbunden hast.

von Karl H. (kbuchegg)


Lesenswert?

M2 schrieb:
> Nochmal zu deinem Code
>
>>(!(Eingabeport & (1<<2)))==0
>
> Kürzen wir das mal
>
> (!(Eigabeport & 0b00000100))==


M2, dein Vorschlag die (1 << Pin) Schreibweise durch die Bitschreibweise 
zu ersetzen ist kontraproduktiv.

Unmengen von Leute hier im Forum versuchen alles Mögliche um die Leute 
möglichst zu dieser Shift-Schreibweise zu bringen.

Matthias: Deine Shift-Schreibweise ist schon in Ordnung. Dein Compiler 
setzzt das schon richtig um. Bzw. er tut etwas noch viel besseres: Er 
kennt diese Schreibweise und optimiert sie wenn möglich zu bestimmte 
Bit-Setz bzw. Bit-Lösch Operationen, wenn dies geht.

>  while(!(Eingabeport==0xff))
>
> damit ist mir jetzt geholfen.

Damit ist deine ganze schöne Flexibilität, um die es dir in erster Linie 
ging, wieder beim Teufel
1
#define TASTER_PORT    PORTC
2
#define TASTER_PIN     PINC
3
#define TASTER_DDR     DDRC
4
5
#define TASTE_LINKS    PC0
6
#define TASTE_RECHTS   PC1
7
#define TASTE_ENTER    PC7
8
9
#define LED_PORT       PORTC
10
#define LED_DDR        DDRD
11
12
#define LED_ROT        PC2
13
#define LED_GRUEN      PC4
14
15
int main()
16
{
17
  TASTER_DDR &= ~( ( 1<<TASTE_LINKS ) |       // die Portbits für die Tasten
18
                  ( 1<<TASTE_RECHTS ) |      // auf Eingang stellen
19
                  ( 1<<TASTE_ENTER ) );      // (sind sie an und für sich sowieso per Default)
20
21
  TASTER_PORT |= ( 1<<TASTE_LINKS ) |      // Pullups für die Tasten einschalten
22
                 ( 1<<TASTE_RECHTS ) |
23
                 ( 1<<TASTE_ENTER );
24
 
25
  LED_DDR |= ( 1 << LED_ROT ) |            // die Ausgaenge für die LED
26
             ( 1 << LED_GRUEN );
27
 
28
  LED_PORT |= ( 1 << LED_ROT );
29
  LED_PORT &= ~( 1 << LED_GRUEN );
30
31
  while( 1 ) {
32
    if( !( TASTER_PIN & ( 1<<TASTE_LINKS ) ) ||
33
        !( TASTER_PIN & ( 1<<TASTE_RECHTS ) ) ||
34
        !( TASTER_PIN & ( 1<<TASTE_ENTER ) ) ) {    // irgendeine Taste gedrückt?
35
      LED_PORT &= ~( 1 << LED_ROT );
36
      LED_PORT |= ( 1 << LED_GRUEN );
37
    }
38
    else {
39
      LED_PORT |= ( 1 << LED_ROT );
40
      LED_PORT &= ~( 1 << LED_GRUEN );
41
    }
42
  }
43
}

So kannst du nur in den #define festlegen, wo welche Taste bzw. LED 
angeschlossen wird. Wobei hier noch davon ausgegangen wird, dass die 
jeweilige Bauteilkategorie alle am selben Port angeschlossen ist. Wenn 
man das noch feiner braucht, dann muss man noch mehr #define einführen, 
zb für jede LED eine eigene Port/DDR Definition und im Code dann 
entsprechend aufdröseln.

Mit noch ein paar #define mehr kann man zb die Vorgang des Bit-Setzens 
bzw. Bit-löschens zb für LED hinter einem Makro verstecken, so dass sich 
der Code in der Hauptschleife so liest
1
int main()
2
{
3
  ....
4
5
  while( 1 ) {
6
7
    if( !( TASTER_PIN & ( 1<<TASTE_LINKS ) ) ||
8
        !( TASTER_PIN & ( 1<<TASTE_RECHTS ) ) ||
9
        !( TASTER_PIN & ( 1<<TASTE_ENTER ) ) ) {    // irgendeine Taste gedrückt?
10
      LED_ON( LED_ROT );
11
      LED_OFF( LED_GRUEN );
12
    }
13
    else {
14
      LED_OFF( LED_ROT );
15
      LED_ON( LED_GRUEN );
16
    }
17
  }
18
}

jetzt hat man einen lesbaren Code, der durch die #define zudem noch gut 
an andere Gegebenheiten angepasst werden kann.
Bei Makros (#define) ist es meistens eine gute Idee, wenn man sich 2 
Dinge hinschreibt:
  * wie schaut der Code ursprünglich aus
  * wie hätte ich gerne, dass der Code aussieht

Aus dem Vergleich der beiden folgt dann relativ unmittelbar, durch 
welche Textersetzung Punkt 2 aus Punkt 1 erhalten werden kann. Und damit 
hat man dann schon meist das Makro fast vollständig.

Das compilierbare Ziel
1
      LED_PORT &= ~( 1 << LED_ROT );
kann man aus
1
      LED_ON( LED_ROT );
erzeugen, indem man den Präprozessor anweist mittels
1
#define LED_ON(led)    LED_PORT &= ~( 1 << led )
die entsprechende Textersetzung durchzuführen. Du schreibst das für dich 
lesbare
1
      LED_ON( LED_ROT );
und durch Anwenden aller Textersetzungen entsteht für den Compiler dann 
der Code
1
     PORTC &= ( 1<<PC2 );
welches er in eine "Clear Bit 2 an PORTC"-Assembler-Instruktion 
übersetzt.

von Matthias H. (maethes26)


Lesenswert?

Fridolin schrieb:
> Eventuell unqualifiziert da ich gerade nur oberflächlich ins Datenblatt
> geschaut habe:
> Im Kapitel "Alternate Functions of Port C" des Atmega32 Datenblatts
> steht in Tabelle 29, dass PC7 bis PC4 scheinbar für JTAG genutzt werden,
> wenn die Fuse JTAGEN gesetzt ist. Nachschauen ob das so ist, kannst du
> einfach über das entsprechende Tab in AVR-Studio wenn du dich auf den
> Controller (ich denke mal über die ISP-Schnittstelle) verbunden hast.

Hallo Fridolin,

hat geklappt. Nachdem ich die Jtag Schnittstelle in den Fuses 
deaktiviert habe, konnte ich die PORTC PINs problemlos benutzen.

viele Grüße,

Matthias.

von M2 (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> M2, dein Vorschlag die (1 << Pin) Schreibweise durch die Bitschreibweise
> zu ersetzen ist kontraproduktiv.
>
> Unmengen von Leute hier im Forum versuchen alles Mögliche um die Leute
> möglichst zu dieser Shift-Schreibweise zu bringen.

Ich bin der Auffassung, Code muss übersichtlich sein. Und das ist die 
1000fache 1<<x Schreibweise nicht (Zumindes bin ich der Meinung, du 
kannst es ja anders sehen). Und dann die invertierung und der Vergleich 
mit 0. Sicherlich kann man das 0xff noch anders ausdrücken mit 
ergendwelchen Konstanten.

von M2 (Gast)


Lesenswert?

while( (!(Eingabeport & (1<<WARTEBIT0)))==1 && (!(Eingabeport &
(1<<WARTEBIT1)))==0 && (!(Eingabeport & (1<<WARTEBIT2)))==0  &&
(!(Eingabeport & (1<<WARTEBIT3)))==0  && (!(Eingabeport &
(1<<WARTEBIT4)))==1  && (!(Eingabeport & (1<<WARTEBIT5)))==0  &&
(!(Eingabeport & (1<<WARTEBIT6)))==1  && (!(Eingabeport &
(1<<WARTEBIT7)))==0   );

@Karl Heinz Buchegger

(Code verändert)

Sag mir mal in 1 Sekunde welchen Pegel Wartebit 5 haben soll

von M2 (Gast)


Lesenswert?

Achso und zeige mir mal den Assembler-Code dazu.

von Karl H. (kbuchegg)


Lesenswert?

M2 schrieb:
> while( (!(Eingabeport & (1<<WARTEBIT0)))==1 && (!(Eingabeport &
> (1<<WARTEBIT1)))==0 && (!(Eingabeport & (1<<WARTEBIT2)))==0  &&
> (!(Eingabeport & (1<<WARTEBIT3)))==0  && (!(Eingabeport &
> (1<<WARTEBIT4)))==1  && (!(Eingabeport & (1<<WARTEBIT5)))==0  &&
> (!(Eingabeport & (1<<WARTEBIT6)))==1  && (!(Eingabeport &
> (1<<WARTEBIT7)))==0   );
>
> @Karl Heinz Buchegger
>
> (Code verändert)
>
> Sag mir mal in 1 Sekunde welchen Pegel Wartebit 5 haben soll

Formatier es ordentlich, dann sieht man das auch
1
  while( (!(Eingabeport & (1<<WARTEBIT0))) == 1 &&
2
         (!(Eingabeport & (1<<WARTEBIT1))) == 0 &&
3
         (!(Eingabeport & (1<<WARTEBIT2))) == 0 &&
4
         (!(Eingabeport & (1<<WARTEBIT3))) == 0 &&
5
         (!(Eingabeport & (1<<WARTEBIT4))) == 1 &&
6
         (!(Eingabeport & (1<<WARTEBIT5))) == 0 &&
7
         (!(Eingabeport & (1<<WARTEBIT6))) == 1 &&
8
         (!(Eingabeport & (1<<WARTEBIT7))) == 0 )
9
    ;

abgesehen davon, dass deine Vergleiche mit den Konstanten 
kontraproduktiv sind. In C ist weniger manchmal eben mehr. Aber das 
weniger muss auch an der richtigen Stelle sitzen.

von Ralf G. (ralg)


Lesenswert?

M2 schrieb:
> while( (!(Eingabeport & (1<<WARTEBIT0)))==1 && (!(Eingabeport &
> (1<<WARTEBIT1)))==0 && (!(Eingabeport & (1<<WARTEBIT2)))==0  &&
> (!(Eingabeport & (1<<WARTEBIT3)))==0  && (!(Eingabeport &
> (1<<WARTEBIT4)))==1  && (!(Eingabeport & (1<<WARTEBIT5)))==0  &&
> (!(Eingabeport & (1<<WARTEBIT6)))==1  && (!(Eingabeport &
> (1<<WARTEBIT7)))==0   );

Wer macht denn sowas??

von Karl H. (kbuchegg)


Lesenswert?

M2 schrieb:
> Karl Heinz Buchegger schrieb:
>> M2, dein Vorschlag die (1 << Pin) Schreibweise durch die Bitschreibweise
>> zu ersetzen ist kontraproduktiv.
>>
>> Unmengen von Leute hier im Forum versuchen alles Mögliche um die Leute
>> möglichst zu dieser Shift-Schreibweise zu bringen.
>
> Ich bin der Auffassung, Code muss übersichtlich sein.

Eben.
Und da ist die << Schreibweise allemal besser als eine Binärzahl. Von 
Wartungsfreundlicher reden wir erst mal gar nicht.

Was ist leichter zu lesen bzw zu verstehen
1
    LED_PORT &= ~( 1 << ALARM_LED );
2
3
bzw.
4
5
    LED_ON( ALARM_LED );

oder
1
    POTRD &= 0b11111011;

Was ist leichter zu verändern, falls die LED in der nächsten 
Programmversion umziehen muss, weil der Pin wegen seiner Sonderfunktion 
für etwas anderes gebraucht wird?

von Karl H. (kbuchegg)


Lesenswert?

M2 schrieb:
> Achso und zeige mir mal den Assembler-Code dazu.

So oft kommt das nicht vor, dass man tatsächlich alle 8 Bit eines Ports 
in einer Abfrage berücksichtigen muss. Und selbst wenn, kann man das 
immer noch mit einer ganz anderen Schreibweise berücksichtigen

1
 while( (Eingabeport & (1<<WARTEBIT1 | 1<<WARTEBIT4 | 1<<WARTEBIT5) )
2
   ;

solange loopen, wie WARTEBIT1 und WARTEBIT4 und WARTEBIT5 auf 1 sind 
(alle anderen Pins bleiben unberücksichtigt).

Braucht man: Solange warten wie von allen 8 Bits (also alle 
berücksichtigt) die Pins WARTEBIT1, WARTEBIT4 und WARTEBIT5 auf 1 sind 
und alle anderen auf 0, dann
1
 while( Eingabeport == (1<<WARTEBIT1 | 1<<WARTEBIT4 | 1<<WARTEBIT5) )
2
   ;


Der Compiler macht dann wieder deine heiß geliebte Hex-Zahl drauss. Im 
Assembler Output macht das daher keinen Unterschied zu der von dir 
propagierten Variante.

was macht wohl dieser Code auf logischer Ebene?
1
   while( PIND & 0x43 )
2
     ;

recht viel kann man darüber nicht sagen, ausser dass er solange wartet, 
solange 3 bestimmte Pins am Port D auf 1 sind. Aber warum und wieso, 
Fehlanzeige

Wohingegen mir der Code
1
 while( SENSOR_PIN & ( 1 << OVERHEATED |
2
                       1 << PRESSURE_TOO_LOW |
3
                       1 << DOOR_OPEN ) )
4
   ;
schon eine ganz klare Vorstellung davon gibt, warum da eine Schleife 
ist, und worauf da eigentlich gewartet wird bzw. welche Bedingungen 
erfüllt sein müssen, damit es im Programm weiter geht.

Die Information, dass am Pin 0 der Temperatur Sensor seine Überhitzung 
meldet, ist hingegen Information, die ich vom logischen Standpunkt aus 
gesehen an dieser Stelle nicht brauche. Das sind Konfigurationswerte, 
deren exakter Zahlenwert an dieser Stelle ziemlich uninteressant ist 
bzw. sein sollte, solange er nur im gültigen Bereich liegt.

von Karl H. (kbuchegg)


Lesenswert?

Und ob man das jetzt so schreibt
1
#define OVERHEATED        0
2
#define PRESSURE_TOO_LOW  1
3
#define DOOR_OPEN         6
4
5
...
6
7
8
 while( SENSOR_PIN & ( 1 << OVERHEATED |
9
                       1 << PRESSURE_TOO_LOW |
10
                       1 << DOOR_OPEN ) )
11
   ;


oder so
1
#define OVERHEATED        (1 << 0)
2
#define PRESSURE_TOO_LOW  (1 << 1)
3
#define DOOR_OPEN         (1 << 6)
4
5
...
6
7
8
 while( SENSOR_PIN & ( OVERHEATED |
9
                       PRESSURE_TOO_LOW |
10
                       DOOR_OPEN ) )
11
   ;


das ist nun wirklich syntaktischer Zucker. In beiden Fällen erkennt man 
rasch, welches Signal welchem Pin zugeordnet ist UND welchen Sinn die 
while-Schleife hat.

UND ... (was dir wichtig ist)

... man zahlt keinen Runtime-Penalty gegenüber
1
   while( PIND & 0x43 )
2
     ;

Es ist nur eine andere Schreibweise, die in identischem Code mündet, die 
aber einige dokumentarische Vorteile hat, wie du hoffentlich aus den 
Beispielen gesehen hast.

Allerdings: ein wenig Mühe muss man sich beim Hinschreiben schon geben. 
Ist aber so schlimm auch wieder nicht. Eine typische Codezeile wird 2 
bis 3 mal gschrieben (inkl Korrekturen), wird aber typischerweise mehr 
als 10 mal gelesen. D.h. das bischen Mehraufwand beim Tippen macht sich 
durch schnelleres Coderfassen beim Lesen mehr als bezahlt.

von M2 (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> #define OVERHEATED        (1 << 0)
> #define PRESSURE_TOO_LOW  (1 << 1)
> #define DOOR_OPEN         (1 << 6)
>
> ...
>
>
>  while( SENSOR_PIN & ( OVERHEATED |
>                        PRESSURE_TOO_LOW |
>                        DOOR_OPEN ) )
>    ;

Mit dieser Schreibweise bin ich auch einverstanden, das ist wieder 
schnell lesbar ;).

Wobei ich es so geschrieben hätte
#define OVERHEATED        (1 << 0x01)
#define PRESSURE_TOO_LOW  (1 << 0x02)
#define DOOR_OPEN         (1 << 0x40)

Aber das ist geschmacks Sache und soll jeder so machen wie er mag. Im 
Programm selber sieht es dann ja identisch aus.

von M2 (Gast)


Lesenswert?

Copy and past fehler Fehler ;)

#define OVERHEATED        0x01
#define PRESSURE_TOO_LOW  0x02
#define DOOR_OPEN         0x40

so meine ich

von ... (Gast)


Lesenswert?

M2 schrieb:
> #define OVERHEATED        0x01
> #define PRESSURE_TOO_LOW  0x02
> #define DOOR_OPEN         0x40
>
> so meine ich

Das ist aber auch daneben. Bei der Schreibweise von Karl Heinz sieht man 
auf den ersten Blick, das es sich bspw. bei DOOR_OPEN um Pin 6 handelt. 
Bei Deiner Schreibweise darf man erst wieder rumrechnen. Ich lass lieber 
den Compiler rechnen, der macht wenigstens keine Fehler dabei.

von Karl H. (kbuchegg)


Lesenswert?

... schrieb:
> M2 schrieb:
>> #define OVERHEATED        0x01
>> #define PRESSURE_TOO_LOW  0x02
>> #define DOOR_OPEN         0x40
>>
>> so meine ich
>
> Das ist aber auch daneben. Bei der Schreibweise von Karl Heinz sieht man
> auf den ersten Blick, das es sich bspw. bei DOOR_OPEN um Pin 6 handelt.
> Bei Deiner Schreibweise darf man erst wieder rumrechnen.

Das wäre auch mein Einwand gewesen. Ich habs dann aber gelassen, weil 
ich 0x40 dann nicht mehr ganz so schlimm finde, auch wenn ich keinen 
Vorteil in der Hexzahl zu (1<<6) sehe.

> Ich lass lieber
> den Compiler rechnen, der macht wenigstens keine Fehler dabei.

Das seh ich genauso wie du. Lass den Compiler die Routine aufgaben 
übernehmen.

von ... (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Das wäre auch mein Einwand gewesen. Ich habs dann aber gelassen, weil
> ich 0x40 dann nicht mehr ganz so schlimm finde, auch wenn ich keinen
> Vorteil in der Hexzahl zu (1<<6) sehe.

Ich selbst hab prinzipell auch kein Problem mit hex, wobei ich dann 
allerdings eher noch auf oktal zurückgreifen würde. Ich hab aber auch 
schon mehr als 25 Jahre damit zu tun.

von M2 (Gast)


Lesenswert?

War mir vorher schon klar das der einwand jetzt kommt ;) . Ich mags halt 
so. Das soll jeder so machen wie er mag. Ich komme mit den HEX-Zahlen 
gut klar. und wer HEX nicht mag kann auch Binär nehmen und dann sieht 
man es wieder auf den ersten Blick.

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.