Hallo zusammen, ich programmiere auf einem dsPIC mit dem C30 Compiler und hier sind sowohl die Bits der SFRs als auch die Ports im Header File als Bitfeld maskiert, sodass man direkt auf ein einzelnes Bit zugreifen kann. Nun möchte ich eben ein solches Bit während der Init auf einen bestimmten Wert setzen, nämlich dem invertierten (oder gegenteiligen) Wert dessen was an einem bestimmten Portpin anliegt --> also in etwa: if (PORTAbits.RA15 == 1) { INTCON2bits.INT4EP = 0; } else { INTCON2bits.INT4EP = 1; } Um dies kürzer schreiben zu können, gibt es drei Varianten, von denen ich gerne wüsste wo der Unterschied liegt, alle funktionieren nämlich einwndfrei, dass Assembly ist allerdings unterschiedlich: a) INTCON2bits.INT4EP = PORTAbits.RA15 ? 0 : 1; b) INTCON2bits.INT4EP = !PORTAbits.RA15; c) INTCON2bits.INT4EP = ~PORTAbits.RA15; Sprich ist der Bitoperator (c) und logische Operator (b) bei einzelnen Bits gleichzusetzten ? Was ist der bessere Stil ? Was würdet ihr verwenden ? Danke und Grüße...
>Was würdet ihr verwenden ?
Möglichkeit #4:
1 | INTCON2bits.INT4EP ^= 1; |
Zu deiner Frage: Der logische Negierungsoperator ! funktioniert zwar bei deiner Anwendung, das ist aber eher Zufall. Vom der Semantik her macht der eigeltich was anderes, und passt nicht zu der Aufgabenstellung. Möglichkeit 1 und 3 sind Geschmachssache. Wenn der Compiler "weiß", das ein Bit nur die Werte 0 oder 1 haben kann, könnte da der selbe Code erzeugt werden, aber vermutlich weiß er das nicht, und dann ist eben eine Prüfung auf 0 bzw 1 etwas anderes, als ein binäres nicht. Oliver
Hallo, zunächst Mal zu deinem Vorschlag: if (PORTAbits.RA15 == 1) { INTCON2bits.INT4EP = 0; } else { INTCON2bits.INT4EP = 1; } das ist im wesentlichen das gleiche wie a) INTCON2bits.INT4EP = PORTAbits.RA15 ? 0 : 1; da das ? eine if Anweisung darstellt. Das ist ganz normaler C-Syntax und du findest im Internet zahlreiche Erklärungen. Beispiel: if(bedingung) { return 1; } else { return 0; } ist in Kurzschreibweise: bedingung ? 0 : 1; wie gesagt, eine C-Referenz hilft dir hier weiter. b) INTCON2bits.INT4EP = !PORTAbits.RA15; hier passiert folgendes: PORTAbits.RA15 ist der Zustand am 15. Pin des PortA. Dieser wird durch ! invertiert. Das ganze wird dann INT4EP zugewiesen. Bei ! handelt es sich um den logischen NICHT-Operator. D.h. wenn du eine Variable (z.B. int var) hast und diese invertierst (also !var). Dann bekommst du den Wert 1 wenn die Variable 0 war und 0 wenn die Variable nicht 0 war. Es handelt sich also nicht um ein Bitweises NICHT. c) INTCON2bits.INT4EP = ~PORTAbits.RA15; hier hast du nun ~. Das ist der Operator für Bitweises NICHT. D.h. bei einer Variable (int var=15) bewirkt ~var den Rückgabewert 4294967280. Zur Erläuterung: ein Integer ist 32-Bit breit. 15 entspricht also 000000000000000000001111b. Nun wird jedes Bit einzeln invertiert: 111111111111111111110000b. Dieser Wert entspricht dezimal 4294967280. b) und c) unterscheiden sich in deinem Fall natürlich nicht, da du Bitmasken verwendest. Am sinnvollsten ist die Verwendung von b oder c, da du hier lediglich 2 Anweisungen ausführts nämlich Invertierung und Zuweisung. Du braucht also genau zwei Takte um die Zeile abzuarbeiten. Bei a handelt es sich um einen Bedingten Sprung der je nachdem was ausgeführt wird 2-3 Takte in Anspruch nimmt. Dann muss noch der Rückgabewert in den Stack gelegt werden und zur nächsten Anweisung gesprungen werden. Das sind dann Pauschal 5-6 Takte. Wenn es dir auf Geschwindigkeit nicht ankommt ist es egal welche Variante du nimmst. Trotzdem sollte man natürlich so optimiert wie möglich Programmieren. b und c finde ich immer noch sehr gut lesbar und deswegen solltest du b oder c verwenden. Welches von beiden kannst du würfeln. Ich hoffe es war Verständlich Stephan
> Möglichkeit #4: > INTCON2bits.INT4EP ^= 1; Passt leider nicht, denn INT4EP soll nicht invertiert werden, sondern soll mit dem Inversen von RA15 gefüllt werden, das ist was anderes. Kann sein, dass das mit XOR irgendwie erledigt werden kann, aber warum um die Ecke denken? Möglichkeit c), das binäre Inverse, ist genau das, was der Frager will. Hat auch den Vorteil, dass es genauso mit Bitmasken funktionieren würde, die breiter als 1 Bit sind. a) und b) ersetzen die Bit-Operation durch eine boolsche. Auch wenn es hier dasselbe Ergebnis liefert: Die Daten werden uminterpretiert, und grundsätzlich kann man dabei (z.B. durch falsche Annahmen) Fehler machen. Darum würde ich das nicht empfehlen. Besser, weil klarer, ist, immer die Operationen zu verwenden, die zur Natur der Daten passen.
> a) und b) ersetzen die Bit-Operation durch eine boolsche. Auch wenn es > hier dasselbe Ergebnis liefert: Die Daten werden uminterpretiert, und > grundsätzlich kann man dabei (z.B. durch falsche Annahmen) Fehler > machen. Darum würde ich das nicht empfehlen. Besser, weil klarer, ist, > immer die Operationen zu verwenden, die zur Natur der Daten passen. Dem Stimme ich natürlich zu. Das folgt dann dem Motto: Bierflasche mit einem öffner aufmachen führt zwar zum gleichen Ergebnis wie mit dem Feuerzeug, fliegt einem das Feuerzeug um die Ohren hat man aber ein Problem.
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.