Ich möchte gerne folgendes Bit-Muster mit einer Tasteneingabe hochzählen
und mit einer anderen taste runterzählen:
0000 0000
0001 0000
0010 0000
0011 0000
und das gleiche mit:
0000 0000
0000 0100
0000 1000
0000 1100
Wenn das letzte Bitmuster erreicht ist und man schaltet weiter soll
wieder von vorne begonnen werden.
Wie stell ich das am einfachsten an?
Es sollen ja immer nur 2 Bits fortlaufend geändert werden.
Soll ich hier binär oder doch lieber Hex zählen? -> Wäre jetzt
Profimäßig geklärt...
Lokus P. schrieb:> Soll ich hier binär oder doch lieber Hex zählen?
Ich stehe vor einem ähnlichen Problem. Ich hoffe ihr
könnt mir weiterhelfen. Soll ich jetzt Butter oder
Margarine aufs Brot tun?
Frickelfritze schrieb:> Soll ich jetzt Butter oder> Margarine aufs Brot tun?
Das ist falsch. Es muss "Butter oder Butter" heißen.
Die Zahlendarstellung im Programm spielt keine Rolle, wenn die Variable
selbst binär ist. (Also int, uint8_t, ...)
Dem Prozessor ist es völlig wurscht. Binär oder Hexadezimal sind nur
verschiedene Darstellungsarten. Die Daten und die Rechenoperationen, die
im Programm ausgeführt werden, sind exakt die selben.
Daher nimm das, was besser lesbar ist. Da du uns die Sprache
verheimlichst, kann man da wenig Tipps geben.
Lokus P. schrieb:> Wie siehts jetzt mit dem Rest aus?
Welchem Rest?
Lokus P. schrieb:> Ok, hätten wir mal die erste Frage geklärt. Wie siehts jetzt mit dem> Rest aus?
Mit einer AND-Verknüpfung (C-Operator: &) kannst Du beliebige Bits auf 0
zwingen, also z.B. ergibt
1011 0101
& 0011 1100
---------
0011 0100
Thomas E. schrieb:> W.A. schrieb:>> p = (p++) & 0x03;>> wohl eher p = (++p) & 0x03;
Wie in einem Thread nebenan letztens ausführlich diskutiert, ist beides
nicht zulässig, da das Verhalten in C undefiniert ist. Es muss heißen:
Rolf M. schrieb:> Wie in einem Thread nebenan letztens ausführlich diskutiert, ist beides> nicht zulässig, da das Verhalten in C undefiniert ist. Es muss heißen:
Unabhängig davon, daß ich hier auch (p+1) bevorzugen würde (weil
"schöner"), sehe ich an (++p) aber weder ein undefiniertes Verhalten,
noch warum es unzulässig sein soll!?
Auch (p++) ist zulässig und definiert, führt hier bei "p = (p++)" aber
nicht zur Veränderung der Variablen p.
..eher armselig ist die Fragestellung!
Die stellt kein Fünfjähriger mehr.
Nimm mal ein Blatt Papier und nen Bleistift.
Auf Tastendruck erhöht sich eine Variable jeweils von Null um den Wert
16.
Also 0,16,32,48. Bei 48 soll es umgekehrt laufen.
Wer das Problem löst, bekommt einen Nobelpreis. Haha
p=(OUT_PORT>>4)&3;// 3 ist max 2Bit, 4 ist Ausgabeposition
6
P=(p+1)%4;// 0..3
7
8
OUT_PORT=OUT_PORT&~(3<<4)// Bit 4..5 "frei machen"
9
|(P<<4);// Zähler wieder einfügen
10
...
11
}
Die magischen Zahlen kann man besser als SHIFT und MASK einmal
festlegen, via #define oder static const (oder constexpr, wenn man
dessen Sprache spricht)
Der Zähler könnte natürlich auch außerhalb des OUT_PORT leben, als
globale Variable
@Db:
Einfach nur 16 draufaddieren funktioniert natürlich nur, wenn man kein
Problem mit den Überlauf des Zählers auf das 3.Bit hat.
Besser geht das mit C++ (mit avr-gcc5.3),da bin ich gerade am Erkunden
von C++11/14. Mit etwas variadic template kann man die Bits, die man
hoch/runter zählen will in jeder beliebigen Reihenfolge auf jedem
vorhandenen PORT verteilen.
Thomas E. schrieb:> Rolf M. schrieb:>> Wie in einem Thread nebenan letztens ausführlich diskutiert, ist beides>> nicht zulässig, da das Verhalten in C undefiniert ist. Es muss heißen:>> Unabhängig davon, daß ich hier auch (p+1) bevorzugen würde (weil> "schöner"), sehe ich an (++p) aber weder ein undefiniertes Verhalten,> noch warum es unzulässig sein soll!?
Nicht das (++p) alleine, sondern in Kombination mit der Zuweisung.
> Auch (p++) ist zulässig und definiert, führt hier bei "p = (p++)" aber> nicht zur Veränderung der Variablen p.
Es fürt zu undefiniertem Verhalten laut ISO C, da die Variable p zweimal
beschrieben wird, ohne dass ein Sequenzpunkt dazwischen liegt.
Aber wie gesagt, das wurde letztens schon ausführlichst diskutiert.
Lokus P. schrieb:> eher armselig.
Armselig ist deine Frage. Jeder mit Minimal-Eigenintelligenz würde sich
schämen, sie überhaupt gestellt zu haben...
Denn sie beweist:
1) Du hast keine Ahnung von binärer Logik.
2) Du hast keine Ahnung von der Programmiersprache, die du verwendest.
Damit: Du tust etwas, wozu dir sämtliche essentiellen Grundlagen fehlen.
Mehr noch: Dir ist nicht einmal klar, dass diese Grundlagen essentiell
sind und dass sie dir fehlen.
Klar: dann muss natürlich jeder Hinweis auf diesen Problemkreis aus
deiner Sicht einer Beleidigung gleichkommen. Ist aber keine...
Es ist einfach so: ein wirklich Doofer kann einfach nicht erkennen, dass
er doof ist...
Carl D. schrieb:> Lokus P. schrieb:>> Was soll Ausgabe1 darstellen?>> ...>> oder wie?> void right()> {> int p; // tmp, Zähler selbst ist Teil von OUT_PORT>> p = (OUT_PORT>>4) & 3; // 3 ist max 2Bit, 4 ist Ausgabeposition> P = (p+1) % 4; // 0..3>> OUT_PORT = OUT_PORT & ~(3<<4) // Bit 4..5 "frei machen"> | (P<<4); // Zähler wieder einfügen> ...> }>> Die magischen Zahlen kann man besser als SHIFT und MASK einmal> festlegen, via #define oder static const (oder constexpr, wenn man> dessen Sprache spricht)>> Der Zähler könnte natürlich auch außerhalb des OUT_PORT leben, als> globale Variable>> @Db:> Einfach nur 16 draufaddieren funktioniert natürlich nur, wenn man kein> Problem mit den Überlauf des Zählers auf das 3.Bit hat.>> Besser geht das mit C++ (mit avr-gcc5.3),da bin ich gerade am Erkunden> von C++11/14. Mit etwas variadic template kann man die Bits, die man> hoch/runter zählen will in jeder beliebigen Reihenfolge auf jedem> vorhandenen PORT verteilen.
Das funktioniert doweit, danke.
Aber warum bekomme ich diesen Warnhinweis:
../main.c:104: warning: suggest parentheses around arithmetic in operand
of |
bei der Zeile: OUT_PORT = OUT_PORT & ~(3<<4) | (p<<4);
c-hater schrieb:> Es ist einfach so: ein wirklich Doofer kann einfach nicht erkennen, dass> er doof ist...
...und ein kaltschnäuziger, arroganter Mensch kann einfach nicht
erkennen, daß er NICHT der Nabel der Welt ist.
Auch wenn ich dir hier in der Sache völlig recht gebe, aber deine
Ausdrucksweise macht deiner Mutter klar, daß sie mit deiner Erziehung
auf ganzer Linie völlig versagt hat.
> Aber warum bekomme ich diesen Warnhinweis:>> ../main.c:104: warning: suggest parentheses around arithmetic in operand> of |>> bei der Zeile: OUT_PORT = OUT_PORT & ~(3<<4) | (p<<4);
Weil es sehr schlechter Stil ist, bei Binäroperatoren Klammern
wegzulassen. Deren Präzedenz ist teilweise unintuitiv und führt ohne
Klammern schnell zu Fehlern.
Ich würde übrigens in zwei getrennten globalen Variablen zählen, und aus
den aktuellen Zählerständen dann die Ausgabe auf den Port
zusammensetzen.
holger schrieb:>>Aber warum bekomme ich diesen Warnhinweis:>> ../main.c:104: warning: suggest parentheses around arithmetic in operand>> of |>>>> bei der Zeile: OUT_PORT = OUT_PORT & ~(3<<4) | (p<<4);> Weil da Klammern fehlen.
Ja, aber nicht wie's der Compiler vorschlägt, denn erst muß man die Bits
maskieren (&) und dann den neuen Wert einfügen (|).
@Lokus:
Schreib es so:
1
OUT_PORT=(OUT_PORT&~(3<<4))|(p<<4);
dann versteht es der GCC (und vielleicht auch sonst noch wer)
Rolf M. schrieb:> Es fürt zu undefiniertem Verhalten laut ISO C, da die Variable p zweimal> beschrieben wird, ohne dass ein Sequenzpunkt dazwischen liegt.> Aber wie gesagt, das wurde letztens schon ausführlichst diskutiert.
Sorry, habe diese Diskussion offenbar wohl nicht verfolgt, und weiß auch
nicht, wo/wie ich danach suchen soll.
Ist es nicht so, daß bei einer Zuweisung zuerst der Ausdruck rechts vom
"=" ausgewertet wird, und dann der Wert des Ausdrucks der Variablen
zugewiesen wird? Da sehe ich jedenfalls keinen Raum für Undefiniertes!
Thomas E. schrieb:> Rolf M. schrieb:>> Es fürt zu undefiniertem Verhalten laut ISO C, da die Variable p zweimal>> beschrieben wird, ohne dass ein Sequenzpunkt dazwischen liegt.>> Aber wie gesagt, das wurde letztens schon ausführlichst diskutiert.>> Sorry, habe diese Diskussion offenbar wohl nicht verfolgt, und weiß auch> nicht, wo/wie ich danach suchen soll.
Ich meinte diese hier:
Beitrag "fragezeichen operator may be undefined"
Am Ende von Beitrag "Re: fragezeichen operator may be undefined" hab ich
auch nochmal explizit hingeschrieben, was dazu in der
ISO-C-Spezifikation steht. Die dort angegebenen Beispiele verdeutlichen,
dass es genau um solche Fälle geht.
In der Diskussion haben das einige auch nicht eingesehen, weil sie sich
nicht vorstellen können, warum da was schiefgehen sollte. Das ändert
aber nichts daran. Solche undefinierten Konstrukte hinzuschreiben, ist
wie mit abgefahrenen Reifen rumfahren und zu ignorieren, dass das
gefährlicher und außerdem verboten ist, weil ja noch nie was passiert
ist.
> Ist es nicht so, daß bei einer Zuweisung zuerst der Ausdruck rechts vom> "=" ausgewertet wird, und dann der Wert des Ausdrucks der Variablen> zugewiesen wird?
Das schon, aber nicht definiert ist, wann die Nebeneffekte (also das
Schreiben in die Variable) abgeschlossen ist.
Das mit dem Modulo muß man natürlich für Zähler bis 2hochN -1 nicht
machen.
1
...
2
u=(u+1)&((1<<2)-1);
3
...
4
d=(d-1)&((1<<2)-1);
5
...
Damit zählt man Modulo 4 hoch/runter.
Ich habe mit Absicht stehen gelassen, wie es zur magischen Zahl 3 kommt.
In konkreten Programm sollt man da #define's benutzen (oder bessere
Nachfolger).
Denn eventuell will man mal 3Bit Zähler, die auf 0..2 und 5..7 am Port
erscheinen sollen, umstellen. Was bedeutet dann nochmal 2, 3 und 4?
noch eine Frage dazu. ich rufe aus der Function noch eine Function auf:
reset()
Das erzeugt mir eine Warnung: ../main.c:75: warning: implicit
declaration of function 'reset'
Die könnte man zwar ignorieren, aber wie macht man es richtig? Drauf
verzichten?
Lokus P. schrieb:> Die könnte man zwar ignorieren, aber wie macht man es richtig?
Man könnte es richtig machen und sie nicht ignorieren. Denkst du, die
Warnung ist ein Scherz? Sieh mal in einem c-Buch nach oder bemühe eine
Suchmaschine. Du bist sicherlich nicht der erste, der diese Warnung
bekommt, also findest du die Auflösung sicher bei einer Suchmaschine...
Rolf M. schrieb:> Ich meinte diese hier: ...
Danke! Habe inzwischen auch noch selbst ein bisschen gegoogled. Dachte,
eine Zuweisung wäre praktisch auch schon ein Sequenzpunkt, ist es aber
dann wohl doch nicht. Man lernt halt nie aus... :)