Gast
#6059571
Hallo, stehe gerade auf dem Schlauch. Ich habe mehrere Leuchtdioden. Diese würde ich gerne so..
1 | |
2 | |
Ist das überhaupt ohne Makros möglich?
|
Anzeige
|
C -> Port Bitset
Gast
#6059571
Hallo, stehe gerade auf dem Schlauch. Ich habe mehrere Leuchtdioden. Diese würde ich gerne so..
Ist das überhaupt ohne Makros möglich?
Gast
#6059572
Könnte mit einem Union und einem Bitfield gehen wenn das ganze eine Zeiger auf den Port ist. Bin mir aber nicht ganz sicher.
Gast
#6059577
SETBIT(LED,GREEN) hiesse es bei mir, Makro dazu:
LED ist dann dein Ausgangpin und GREEN die Nummer (alles in den defines zu erledigen)
Gast
#6059583
Wollte er nicht wissen ob es ohne Makros möglich ist :D Mit . ist das vermutlich ne ganze Menge Schreibarbeit. Wenns auch ohne . sein darf, gibt es hier schon fertige Macros: Beitrag "Re: Port als Variable" Geht bedingt mit bit-field: https://en.cppreference.com/w/c/language/bit_field Ist aber implementation-defined.
Gast
#6059597
Wilhelm M. schrieb: > Geht bedingt mit bit-field: > > https://en.cppreference.com/w/c/language/bit_field > > Ist aber implementation-defined. Okay. Aber da sehe ich nichts vom Port Zugriff? Peter K. schrieb: > Ist das überhaupt ohne Makros möglich? Nein. Peter K. schrieb: > Okay. Aber da sehe ich nichts vom Port Zugriff? Es gibt unzählige Versuche, das mit bit-fields zu lösen - auch hier im Forum. Die sind alle falsch bis zweifelhaft, weil sie ausnahmslos mindestens implementation-defined behaviour dabei haben, manche im Kontext von C++ mit union as type-punning UB. Also: entweder richtig machen (Klasse in C++) oder sein lassen.
Gast
#6059673
Peter K. schrieb: > Ist das überhaupt ohne Makros möglich? Wie ist das mit Makros möglich? (diese Schreibweise mit LED._____)
Gast
#6059702
> Wie ist das mit Makros möglich? (diese Schreibweise mit LED._____)
Mit genügend hoher "ugly-hack-Schwelle":
foobar schrieb: >> Wie ist das mit Makros möglich? (diese Schreibweise mit LED._____) > > Mit genügend hoher "ugly-hack-Schwelle": >
Es gibt einen fest reservierten Platz in der Hölle, für Leute die so was machen.
Gast
#6059712
Wilhelm M. schrieb: > Ist aber implementation-defined. Ja. Aber ein Portzugriff ist nicht nur an den Compiler, sondern auch an die HW genagelt, also relativ überschaubar das Problem. Wenn der Port ganz normal memory-mapped ist und bitweise adressierbar ist, dann geht das meistens relativ straight:
Gast
#6059740
Keep it simple! In einer Header Datei:
In einer *.c oder *.cpp Datei:
Der Compiler reduziert das optimal auf Einzelbit-Befehle (cbi und sbi).
Gast
#6059749
> #define LED_GREEN_OFF { PORTB &= ~(1<<PB2)); }
Immer ein "do-while(0)" um die geschweiften Klammer! Dann geht dein
Beispiel auch ohne die geschweiften Klammern beim "if".
Gast
#6059797
Stefan F. schrieb: > LED GREEN OFF Huch, da fehlen die Unterstriche: LED_GREEN_OFF; foobar schrieb: > Immer ein "do-while(0)" um die geschweiften Klammer! Dann geht dein > Beispiel auch ohne die geschweiften Klammern beim "if". bei gcc nicht nötig, da impliziert durch die {} klammer und sowieso schon alles ugly. mt
Gast
#6059966
>> Immer ein "do-while(0)" um die geschweiften Klammer! > > bei gcc nicht nötig, Bei jedem C-Compiler nötig! Siehe http://c-faq.com/cpp/multistmt.html
Gast
#6059974
Da ich hinter if, else, while, for, ... sowieso immer geschweifte Klammern schreibe, ist mit dieser kleine gemeine Unterschied noch nie aufgefallen.
Gast
#6060070
Stefan F. schrieb: > #define LED_GREEN_ON { DDRB |= (1<<PB2)); PORTB |= (1<<PB2)); } Was unterscheidet PB2 von PA2? Die (1<<PB2) schreibweise verblödet langsam. Wieviel Klammern sind falsch? :-< #define LED_GREEN_ON { DDRB |= BIT_2; PORTB |= BIT_2; }
Gast
#6060083
> #define LED_GREEN_ON { DDRB |= BIT_2; PORTB |= BIT_2; }
Besser
#define LED_GREEN_ON do { DDRB |= BIT_2; PORTB |= BIT_2; } while (0)
;-)
MaWin schrieb: > #define LED_GREEN_ON { DDRB |= BIT_2; PORTB |= BIT_2; } Was ist denn das für ein Blödsinn: jedesmal, wenn man die LED einschalten will auch das DDR zu setzen. Stefan F. schrieb: > // Green LED = PB2 high active > #define LED_GREEN_ON { DDRB |= (1<<PB2)); PORTB |= (1<<PB2)); } > #define LED_GREEN_OFF { PORTB &= ~(1<<PB2)); } Das ist wirklich sehr unschön: PB2 an drei Stellen redundant zu verwenden. Für (1 << X) hatte Atmel/MicroChip schon seit Urzeiten _BV(x) eingeführt. A. S. schrieb: > Wenn der Port ganz normal memory-mapped ist und bitweise adressierbar > ist, dann geht das meistens relativ straight: > /* reihenfolge Compiler(setting) und HW-spezifisch */ > struct sLedPort > { > unsigned char Green : 1; > unsigned char : 2; > unsigned char Blue : 1; > unsigned char : 3; > unsigned char Yellow: 1; > } So etwas führt immer zu RMW-Sequenzen im Maschinencode. Bei µC, die einzelne set/clear oder flag Register haben (also alle etwas moderneren), ist etwa ein
die einzig richtige Möglichkeit. Das mit den Bit-Fields für µC-Register ist und bleibt ein Hack.
Gast
#6060218
Wilhelm M. schrieb: > So etwas führt immer zu RMW-Sequenzen im Maschinencode. Das stimmt nicht und wäre auch unlogisch. Wenn der Controller einzelbits manipulieren kann, tut er es. Ich sehe nicht, dass irgendeine Makrolösung hier geradlieniger ist. A. S. schrieb: > Das stimmt nicht und wäre auch unlogisch. Wenn der Controller einzelbits > manipulieren kann, tut er es. Wenn der µC das kann, und der Compiler diese Optimierung verwendet, ja. Bei den alten AVR gilt das eben nur für die unteren Register. Um hier vollkommen neutral zu sein, haben moderne µC (auch die avr0/tiny1) die set/clear bzw. flag Register. DA funktioniert das dann bei jedem Register. Bei einem bit-field oberhalb von 0x1f hätten wir sonst wieder RMW- Sequenzen (mit all ihren sonstigen Nachteilen wie nicht-Atomarität). A. S. schrieb: > Ich sehe nicht, dass irgendeine Makrolösung hier geradlieniger ist. Da sowieso nicht. Ich sagte ja schon oben: entweder richtig per bit-shift oder eben in einer Klasse abstrahieren. Wilhelm M. schrieb: > Ich sagte ja schon oben: entweder richtig per bit-shift > oder eben in einer Klasse abstrahieren. Oder akzeptieren, dass der ganze Krempel ohnehin hardware- und compilerspezifisch ist und hässlich sowieso. Es muss nicht vollkommen neutral sein. Ob ich nun ein hässliches Makro, ein hässliches Bitfeld-Overlay oder eine hässliche Templateklasse im Header verstecke, ist (zumindest bei den üblichen AVR-Anwendungen) relativ egal. Hauptsache, der eigentliche Code sieht halbwegs sauber und übersichtlich aus. S. R. schrieb: > Ob ich nun ein hässliches Makro, ein hässliches Bitfeld-Overlay oder > eine hässliche Templateklasse im Header verstecke, ist (zumindest bei > den üblichen AVR-Anwendungen) relativ egal. Nun, wir sind in C, da geht es halt nicht besser als mit einem Macro-Hack. Wobei ich immer eine Funktion vorziehen würde (als header-only Bibliothek mit anderen nettes Sachen). Wer mit dem IB der bit-fields und den sonstigen Nachteilen leben möchte, kann das ja gerne machen. In meinen Augen ist das jedenfalls kein Weg. Natürlich, in C++ hat man dafür sein Klassentemplate und entsprechende Spezialisierungen für irgendwelche µC-Abnormitäten. Und wenn man das gescheit macht, finde ich das auch auf der Bibliotheksseite gar nicht mal so hässlich ;-) Wilhelm M. schrieb: > MaWin schrieb: >> #define LED_GREEN_ON { DDRB |= BIT_2; PORTB |= BIT_2; } > > Was ist denn das für ein Blödsinn: jedesmal, wenn man die LED > einschalten will auch das DDR zu setzen. Ist halt so Arduino Style. Wobei da dann noch 29 andere Dinge gemacht werden. Aber man ist auf dem gleichen Weg.
Gast
#6060301
Cyblord -. schrieb: > foobar schrieb: >>> Wie ist das mit Makros möglich? (diese Schreibweise mit LED._____) >> >> Mit genügend hoher "ugly-hack-Schwelle": >>> #define LED (*(volatile struct { char Red:1,Green:1,Blue:1,rest:5; } >> *)&PORTB) >> > Es gibt einen fest reservierten Platz in der Hölle, für Leute die so was > machen. Das liefert Microchip in hunderten von Headerfiles für die PICs mit:
Da erinnert einen der Compiler, ist der gcc, auch daran, da0 es Bit 5 auf Port A nicht gibt. Und ich mach mir das mit #define LED_GREEN PORTAbits.RA0 LED_GREEN = 1; auch noch den Code lesbarer. In den Himmel komm ich sowieso nicht, dafür gibts in der Hölle free WLan. MfG Klaus
Gast
#6060340
Mach dir eine C++ Klasse und überschreibe den Zuweisungs-Operator.
Gast
#6060602
Wilhelm M. schrieb: > Nun, wir sind in C, da geht es halt nicht besser als mit einem > Macro-Hack. Warum schreibst Du das, wo Du doch mein reines C-Beispiel gelesen hast? Es ist kein Macro nötig und schön sowieso nicht. A. S. schrieb: > Warum schreibst Du das, wo Du doch mein reines C-Beispiel gelesen hast? Zitiere mich dann bitte richtig. Das gesamte Statement war: Wilhelm M. schrieb: > Nun, wir sind in C, da geht es halt nicht besser als mit einem > Macro-Hack. Wobei ich immer eine Funktion vorziehen würde (als > header-only Bibliothek mit anderen nettes Sachen). > > Wer mit dem IB der bit-fields und den sonstigen Nachteilen leben möchte, > kann das ja gerne machen. In meinen Augen ist das jedenfalls kein Weg.
Gast
#6060649
Wilhelm M. schrieb: > Was ist denn das für ein Blödsinn: jedesmal, wenn man die LED > einschalten will auch das DDR zu setzen. Ist nur ein Vorschlag. Man muss ja nicht alles 1:1 nachmachen. Cyblord -. schrieb: > Ist halt so Arduino Style. Ja, geht in die Richtung. Allerdings 30x mal schneller als Arduino. Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|