Forum: Compiler & IDEs PORTB=((wert/ten[digit])%10)|(16<<digit); verständnisproblem


von Matthias R. (recki)


Lesenswert?

// PORTB initialisiert für LEDs
int wert; // darzustellende Zahl
int digit=0; // aktuelle Stelle
int ten[]={1,10,100,1000};
while(1)
{
  PORTB=((wert/ten[digit])%10)|(16<<digit);  was bewirkt %10 und 
16<<digit ??
  digit=(digit+1)&3;                         was macht &3 ???
  ... was anderes sinnvolles tun
  _delay_ms(10);
}

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

Dazu empfehle ich dir folgende Übersicht:

http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B

und folgende Lektüre:

Bitmanipulation

von Oh man (Gast)


Lesenswert?

Mittlerweile solltest du herausgefunden haben,
dass das "%10" den ganzzahligen Rest der Division von dem Wert von 
"(wert/ten[digit])" durch 10 zurückgibt und dass
"16<<digit" bedeutet, dass die Zahl 16 (binär Dargestellt; also alle 
vorkommenden Einser) um die Anzahl an Stellen die als Zahlenwert in 
digit abgespeichert wurden, nach links verschoben wird.

Ohne jetzt nochmal nachgesehen zu haben sollte das so stimmen. Hoffe ich 
zumindest. ;D Ansonsten korrigiert mich bitte.

von Oh man (Gast)


Lesenswert?

Also, jetzt merk ich doch so langsam, dass son Studium doch zu was 
nützlich ist ;)

von Rolf Magnus (Gast)


Lesenswert?

Also ich hab bezüglich C-Programmierung im Studium nichts gelernt, außer 
daß es auch Professoren gibt, die nicht wirklich Ahnung von dem haben, 
was sie vorlesen. Hätte ich C nicht schon vorher gekannt, dann hätte ich 
den Unsinn auch noch geglaubt, den der verzapft hat.

von Mic M. (radbruch)


Lesenswert?

Hallo

Ein Versuch:

Vermutlich ist das eine 4-segmentige Anzeige, Bit4-7 wählt das Segment 
und Bit0-3 die darzustellende Ziffer. Bei jedem Durchgang der 
Hauptschleife wird die Ziffer in nur einem Segment angezeigt. Die Nummer 
des aktuellen Segments wird in digit gespeichert, der Wert für digit 
geht deshalb von 0 bis 3 bzw. reichen die Bits 0 und 1 um die 
Segmentnummer zu speichern. Deshalb wird bei jedem Durchgang digit 
erhöht und auf zwei Bits reduziert:

digit=(digit+1)&3;

Der Rest ist etwas komplizierter. Da immerhin auch auf 1000 geprüft 
wird, vermute ich, Wert hat zumindest 16-Bit oder mindestens 5 dezimale 
Stellen. Dazu reicht eine 4-stellige Anzeige nicht. Deshalb werden die 
Einer auf einem zusätzlichen 5. Segment angezeigt und an einem anderen 
Port ausgegeben. Die Ziffern der Zehner bis 10000er-Stellen:

wert/ten[digit])%10: Wert/ten[digit] erzeugt die Ziffer, %10 kürzt die 
Einer-Stelle weg. Dann steht in den Bits 0-3 die jeweilige Ziffer für 
Segment 1-5. Am PortB wird dann die jeweilige Ziffer in Bit 0-3 und das 
Segment mit |(16<<digit) in Bit 4-7 ausgegeben. Sehr clever gemacht.

Gruß

mic

von Matthias R. (recki)


Lesenswert?

Ja das hilft mir doch schonmal weiter.
Es ist nur keine 4 segmentanzeige sondern eine 7 die nur über einen 
decoder mit dem bcd code angesteuert wird. Ich finden das auch gut 
gemacht deshalb will ich es auch gerne nutzen nur bis jetzt weiß ich 
noch nicht wie ich die meine werte darein bekomme. Die soll ich ja laut 
kommentar in die variable wert ablegen oder ? kann ich dann aus dem wert 
nen array machen und da meine zahlen ablegen und da dann ne zählschleife 
vorpacken??

von MWS (Gast)


Lesenswert?

Mic M. schrieb:
> Der Rest ist etwas komplizierter. Da immerhin auch auf 1000 geprüft
> wird, vermute ich, Wert hat zumindest 16-Bit oder mindestens 5 dezimale
> Stellen. Dazu reicht eine 4-stellige Anzeige nicht.

Wieso das denn ?

4 Stellen: 9999

PORTB=((wert/ten[digit])%10)|(16<<digit);
PORTB=((9999/ten[3])%10)|(16<<3);
PORTB=((9999/1000)%10)|(B10000000);
PORTB=(9 %10)|(B10000000);
PORTB=9|B10000000;
PORTB=B10001001;

> digit=(digit+1)&3;

Einfach ein Zähler von 0-3.

Mic M. schrieb:
> %10 kürzt die Einer-Stelle weg.

Das kürzt sie nicht weg, das lässt sie über.

von Matthias R. (recki)


Lesenswert?

Ja wenn der wert 9999 und ten[3]
bekomme ich an Port PORTB=B10001001;
an meinem Port raus richtig?
aber der werd soll ja meine Zahl sein also wenn ich jetzt da 3333 
reinschreib bekomm ich dann B10000011 raus oder wie? macht der das dann 
auch 0000 mit der ich dann B10000000 bekommen?

Ich möchte gerne ja gerne in die BITs 0-3 meine BCD-code für die 
anzeigen schreiben.
 Sry ich versteh das schwer bin halt noch in den anfängen

von MWS (Gast)


Lesenswert?

Matthias R. schrieb:
> also wenn ich jetzt da 3333 reinschreib bekomm ich dann B10000011

Das bekommst Du, wenn digit = 3 ist.

Es dürfte sich bei diesem Code um die Adressierung für eine 
gemultiplexte Anzeige handeln, die unteren 4 Bits gehen an einen 
BCD-7Segment Decoder, die oberen 4 Bits an die Spaltentreiber.

Matthias R. schrieb:
> macht der das dann auch 0000 mit der ich dann B10000000 bekommen?

Wenn ich dieses Ausländisch richtig verstehe, ja.

Der Code holt aus "wert" jeweils eine Stelle raus, welche davon wird 
durch "digit" bestimmt, und schreibt sie auf die unteren 4 Bits des 
Ports. Gleichzeitig wird der richtige Spaltentreiber über die oberen 4 
Bits gesetzt.

von Volkmar D. (volkmar)


Lesenswert?

Und da dies in einer Endlosschleife läuft wird bei jedem 
Schleifendurchlauf die nächste Stelle angesteuert (durch 
"digit=(digit+1)&3;") und nach 4 Durchläufen geht es wieder von vorne 
los.

Und das Delay in der letzten Zeile bewirkt das jedes Digit für 10ms 
angezeigt wird, d.h. die Wiederholrate liegt bei 25Hz.

von Matthias R. (recki)


Lesenswert?

MWS schrieb:
> Der Code holt aus "wert" jeweils eine Stelle raus, welche davon wird
> durch "digit" bestimmt, und schreibt sie auf die unteren 4 Bits des
> Ports. Gleichzeitig wird der richtige Spaltentreiber über die oberen 4
> Bits gesetzt.

Ok das heißt wenn mein wert 1234 hat sollten meine Azeige 4 
Siebensegmentanzeige auch 1234 anzeigen?
Wenn ich das richtig verstehe wird die Variable wert durch digit 4 mal 
ausgelesen und hintereinander mit dem passenden Spaltentreiber die zahl 
in die unteren 4 BITs geschrieben.

Also wäre dann 1 meine tausender
               2 meine hunderter
               3 meine zehner
               4 meine einer

Oder versteh ich das jetzt ganz falsch?

von Volkmar D. (volkmar)


Lesenswert?

Richtig, siehe mein vorhergehendes Posting.

von MWS (Gast)


Lesenswert?

Matthias R. schrieb:
> Ok das heißt wenn mein wert 1234 hat sollten meine Azeige 4
> Siebensegmentanzeige auch 1234 anzeigen?

Ja.

> Wenn ich das richtig verstehe wird die Variable wert durch digit 4 mal
> ausgelesen und hintereinander mit dem passenden Spaltentreiber die zahl
> in die unteren 4 BITs geschrieben.
>
> Also wäre dann 1 meine tausender
>                2 meine hunderter
>                3 meine zehner
>                4 meine einer

Wenn Du mit "1" den Portpin 4 meinst, dann ja. Das Ergebnis sieht z.B. 
so aus:

wert = 1234   digit 0,1,2,3,0,1,2,3, usw.

Port = B00010100
Port = B00100011
Port = B01000010
Port = B10000001
Port = B00010100
Port = B00100011
Port = B01000010
Port = B10000001
usw.

von MWS (Gast)


Lesenswert?

MWS schrieb:
> Wenn Du mit "1" den Portpin 4 meinst, dann ja. Das Ergebnis sieht z.B.
> so aus:

Korrektur, das wäre nicht 4, sondern 7 und die Zählweise geht anders 
rum:

Matthias R. schrieb:
> Also wäre dann 1 meine tausender
>                2 meine hunderter
>                3 meine zehner
>                4 meine einer

digit 3 = Tausender = Portpin 7
digit 2 = Hunderter = Portpin 6
digit 1 = Zehner = Portpin 5
digit 0 = Einer = Portpin 4

Der Rest den ich schrieb ist ok.

von Matthias R. (recki)


Lesenswert?

Ja danke ich habs auch verstanden so meinte ich das auch hab mich vll 
nur ein bissle falsch ausgedrückt.
Danke für die ganzen infos.

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.