Ich suche Erklärungen für diese Befehle.
if(ACSR & (1<<ACO)){
PORTC |= (1<<DDC0);
}
else{
PORTC = (0<<DDC0);
Ich habe das ganze gegoogelt aber nix gefunden.
Kann da jemand kurz helfen?
xXxPu55YD35TrOyEr69xXx schrieb:> if(ACSR & (1<<ACO))>> PORTC |= (1<<DDC0);
und was steht bei dem link?
& AND (UND)
<< Shift Left (Linksschieben
|= OR (ODER)
etwas kombinieren musst du schon selber
xXxPu55YD35TrOyEr69xXx schrieb:> Und wenn ich (1<< PB0) schreibe, dann setze ich PB0 doch auf high?
nein - es ist ja überhaupt keine Zuweisung. PB0 ist eine Konstante und
kann nie gesetzt werden.
Dr. Ötte schrieb:> Warum schreibt man denn>> PORTC = (0<<DDC0);>> anstelle>> PORTC = 0;
Deswegen bin ich ja so irritiert.
Und was soll das Linksschieben bewirken? Wäre mehr als dankbar für ne
kurze Erklärung.
>Warum schreibt man denn>PORTC = (0<<DDC0);>anstelle>PORTC = 0;
Bwiwrkt beides dasselbe, ich weiss auch nicht was das soll.
Falls der Programmierer lediglich das Bit vom dem if Statement wieder
auf 0 setzen wollte, hat er es falsch gemacht, er setzt alle Bits auf
null.
Womöglich wollte der Programmierer folgendes:
Dr. Ötte schrieb:> Warum schreibt man denn>> PORTC = (0<<DDC0);>> anstelle>> PORTC = 0;
Das schreibt man nur dann so, wenn man nicht verstanden hat, daß es
völlig sinnlos ist, Nullen durch die Gegend zu schieben.
Dr. Ötte schrieb:> Warum schreibt man denn>> PORTC = (0<<DDC0);>> anstelle>> PORTC = 0;
Wer tut das? Es bewirkt das Gleiche, wenn der Compiler zumindest ein
bisschen optimiert, aber das untere ist verständlicher.
xXxPu55YD35TrOyEr69xXx schrieb:> Und was soll das Linksschieben bewirken? Wäre mehr als dankbar für ne> kurze Erklärung.
Man nimmt eine 1 (0001) und schiebt die um eine gewisse Anzahl an
Stellen nach links. Bei zwei Stellen wäre das dann 0100. Damit setzt man
das Bit Nummer zwei.
Rufus Τ. F. schrieb:> Das schreibt man nur dann so, wenn man nicht verstanden hat, daß es> völlig sinnlos ist, Nullen durch die Gegend zu schieben.
Ohne Optimierung ergibt das ein paar verschleierte NOP ;-)
>> Das schreibt man nur dann so, wenn man nicht verstanden hat, daß es>> völlig sinnlos ist, Nullen durch die Gegend zu schieben.>Ohne Optimierung ergibt das ein paar verschleierte NOP ;-)
Nope, das gibt nicht mal ohne optimierung NOPs, Konstanten löst bereits
der C-Präprozessor auf.
if(ACSR & (1<<ACO)
Schlumpf Dir mal das Datenblatt des verwendeten Mikrokontrollers. Da
gibt es bestimmt ein Special Function Register (SFR) mit dem schönen
Namen ACSR.
Eines der darin enthaltenen Bits nennt sich ACO.
Was dieses Bit aussagt, findest Du im Datenblatt.
Weiterhin hat Dir ein netter Mensch schon mal was vorbereitet, damit Du
schön bequem auf dieses Bit zugreifen kannst.
Er hat Dir das SFR unter dessen Namen ACSR zugänglich gemacht. Und er
hat ein Define mit der Bitnummer für ACO angelegt. Ist doch toll.
Wenn man also jetzt eine 1 so oft nach links schiebt wie die Bitnummer,
dann hat man danach eine Zahl in der genau nur das Bit mit dieser Nummer
gesetzt ist.
Wenn man so eine Zahl, die man auch Maske nennt, mit einem Wert und
verknüpft, überlebt nur das eine Bit, alle anderen sind danach 0.
Die if-Anweisung hält die Bedingung für wahr, wenn ein Wert ungleich 0
heeraus kommt. Wenn der Wert der Bedingung gleich 0 ist, wird die
Anweisung/der Block, der dem if zugeordnet ist nicht ausgeführt.
kurz gesagt, wenn Bit ACO in ACSR gesetzt...
PORTC = (0<<DDC0);
nicht zu erklären, da blöder Fehler
PORTC &= ~(1<<DDC0);
währe Ihr Preis gewesen.
Mikel schrieb:> Nope, das gibt nicht mal ohne optimierung NOPs, Konstanten löst bereits> der C-Präprozessor auf.
sicher? Ich dachte er rechnet nur bei #ifdef sonst NIE.
Und wenn ich (1<< PB0) schreibe, dann setze ich PB0 doch auf high?
Wenn du den Pin vorher in den Outputmodus geschaltet hast, ja.
BP0 ist als 0 definiert, damit ergibt (1<<BP0)==1=='0b00000001'
Dr. Ötte schrieb:> Und wenn ich (1<< PB0) schreibe, dann setze ich PB0 doch auf high?>> Wenn du den Pin vorher in den Outputmodus geschaltet hast, ja.
nein, es wird überhaupt nicht gesetzt dafür braucht man eine Zuweisung
(=)
Peter II schrieb:> Mikel schrieb:>> Nope, das gibt nicht mal ohne optimierung NOPs, Konstanten löst bereits>> der C-Präprozessor auf.>> sicher? Ich dachte er rechnet nur bei #ifdef sonst NIE.
Wenn du zum Beispiel schreibst: c = 3 + 5;
Dann setzt er eine 8 ein. Der Compiler bekommt die 3 und die 5 niemals
zu sehen.
Huh schrieb:> Wenn du zum Beispiel schreibst: c = 3 + 5;> Dann setzt er eine 8 ein. Der Compiler bekommt die 3 und die 5 niemals> zu sehen.
das schein mein GCC andere Meinung zu sein.
Peter II schrieb:> Huh schrieb:>> Wenn du zum Beispiel schreibst: c = 3 + 5;>> Dann setzt er eine 8 ein. Der Compiler bekommt die 3 und die 5 niemals>> zu sehen.>> das schein mein GCC andere Meinung zu sein.
Das wage ich auch mal zu bezweifeln. Dafür müsste doch der Präprozessor
den Code selber parsen und damit viel mehr 'Intelligenz' haben, als er
eigentlich braucht.
Es kann sein, dass heutige Präprozessoren das können, aber ist das
grundsätzlich oder zumindest normalerweise so?
/* Ist das ACO (Analog Comparator Output) Bit in ACSR (Analog
2
Comparator Control und Status Register) gesetzt? Heißt soviel wie:
3
Hat der Comparator gefeuert?
4
*/
5
if(ACSR&(1<<ACO)){
6
7
8
9
/* Ist vermutlich geballter Schwachsinn. Da wird in PORTC das DDC0
10
(Data Direction Control Bit 0) gesetzt.
11
Nur gehört das DDC0 Bit zum Register DDRC (Data Direction Control
12
Register für PORTC), aber nicht zum PORTC.
13
Wenn der Autor hier schalten wollte, dass Bit 0 von PORTC
14
als Ausgang konfiguriert werden sollte, hätte er DDCR statt
15
PORTC schreiben sollen. Wollte er einfach Bit0 auf high setzen,
16
hätte er besser PC0 statt DDC0 geschrieben.
17
*/
18
PORTC|=(1<<DDC0);
19
}
20
else{
21
22
23
24
/* Wie schon Vorredner geschrieben: gewiss wollte der Autor
25
bloß ein einzelnes Bit löschen, löscht statt dessen aber alle.
26
Ansonsten der selbe irreführende Register- / Bitnamenmix wie oben.
27
*/
28
PORTC=(0<<DDC0);
29
}
Grundsätzlich ist es eine gute Idee lieber mit Namen (Konstanten) statt
mit Zahlen zu arbeiten. Das macht Code leserlicher und verdeutlicht die
Intension. Deswegen schreibt man lieber auch mal (0<<DDC0) statt
einfach nur 0. Denn die 0 alleine kann nicht ausdrücken, dass man
explizit das Data Direction Control Bit gemeint hatte. Ist ein bißchen
wie der Unterschied zwischen "Ey du da, dritter Sohn von neun!" und "Ey,
Klaus!".
Kurt schrieb:> Deswegen schreibt man lieber auch mal (0<<DDC0) statt> einfach nur 0
Dann verrate uns bitte mal, wie du mit dieser sinnfreien 0-Schieberei
einzelne Bits eines Registers löschen willst.
Alles zum Thema 0-Schieberei hat Rufus oben bereits gesagt.
Beitrag "Re: Unklarheiten bei einem C Programm"
Nur zur Klarstellung:
Dem TO ging es wohl nur um die völlig dämliche Zeile
> PORTC = (0<<DDC0);
Die anderen Dinge (Bit abfragen, Bit testen) sind ihm klar.
Die Zeile mit 0<< ist ein bedauerlicher Schreibfehler oder wurde von
einem Bastler durch "probieren" herausgefunden.
Mikel, TO und vermutlich andere haben gepostet, wie man es richtig
macht.
Rufus Τ. F. schrieb:> Kurt schrieb:>> Da wird in PORTC das DDC0 (Data Direction Control Bit 0) gesetzt.>> Es wird nicht gesetzt, es wird abgefragt.
Das bezog sich auf die Zeile
1
PORTC|=(1<<DDC0);
Diese Zeile fragt nichts ab, sondern schaltet PC0 auf high. Zumindest
wenn das DDRC dafür als Ausgang gesetzt ist. Nach Präprozessor und
Optimierung im Compiler wird daraus wohl:
[a]sbi PORTC, 0;[/a]
Rainer B. schrieb:> Kurt schrieb:>> Deswegen schreibt man lieber auch mal (0<<DDC0) statt>> einfach nur 0> Dann verrate uns bitte mal, wie du mit dieser sinnfreien 0-Schieberei> einzelne Bits eines Registers löschen willst.> Alles zum Thema 0-Schieberei hat Rufus oben bereits gesagt.
Da wird ja nicht wirklich was geschoben. Dass es sinnfrei ist Nullen zu
shiften weiß auch der Compiler und optimiert das weg. Aber der Schreiber
/ Leser des Codes kann so ausdrücken um welches Bit es ihm geht. Und
genau diese hier so oft gescholtene, müffelige Zeile zeigt den Grund,
warum das vorteilhaft ist:
1
PORTC=(0<<DDC0);
So kann man schon beim Lesen des Codes erkennen, dass der Autor hier mit
99% Sicherheit einen Fehler gemacht hat: alle 8 Bits statt nur Bit0 zu
löschen. Hätte er nur
1
PORTC=0;
geschrieben, wäre man davon ausgegangen, dass das Absicht und kein
Fehler war. Die Pseudo-Bitshifterei dient einzig dem Zweck die Intension
im Code zu formulieren.
Oft wird (0<<XYZ) aus optischen Gründen verwendet (ja, ein Quellcode
sollte auch schön und lesbar sein).
Beispiel
A = (1<<AX5) | (0<<AX4) | (1<<AX3) | (1<<AX2) | (0<<AX1);
Natürlich sind die ganzen (0<<AX) vom Code her sinnlos.
Das hat aber eine andere Aussage als
A = 0b10110;
Ein Quellcode ist nicht für den Computer, sondern für den Menschen
gedacht.
Ich lese einen optisch schönen und sauberen Code lieber, als zusammen
gequetschten Wirrwar ohne Kommentare. Ist der Code aber gut genug,
braucht man keine Kommentare.
Man muss also nicht alles verteufeln, was für den Computer sinnlos ist.
So lasse ich mir das gefallen, da sieht man, welche Bits gesetzt sind,
und kann es schnell ändern. Ok, wenn es ein Byte ist, werden 3 weitere
Bits kommentarlos auf 0 gesetzt.
1
A=(1<<AX5)|(0<<AX4)|(1<<AX3)|(1<<AX2)|(0<<AX1);
Aber bei dem folgenden Ausdruck macht man dem eiligen Leser weiss, hier
würde nur Bit DDC0 geändert. In Wirklichkeit wird aber das komplette SFR
PORTC auf 0 gesetzt. Ein Quell der Freude, wenn man mal DDC1 benutzt und
puff ist es 0 und niemand weiss warum. Da finde ich es klarer = 0 zu
schreiben.
Hihi, es ist ja noch schlimmer. In der 'Bitmaske' wird DDC0 (ein Bit aus
DDRC) genannt, aber gelöscht wird PORTC - also die Bits PC0..PC7.
fop schrieb:> Ein Quell der Freude, wenn man mal DDC1 benutzt und> puff ist es 0 und niemand weiss warum.
DDC1 wird von dem Code nicht berührt. Aber wenn Du eigentlich PC1
meinst, dann hast Du voll Recht! Auf jeden Fall ist in der Zeile ein
Schaf das knurrt und bellt, egal wie unschuldig es auszusehen versucht.