Hallo,
ich wollte mal fragen, ob das auch eleganter geht:
1
if(anAus)
2
{
3
PORTB|=(1<<PB0)
4
}
5
else
6
{
7
PORTB&=~(1<<PB0)
8
}
Die Variable kommt aus einem größeren Programm, ich muss sie also in der
Form haben.
Mir wäre etwas in dem Stiel:
"PinX = anAus" lieber.
Ich habe den Code gleich 10mal in einer ISR, deshalb hätte ich es gern
etwas schlanker ;)
Für einen hilfreichen Tipp bin ich dankbar.
Gruß,
Tobi
Ein Fest a. schrieb:> Ich habe den Code gleich 10mal in einer ISR, deshalb hätte ich es gern> etwas schlanker ;)
Das sieht nur in C so behäbig aus. Der Compiler macht das schon ziemlich
schlank.
In C kannst du noch syntaktischen Zucker drüberstreuen, damit es nicht
ganz so behäbig aussieht. Aber am Prinzip ändert sich dadurch nichts.
zb kannst du dir die Details in einem Makro verstecken.
Karl Heinz Buchegger schrieb:> In C kannst du noch syntaktischen Zucker drüberstreuen, damit es nicht> ganz so behäbig aussieht. Aber am Prinzip ändert sich dadurch nichts.
Z.B. mit meiner sbit.h
Peter Dannegger schrieb:> Karl Heinz Buchegger schrieb:>> In C kannst du noch syntaktischen Zucker drüberstreuen, damit es nicht>> ganz so behäbig aussieht. Aber am Prinzip ändert sich dadurch nichts.>> Z.B. mit meiner sbit.h>
1
>if(anAus)
2
>{
3
>PORT_B0=1;
4
>}
5
>else
6
>{
7
>PORT_B0=0;
8
>}
9
>
Was mich immer schon mal interessiert hat.
Kriegt der gcc das hin, dass er da Einzelbitoperationen draus macht,
oder erledigt er das über Read/Modify/Update?
> PORT_B0 = 1;> 86: c0 9a sbi 0x18, 0 ; 24
Hey. cool.
Deine Struktur-Geschichte hätte nämlich einen reisengroßen Vorteil. Man
könnte für alle Hardwareregister eine entsprechende Struktur generieren,
mit sauberen Bitnamen:
TIMSK.TOIE0 = TRUE;
und wenn das TIEO1 Bit bei einem µC nicht im TIMSK Register ist, dann
schreit der Compiler. Die "klassischen" Fehler, dass die WGM Bits in 2
verschiedenen Config-Register sind, wären damit entschärft.
Bzw. dann weitergehend überhaupt nur noch
TOIE0 = TRUE;
und der Compiler "sucht selber raus", in welchem Register das
entsprechende Bit sitzt.
Das wär schon was.
Ralf G. schrieb:> Ich häng' mich mal rein.> Könnte sowas in der ein oder anderen Situation nicht noch> übersichtlicher sein:
Läuft ja im Kern aufs selbe raus.
> Aufruf:>
1
>PortD.b2=1;
2
>
So wie Peter das macht, geht das ja noch einen Schritt weiter. In einem
realen Programm wirst du ja nicht, oder nur selten, an PortD.b2 etwas
zuweisen. Denn an dem Pin hängt ja etwas. Zb eine Error Led oder eine
Busy LED. D.h. du möchtest gerne schreiben:
1
#define ERROR_LED SBIT( PORTD, 2 )
2
#define BUSY_LED SBIT( PORTD, 3 )
3
4
...
5
6
ERROR_LED=1;
7
BUSY_LED=0;
Sein SBIT Makro dient dazu, eine Verknüpfung zwischen Port und Pin zu
schaffen, damit man im eigentlichen Code überhaupt nichts nacharbeiten
muss, wenn Funktionseinheiten ihre Pinzuordnung wechseln.
Kann man wirklich immer so auch auf DDRD und PIND zugreifen??
ich mein so: (ich weiß nicht, ob die '+1' so stimmt, aber ich meine ja
nr vom Prinzip her...
1
#define PinD (*((volatile struct bits*)&(PORTD+1)))
Sepp schrieb:> Kann man wirklich immer so auch auf DDRD und PIND zugreifen??> ich mein so: (ich weiß nicht, ob die '+1' so stimmt, aber ich meine ja> nr vom Prinzip her...
Ich meine mich zu erinnern, dass es beim Mega128 (F oder G) eine
Ausnahme gibt.
Karl Heinz Buchegger schrieb:>> Läuft ja im Kern aufs selbe raus.>> ...>> So wie Peter das macht, geht das ja noch einen Schritt weiter. In einem> realen Programm wirst du ja nicht, oder nur selten, an PortD.b2 etwas> zuweisen.
Naja, es wird sozusagen aus dem Port dann eine Datenstruktur.
So wie bei:
Karl Heinz Buchegger schrieb:> TIMSK.TOIE0 = TRUE;
Das 'PORT_D2' wollte ich vermeiden.
> Denn an dem Pin hängt ja etwas. Zb eine Error Led oder eine> Busy LED. D.h. du möchtest gerne schreiben:> #define ERROR_LED SBIT( PORTD, 2 )> #define BUSY_LED SBIT( PORTD, 3 )>> ...>> ERROR_LED = 1;> BUSY_LED = 0;>> Sein SBIT Makro dient dazu, eine Verknüpfung zwischen Port und Pin zu> schaffen, damit man im eigentlichen Code überhaupt nichts nacharbeiten> muss, wenn Funktionseinheiten ihre Pinzuordnung wechseln.
Das wäre dann mit direktem Zugriff auf SBIT. Mmh, auch eine Möglichkeit.
Vielleicht noch zur Disskusion:
Ralf G. schrieb:> Vielleicht noch zur Disskusion:
Wie immer du das machen willst.
Eines muss sowieso klar sein: Das alles ist nur syntaktischer Zucker auf
C-Ebene. Wenn unten nach dem compilieren sowieso wieder das gleiche raus
kommst, geht es nur darum, wie man das Zeugs dann im Code so verwenden
kann, dass man möglichst wenig Fehler machen kann. Und wenn, soll der
Compiler sie abfangen können.
> if ( PinB_(1 << B_EIGENES) == 0 )> Naja, vielleicht auch nicht besser als:> if ( (~PINB) & (1 << B_EIGENES) )
Der springede Punkt um den es mir an dieser Stelle geht besteht darin,
dass du im Code hier 2 Informationen stehen hast, die zusammenstimmen
müssen:
* welcher Port
* welches Bit an diesem Port
Du hast also eine mögliche Fehlerquelle, indem du zwar das richtige Bit
aber am falschen Port angibst. Kein Compiler hilft dir dabei, wenn du
schreibst
if( PinD_( B_EIGENES ) == 0 ) // OOps, sollte eigentlich PinB sein!
Muss ich selber aber an dieser Stelle keine 2 Informationen in
Übereinstimmung bringen
if( B_EIGENES == 0 )
und durch die Makroexpansion expandiert das zum richtigen Bit am
richtigen Port, dann hab ich eine potentielle Fehlerquelle weniger.
D.h. neben den syntaktischen Zucker, hat das ganze Abspecken durchaus
einen ernsten Hintergrund in der passiven Programmierung.
Karl Heinz Buchegger schrieb:> if( B_EIGENES == 0 )
Was ist jetzt schon wieder 'B_EIGENES'? Könnte man hier fragen. Um
dann vielleicht zum Verständis viele verschachtelte Makros
auseinanderpflücken zu müssen.
TIMSK.TOIE0 = TRUE; // (c) khb
... da weiß man, was man hat!
Ralf G. schrieb:> Karl Heinz Buchegger schrieb:>> if( B_EIGENES == 0 )>> Was ist jetzt schon wieder 'B_EIGENES'? Könnte man hier fragen.
:-)
Kann man.
Du bist doch mit dem B_EIGENES hochgekommen.
In der Realität steht dann da eben
if( DRUCK_ALARM )
weil DRUCK_ALARM dann eben so definiert ist, dass das ein Eingangspin am
Port C, Pin 5 ist, an dem der Wasserdrucksensor einen Überdruck anzeigt.
Karl Heinz Buchegger schrieb:> Du bist doch mit dem B_EIGENES hochgekommen.
Ich weiß! :)
Hatte da eher im Blick, dass es sich um so eine 'verschachtelte'
Konstruktion wie von Peter handeln könnte. Und wenn dann schon das|die
Makro(s) fehlerhaft sind...
Also, Makros aus Makros aus Makros aufrufen, versuche ich lieber zu
vermeiden.
Johann L. schrieb:> Peter Dannegger schrieb:>> Man könnte auch schreiben:PORT_B0 = !!anAus;> Aber das ergibt größeren Code.>> Wenn die Variable den zu setzenden Wert schon in Bit0 enthält,
... oder sie, wie es offensichtlich hier sinnvoll wäre, vom Typ bool ist
> geht auch