Forum: Mikrocontroller und Digitale Elektronik Unklarheiten bei einem C Programm


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von xXxPu55YD35TrOyEr69xXx (Gast)


Bewertung
-3 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


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

von xXxPu55YD35TrOyEr69xXx (Gast)


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

von Peter II (Gast)


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

welche sind nicht erklärt?

von xXxPu55YD35TrOyEr69xXx (Gast)


Bewertung
-2 lesenswert
nicht lesenswert
if(ACSR & (1<<ACO))


PORTC |= (1<<DDC0);

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

von Peter II (Gast)


Bewertung
0 lesenswert
nicht 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)


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

von Dr. Ötte (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Warum schreibt man denn

PORTC = (0<<DDC0);

anstelle

PORTC = 0;

von Peter II (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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) (Moderator) Benutzerseite


Bewertung
4 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
1 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
-3 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
-1 lesenswert
nicht 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) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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. (achs)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.