Forum: Mikrocontroller und Digitale Elektronik Unklarheiten bei einem C Programm


von xXxPu55YD35TrOyEr69xXx (Gast)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

xXxPu55YD35TrOyEr69xXx schrieb:
> Ich suche Erklärungen für diese Befehle.

welche Befehle?

ich sehe nur Bitoperationen

http://home.fhtw-berlin.de/~junghans/cref/CONCEPT/bitwise.html

von Matthias Q. (zaphod_beeblebrox)


Lesenswert?

Bist du mit dem Nick auch auf Frauensuche? Kommt bestimmt super an :-)

von xXxPu55YD35TrOyEr69xXx (Gast)


Lesenswert?

Die Operationen sind auf dem Link nicht erklärt. Aber Danke

von Peter II (Gast)


Lesenswert?

xXxPu55YD35TrOyEr69xXx schrieb:
> Die Operationen sind auf dem Link nicht erklärt. Aber Danke

welche sind nicht erklärt?

von xXxPu55YD35TrOyEr69xXx (Gast)


Lesenswert?

if(ACSR & (1<<ACO))


PORTC |= (1<<DDC0);

Ich kenne es sonst nur so hier: DDRB &= ~_BV(PB0)

von Peter II (Gast)


Lesenswert?

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

von xXxPu55YD35TrOyEr69xXx (Gast)


Lesenswert?

Und wenn ich (1<< PB0) schreibe, dann setze ich PB0 doch auf high?

von Dr. Ötte (Gast)


Lesenswert?

Warum schreibt man denn

PORTC = (0<<DDC0);

anstelle

PORTC = 0;

von Peter II (Gast)


Lesenswert?

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.

von xXxPu55YD35TrOyEr69xXx (Gast)


Lesenswert?

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.

von Mikel (Gast)


Lesenswert?

>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:
1
if(ACSR & (1<<ACO))
2
{
3
  PORTC |= (1<<DDC0);
4
}
5
else
6
{
7
  PORTC &= ~(1<<DDC0);
8
}

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Dussel (Gast)


Lesenswert?

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.

von Dussel (Gast)


Lesenswert?

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 ;-)

von Mikel (Gast)


Lesenswert?

>> 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.

von fop (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von Dr. Ötte (Gast)


Lesenswert?

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'

von Peter II (Gast)


Lesenswert?

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 
(=)

von Huh (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von fop (Gast)


Lesenswert?

PB0 ist vermutlich als 0 definiert. Das ergibt
1
(1<<0);
auch
1
1;
genannt. Ein Wert, mit dem nix gemacht wird. Also passiert genau nix.
Ziemlich sinnlos, aber vermutlich gültiges C.

von Dussel (Gast)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

Dussel schrieb:
> Das wage ich auch mal zu bezweifeln.

es ist auch nicht so.
1
#include <stdio.h>
2
3
#define V1 12
4
#define V2 8
5
6
int main() {
7
  int a = V1 + V2;
8
  printf("%d", a );
9
}
10
[c]
11
12
erzeugt nach dem Prä
13
[c]
14
# 6 "test.c"
15
int main() {
16
  int a = 12 + 8;
17
  printf("%d", a );
18
}

von Kurt (Gast)


Lesenswert?

xXxPu55YD35TrOyEr69xXx schrieb:
> Ich suche Erklärungen für diese Befehle.
1
  /* 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!".

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Kurt schrieb:
> Da wird in PORTC das DDC0 (Data Direction Control Bit 0) gesetzt.

Es wird nicht gesetzt, es wird abgefragt.

von Rainer B. (katastrophenheinz)


Lesenswert?

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"

von A. S. (Gast)


Lesenswert?

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.

von Kurt (Gast)


Lesenswert?

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.

von Brummbär (Gast)


Lesenswert?

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.

von Achim (Gast)


Lesenswert?

Brummbär schrieb:
> Oft wird (0<<XYZ) aus optischen Gründen verwendet

Ja, aber in anderen Kontext als im UP. Dort war es entweder falsch oder 
dämlich

von fop (Gast)


Lesenswert?

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.
1
PORTC = (0<<DDC0);

von Kurt (Gast)


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.