Hallo, x |= (Datenwert << 5) <-- Dass würde das 5te bit von x mit dem Wert "Datenwert beschreiben. Könnt Ihr mir sagen, wie es einfacher geht. Ich will nur ein bit in einem Byte, bzw in einem Integer beschreiben. Aber soetwas wie int Testvariable; Testvariable.0 = 1; Testvariable.1 = 0; Testvariable.2 = 0; Geht nicht. Könnt Ihr mir sagen wie ich es Syntax echt machen müsste ? LG Tim
Tim E. schrieb: > Hallo, > > x |= (Datenwert << 5) <-- Dass würde das 5te bit von x mit dem Wert > "Datenwert beschreiben. Nicht wirklich. Damit kannst du 1 Bit auf 1 setzen aber nicht auf 0. 'beschreiben' ist daher irgendwie das falsche Wort. x |= ( 1 << Bitnummer ); // Bit auf 1 setzen x &= ~( 1 << Bitnummer ); // Bit auf 0 setzen > Könnt Ihr mir sagen, wie es einfacher geht. Was gefällt dir daran nicht?
Das Stichwort ist Bitfelder und Union sowas wie union { int x; struct { char bit1:1; char bit2:1; char bit3:1; } } Beispiel, Syntaktisch nicht vollständig / korrekt. mfg Andreas
Tim E. schrieb: > Dass würde das 5te bit von x mit dem Wert > "Datenwert beschreiben. Nein, da_s_ würde es nicht, beziehungsweise nur dann, wenn Datenwert 1 ist. Ein Bit setzen (mit dem Wert 1 beschreiben) geschieht so, wie von Dir beschrieben: Wert |= (1 << Bitnummer); ein Bit löschen (mit dem Wert 0 beschreiben) aber geschieht so: Wert &= ~(1 << Bitnummer); So und nur so wird das in C gemacht. "Einfacher" geht es nicht, aber "Einfacher" würde es auch durch die von Dir gewünschte Notation nicht werden. Es gibt Krücken, beispielsweise die Kombination eines Bitfelds und eines Bytes in einer union, aber das bewirkt letztlich auch nichts anderes und hilft nur Leuten, das Erlernen herauszuzögern, wie man es richtig anstellt.
Das es so lange und umständlich ist, wenn ich nicht weis ob es eine 0 oder 1 ist, weil das unterschiedlich ist. Dann müsste ich immer ein If abfrage machen. LG
Tim E. schrieb: > Das es so lange und umständlich ist, wenn ich nicht weis ob es eine 0 > oder 1 ist, weil das unterschiedlich ist. Dann müsste ich immer ein If > abfrage machen. Und? Die C Mittel Makros und Funktionen, in denen man diese Details 'verstecken' kann, wurden schon vor 40 Jahren erfunden. Du musst sie nur anwenden.
Bitnummern kann man sich auch definieren. Ungefähr so...
1 | #define BITF (1<<15)
|
2 | ...
|
3 | ...
|
4 | #define BIT8 (1<<8)
|
5 | #define BIT7 (1<<7)
|
6 | #define BIT6 (1<<6)
|
7 | ...
|
8 | ...
|
9 | #define BIT0 (1<<0)
|
...sieht das dann beim MSP430 aus, weil der ja eine 16Bit-Maschine ist. Beispiel für Bit 3 und 4... setzen:
1 | foo |= BIT3 + BIT4; |
löschen:
1 | foo &= ~(BIT3 + BIT4); |
mfg mf
Tim E. schrieb: > Dann müsste ich immer ein If abfrage machen. Du musst das doch nur einmal eingeben. Machen tut das der Controller. Und dem ist egal, wie oft er das macht. mfg.
Tim E. schrieb: > Das es so lange und umständlich ist, wenn ich nicht weis ob es eine 0 > oder 1 ist, weil das unterschiedlich ist. Dann müsste ich immer ein If > abfrage machen. In der Zeit in der du da rumprüfst, ob jetzt was getan werden muss, ist es besser, es wird gleich getan. Du gibst den Sollwert eines Bits an. Den nimmt es ein, egal was vorher war. Wenn man alternierendes Verhalten haben will wie ein einrastender Druckknopf, dann gibt es noch toggeln:
1 | int main(void) |
2 | {
|
3 | uint8_t foo = BIT1; |
4 | |
5 | while(1) |
6 | foo ^= BIT1 + BIT6; |
Bit1 und Bit6 spielen jetzt Polizeiauto mit Blaulicht... mfg mf PS: Beim Löschen schön drauf schaun, dass die "~" da ist.
Mini Float schrieb: > In der Zeit in der du da rumprüfst, ob jetzt was getan werden muss, ist > es besser, es wird gleich getan. Du gibst den Sollwert eines Bits an. > Den nimmt es ein, egal was vorher war. Da sei dir man nicht so sicher. Das sieht in C geschrieben zwar kurz und knapp aus, aber guck' dir mal an, was der Compiler daraus macht. Denn das prüfen auf "0" ist ein einziger Befehl, der in einem Takt ausgeführt wird. jz, breq oder wie auch immer. mfg.
eori, andi oder ori sind Einzeiler im Assemblercode. Die konstanten Werte hinter dem "=" werden als solche erkannt und in die Anweisung codiert. Gerade bei ifs in C, wenn sie einen Vergleichsoperator haben, werfen manche compiler immer noch ein tst als expliziten Nullvergleich ein, obwohl es meist nicht sein muss. mfg mf
Na, wenn du meinst. if (Datenwert) Testvariable |= (1 << 5); else Testvariable &= ~(1 << 5); 9c: 80 91 6c 00 lds r24, 0x006C a0: 88 23 and r24, r24 a2: 21 f0 breq .+8 ; 0xac <main+0x10> a4: 80 91 6b 00 lds r24, 0x006B a8: 80 62 ori r24, 0x20 ; 32 aa: 03 c0 rjmp .+6 ; 0xb2 <main+0x16> ac: 80 91 6b 00 lds r24, 0x006B b0: 8f 7d andi r24, 0xDF ; 223 b2: 80 93 6b 00 sts 0x006B, r24 Testvariable &= ~(1 << 5); b6: 80 91 6b 00 lds r24, 0x006B ba: 8f 7d andi r24, 0xDF ; 223 bc: 80 93 6b 00 sts 0x006B, r24 Testvariable |= (Datenwert << 5); c0: 90 91 6b 00 lds r25, 0x006B c4: 80 91 6c 00 lds r24, 0x006C c8: 82 95 swap r24 ca: 88 0f add r24, r24 cc: 80 7e andi r24, 0xE0 ; 224 ce: 89 2b or r24, r25 d0: 80 93 6b 00 sts 0x006B, r24 mfg.
Hi
>eori, andi oder ori sind Einzeiler im Assemblercode.
eori gibt es nicht. Zumindest bei den Registern haben die GCC-Erfinder
die Möglichkeiten des T-Flags völlig ignoriert.
set
bld Rxy,n
setzt Bit n (0...7) im Register xy
clt
bld Rxy,n
löscht Bit n (0...7) im Register xy
MfG Spess
@Thomas Eckmann: Welche Optimierungsstufe nimmst du? Ich optimiere immer, um Fehler zu finden wenn ich dem Compiler keine deutliche Anweisung gebe. mfg mf
Thomas Eckmann schrieb: > Na, wenn du meinst. Jetzt bist du aber unfair :-) > > if (Datenwert) Testvariable |= (1 << 5); else Testvariable &= ~(1 << 5); > 9c: 80 91 6c 00 lds r24, 0x006C > a0: 88 23 and r24, r24 > a2: 21 f0 breq .+8 ; 0xac <main+0x10> > a4: 80 91 6b 00 lds r24, 0x006B hier > a8: 80 62 ori r24, 0x20 ; 32 passiert das Bit setzen > aa: 03 c0 rjmp .+6 ; 0xb2 <main+0x16> > ac: 80 91 6b 00 lds r24, 0x006B hier > b0: 8f 7d andi r24, 0xDF ; 223 das Bit löschen > b2: 80 93 6b 00 sts 0x006B, r24 Das der Compiler den Inhalt der Variablen laden und Speichern muss, ist klar. Wenn du anstelle von Variablen Port-Register genommen hättest, wäre das nicht notwendig gewesen (insofern warst du unfair).
Karl Heinz Buchegger schrieb: > Jetzt bist du aber unfair :-) Wieso? Es ging darum, ob eine If-Abfrage und dann entweder Löschen oder Setzen schneller ist, oder ob es günstiger ist, grundsätzlich zu löschen und dann zu setzen unabhängig vom Inhalt der Variable. > Wenn du anstelle von Variablen Port-Register genommen hättest, > wäre das nicht notwendig gewesen (insofern warst du unfair). Das wollte ich auch erst, weil ich keine Lust hatte, noch zwei Variable hinzuschreiben. Aber dann habe ich gesehen, daß es oben um Variable ging. mfg.
spess53 schrieb: > Zumindest bei den Registern haben die GCC-Erfinder > die Möglichkeiten des T-Flags völlig ignoriert. Nö. Wie konnst du darauf?
Thomas Eckmann schrieb: > Karl Heinz Buchegger schrieb: >> Jetzt bist du aber unfair :-) > Wieso? > Es ging darum, ob eine If-Abfrage und dann entweder Löschen oder Setzen > schneller ist, oder ob es günstiger ist, grundsätzlich zu löschen und > dann zu setzen unabhängig vom Inhalt der Variable. OK. Dann hab ich nicht mitgekriegt, warauf du hinaus wolltest. Und ich denke Mini-Float wollte seinen ursprünglichen Kommentar auch anders verstanden wissen.
Karl Heinz Buchegger schrieb: > Wenn du anstelle von Variablen Port-Register genommen hättest Jetzt mal die Registervariante: if (GPIOR1) GPIOR0 |= (1 << 5); else GPIOR0 &= ~(1 << 5); 9c: 82 b3 in r24, 0x12 ; 18 9e: 88 23 and r24, r24 a0: 11 f0 breq .+4 ; 0xa6 <main+0xa> a2: 8d 9a sbi 0x11, 5 ; 17 a4: 01 c0 rjmp .+2 ; 0xa8 <main+0xc> a6: 8d 98 cbi 0x11, 5 ; 17 GPIOR0 &= ~(1 << 5); a8: 8d 98 cbi 0x11, 5 ; 17 GPIOR0 |= (GPIOR1 << 5); aa: 91 b3 in r25, 0x11 ; 17 ac: 82 b3 in r24, 0x12 ; 18 ae: 82 95 swap r24 b0: 88 0f add r24, r24 b2: 80 7e andi r24, 0xE0 ; 224 b4: 89 2b or r24, r25 b6: 81 bb out 0x11, r24 ; 17 mfg.
Ersetz doch mal das GPIOR1 durch eine Konstante. Denn das wollte der TO ja wirklich machen und hat sich nur ungeschickt ausgedrückt Zitat > Also sowas wie > int Testvariable; > > > Testvariable.0 = 1; > Testvariable.1 = 0; > Testvariable.2 = 0; Er weiß zur Compiletime, welches Bit er 0 oder 1 setzen will.
Karl Heinz Buchegger schrieb: > Er weiß zur Compiletime, welches Bit er 0 oder 1 setzen will. Das ist klar. Das sind dann im GPIO 2 Befehle. Aber ich bin jetzt davon ausgegangen: >x |= (Datenwert << 5) <-- Dass würde das 5te bit von x mit dem Wert >"Datenwert beschreiben. Naja, da hat er sich wohl wirklich unglücklich ausgedrückt. Oder ich hab' das unglücklich verstanden. mfg.
Egal. So wie sein Programm aussieht Beitrag "C Programm break vergessen ?" hat er ganz andere Probleme.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.