Hallo zusammen,
ich habe für mein Projekt bisher einen Arduino benutzt, da ich dort
langsam sehr gut zurecht gekommen bin, wollte ich den Umstieg auf einen
Atmega wagen.
Da ich kein gelernter C Programmierer bin und Arduino die Programmierung
ja wie ich nun gesehen habe relativ einfach gestaltet hat. Habe ich
einige fragen, ich denke es sind einfach so ein paar
Grundverständnisfragen zur Programmierung in C, sind diese gelöst, komme
ich glaube ich auch selbstständig gut weiter.
Ich habe zuerst mit einem simplen Blink programm angefangen.
1
// Testprogramm: Blinken auf Pin PC0
2
//
3
#ifndef MCU // Welcher AVR genutzt wird, wird i.A. im Makefile definiert
4
#define MCU atmega32
5
#endif
6
7
#ifndef F_CPU // kann auch im Makefile definiert sein
8
#define F_CPU 8000000UL // Takt als LONG definieren, da zu groß für Integer
9
#endif
10
11
#include <avr/io.h> // Namen der IO Register
12
#include <util/delay.h> // Funktionen zum warten
13
// Achtung, damit delay richtig funktioniert muß mit Optimierung compiliert werden
14
15
int main(void)
16
{
17
DDRC = _BV(0); // Nur PC0 als output, _BV(0) = (1<<0) = 1
18
PORTC = 254; // Pullups auf allen anderen Pins
19
20
while (1)
21
{
22
PORTC &= 255-_BV(0); // 0 auf Bit 0 Ausgeben, Rest so lassen
23
_delay_ms(500); // 100 ms Warten
24
PORTC |= _BV(0); // 1 auf Bit 0 Ausgeben, Rest so lassen
25
_delay_ms(500);
26
}
27
}
Hier stellen sich für mich jedoch schon die ersten fragen die im
Tutorial nicht richtig erläutert wurden.
1
#include <avr/io.h>
Ich habe mir die io.h mal angeschaut, diese verweist ja eigentlich nur
auf die einzelnen AVR's. Da ich den Atmega32A habe, kann ich dann auf
diese Zeile verzichten ?
1
#define MCU atmega32
und dafür statt
1
#include <avr/io.h>
1
# include <avr/iom32a.h
einsetzen?
Wenn ich das richtig verstanden habe dient das define MCU ja nur der
definierung für die io.h oder?
Frage 2:
1
DDRC = _BV(0); // Nur PC0 als output, _BV(0) = (1<<0) = 1
2
PORTC = 254; // Pullups auf allen anderen Pins
DDRC = _BV(0); // Diese Zeile versteh ich leider garnicht, warum
verweist das DDRC auf PC0 ?
Bzw nehme ich an das DDRC auf Port C verweißt und _BV(0) und die 0 auf
meinen jeweiligen PIN, stimmt das? Wofür steht dann das _BV?
PORTC = 254; versteh ich ebenfalls nicht, wie kommt es dazu das die
Pullups auf allen anderen pins reingeschaltet werden?
Oder ist das nur auf Port C? Wenn es nur Port C wäre, kann meine
vermutung das DDRC auf Port C verweist ja nicht stimmen...
und wofür steht die 254?
1
PORTC &= 255-_BV(0); // 0 auf Bit 0 Ausgeben, Rest so lassen
2
_delay_ms(500); // 100 ms Warten
3
PORTC |= _BV(0); // 1 auf Bit 0 Ausgeben, Rest so lassen
4
_delay_ms(500);
PORTC &= 255-_BV(0);
Das müsste ja die kurzfassung von
PORTC = PORTC & 255-_BV(1); sein oder?
was wiederum Bitmanipulation sein müsste?! Doch was genau tut diese? und
wie kommt es dazu das dadurch mit Pin 0 auf 0 gesetzt wird?
PORTC |= _BV(0) ist eine invertierung oder? Die 0 wird somit auf die 1
gedreht wenn ich das richtig verstehe oder?
Um die beantwortung einfacher zu gestalten, habe ich meine Fragen hier
nocheinmal versucht zusammen zu fassen:
Frage 1: Kann ich anstelle von <avr.io.h>und define MCU atmega32 nur
ein<avr/iom32a.h>setzen?
Frage 1.1: das define MCU, wird das nur für die definierung benötigt
damit <avr.io.h> weiß welchen AVR ich nutze? Oder dient diese
definition noch einem anderen Zweck?
Frage 2: verweist DDRC auf Port C? Wenn nicht, worauf dann?
Frage 2.1: Was bewirkt _BV(0); genau?
Frage 2.1.1 : Steht die 0 in _BV(0) für die Pin Nummer?
Frage 2.2 : Verweißt PORTC nur auf den Port C?
Frage 2.2.1: Wofür steht die 254?
Frage 2.2.1.1: Wenn die 254 für etwas bestimmtes steht, wo finde ich
ein entsprechendes Nachschlagewerk was mir erläutert, welche zahl für
was steht?
Frage 3: Ist PORTC &= 255-_BV(0); die kurzfassung von PORTC = PORTC &
255-_BV(1);
Frage 3.1: Was macht diese Bitmanipulation? Und wie kommt es dazu das
dadurch der pin auf 0 gesetzt wird?
Frage 3.2: Ist PORTC |= _BV(0) eine Invertierung, die dafür sorgt das
die 0 zur 1 wird?
Ich danke euch im voraus vielmals für eure Hilfe, solltet ihr an der ein
oder anderen Stelle der Meinung sein, mensch das steht doch dort in
diesem Tutorials, sendet mir einfach nen link, dann arbeite ich mir das
auch selber raus. Problem war nur das ich bisher trotz google relativ
ratlos dasteh...
Beste Grüße
Martin
Martin Kathke schrieb:> #ifndef MCU // Welcher AVR genutzt wird, wird i.A. im> Makefile definiert
Nicht i.A., sondern nur da.
Der Compiler muß wissen, wofür er compilieren soll. Im Quelltext ist es
zu spät.
Auch das F_CPU-Gerödel schmeiß raus, das gehört nicht in den Quelltext.
F_CPU auch nur im Make definieren.
Und diese #ifdefs gewöhn Dir schleunigst ab, die taugen nur, um sich
sauber ins Knie zu schießen.
> Und diese #ifdefs gewöhn Dir schleunigst ab, die taugen nur, um sich> sauber ins Knie zu schießen.
Nicht, wenn man sie richtig benutzt. Hier z.B. so:
Hallo Martin
Vorne weg: Ich programmiere sonst eher PIC's, kenne mich mit Atmel nicht
sonderlich gut aus. Daher keine Garantie für die Antworten.
Martin Kathke schrieb:> Frage 2: verweist DDRC auf Port C? Wenn nicht, worauf dann?
Mit einem Blich in das Datenblatt des entsprechenden Controllers hättest
du das bestimmt auch alleine gelösst bekommen.
DDRC = Data Direction Register C
Mit diesem Register kannst du einen PIN des PORT C entweder als Eingang
oder als Ausgang definieren. Passend dazu gibt es natürlich DDRA für
PORT A, DDRB für PORT B und so weiter.
Auszug aus dem Datenblatt:
"The DDxn bit in the DDRx Register selects the direction of this pin. If
DDxn is written logic one,
Pxn is configured as an output pin. If DDxn is written logic zero, Pxn
is configured as an input
pin."
Martin Kathke schrieb:> Frage 2.1: Was bewirkt _BV(0); genau?
Das kommt von deinem Compiler. Definiert dürfte das ganze in der
avr-libc header sein.
1
#define _BV(bit) (1 << (bit))
Ich denke, somit dürfte sich der Befehl von alleine erklären. ;)
Martin Kathke schrieb:> Frage 2.1.1 : Steht die 0 in _BV(0) für die Pin Nummer?
Ja und nein. Die 0 bzw. die 1 die dort stehen würde steht lediglich für
den Wert des Bits, welchen du an irgendeine Variable / Register zuweisen
willst.
1
DDRC=_BV(0);// Nur PC0 als output, _BV(0) = (1<<0) = 1
An dieser Stelle vermute ich einen falschen Kommentar. Eher passen
würde:
// Nur PC0 als input
Somit würde nämlich die darauffolgende Zeile auch wieder mehr sinn
machen:
1
PORTC=254;// Pullups auf allen anderen Pins
Da ein Port in diesem Falle aus 8 Bits besteht und 254 einem Binärwert
von "1111 1110" entspricht, gäbe dies durchaus sinn. Ganz sicher bin ich
mir da aber auch nicht.
Martin Kathke schrieb:> Frage 2.2 : Verweißt PORTC nur auf den Port C?
Ja.
Martin Kathke schrieb:> Frage 2.2.1: Wofür steht die 254?> Frage 2.2.1.1: Wenn die 254 für etwas bestimmtes steht, wo finde ich> ein entsprechendes Nachschlagewerk was mir erläutert, welche zahl für> was steht?
Wie oben beschrieben. Wenn es darum geht eine Dezimalzahl aus einem Port
auszugeben, musst du immer Binär denken.
1
// Alle diese Befehle machen genau das selbe!
2
PORTC=255;// Dezimale Schreibweise
3
PORTC=0xFF;// Hexadezimale Schreibweise
4
PORTC=0b11111111;// Binäre Schreibweise
Das Tool hier wird dir bei solchen Anwendungen helfen:
http://www.langeneggers.ch/nuetzliches/umrechner-hex-dez.html
Die letzten Fragen lasse ich mal offen, ich denke das hier zu erklären
wäre verschwendete Zeit, denn dafür gibt es Zahlreiche Informationen im
Internet. Habe dir hier mal ein paar Links zusammengetragen:
http://de.wikibooks.org/wiki/C-Programmierung:_Ausdr%C3%BCcke_und_Operatorenhttp://www.mikrocontroller.net/articles/Bitmanipulationhttp://www.c-howto.de/tutorial-variablen-bitmanipulation.html
Gut möglich dass da das ein oder andere mal das selbe steht. Sind nur
gerade die Google einträge, die mir ins Auge schossen, da ich die Seiten
selbst auch kenne und damit gelernt habe.
Im allgemeinen Rate ich dir zu folgendem: Beginne noch einmal mit der
"Basis." Es ist super, dass du den Umstieg von Arduino auf, nennen wir
es richtige mikrocontroller machen willst. Wenn ich mir deinen Code
ansehe, machst du dir das Leben aber selbst zu kompliziert. Gerade diese
ganzen _BV Befehle könntest du Problemlos anders schreiben. Kaum einer
schreibt seinen Code noch auf diese Art und Weise.
Ich hoffe ich konnte dir ein wenig weiterhelfen.
Gruss
Hey Leute,
also ich glaube ich bin habs größtenteils verstanden, jetzt wollte ich
mir aber ne funktion schreiben mit der ich meine pins direkt ansteuern
kann und habs so versucht
1
#ifndef MCU // Welcher AVR genutzt wird, wird i.A. im Makefile definiert j
2
#define MCU atmega32
3
#endif
4
5
#ifndef F_CPU // kann auch im Makefile definiert sein
6
#define F_CPU 8000000UL // Takt als LONG definieren, da zu groß für Integer
Ist das der komplette Code?
Funktioniert denn das PORTC = 0xFF ?
Falls nicht, bzw auch wenn es funktioniert, solltest du die DDRC
Register mal Konfigurieren. Solltest schon deklarieren ob die Pins Ein
oder Ausgänge sind.
spess53 schrieb:> Wenn das JTAG-Interface aktiv ist, nicht.>> MfG Spess
Ist wenn ich mich recht erinnere Standartgemäss aktiviert, oder?
Dann müsstest das Teil vielleicht auch ausschalten.
Hey Leute,
ich hoffe es ist in Ordnung das ich den Thread hier hin und wieder
nochmal aufkommen lasse,
also ich habe nen merkwürdigen fehler,
ich habe die oben schon geschriebene funktion. 2 Leds und ein taster,
taster gedrückt = Led 2 an Led 1 aus
taster nicht gedrückt = Led 2 aus Led 1 an.
Soweit sogut,
LED 1 liegt an PC1 an led 2 eigentlich PC 2
das ganze funktioniert bei mir aber auf Port C pin 2&3 nicht (
weiterhoch habe ich nicht ausprobiert) jedoch funktioniort die Funktion
ohne Probleme wenn ich die LED 2 an port a schalte (da gehen auch pin 2
&3 )
vill sieht ja jmd den fehler,
oder habe ich mir vill pins vom meinem atmega zerschossen?
1
int pinWrite(uint8_t portnr, uint8_t pin, uint8_t val) // Pin HIGH oder LOW
Dein "Programmierstil" wenn man diesen Saustall so nennen darf, ist
grausig. Willst du nicht mal daran arbeiten? Guck dir mal ordentliche
Programme an und vergleiche die mit deinem.
1.) diese vielen if-konstrukte durch switch oder besser durch
Arrayzugriffe ersetzen. Am besten den ganzen Ansatz überdenken. Was soll
dir deine pinWrite bringen? Deren Funktionalität kannst du direkt
abbilden. Kapsele lieber höhere Funktionalität mit sprechenden Namen.
Also eine Funktion tueDiesUndDas();
Diese low-level-pseudo-abstraktion bringt gar nichts.
2.) Symbolische Bitnamen verwenden
3.) Sinnvole Variablennamen
4.) Konstanten mit define sinnvoll benenen
5.) Entscheide dich, entweder (1<<BIT) oder _BV(BIT). Warum mischst du
das? Je nach Laune, Tageszeit, Temperatur, Zufall? Wann nutzt du was?
Dann kannst du am Ende auch irgendwann sinnvoll auf Fehlersuche gehen.
In diesem Krautsalat macht das keinen Sinn.
cyblord ---- schrieb:> Dein "Programmierstil" wenn man diesen Saustall so nennen darf, ist> grausig. Willst du nicht mal daran arbeiten? Guck dir mal ordentliche> Programme an und vergleiche die mit deinem.>> 1.) diese vielen if-konstrukte durch switch oder besser durch> Arrayzugriffe ersetzen. Am besten den ganzen Ansatz überdenken. Was soll> dir deine pinWrite bringen? Deren Funktionalität kannst du direkt> abbilden. Kapsele lieber höhere Funktionalität mit sprechenden Namen.> Also eine Funktion tueDiesUndDas();> Diese low-level-pseudo-abstraktion bringt gar nichts.>> 2.) Symbolische Bitnamen verwenden>> 3.) Sinnvole Variablennamen>> 4.) Konstanten mit define sinnvoll benenen>> 5.) Entscheide dich, entweder (1<<BIT) oder _BV(BIT). Warum mischst du> das? Je nach Laune, Tageszeit, Temperatur, Zufall? Wann nutzt du was?>>> Dann kannst du am Ende auch irgendwann sinnvoll auf Fehlersuche gehen.> In diesem Krautsalat macht das keinen Sinn.
Mein "Programmierstil" ist keine Woche alt, daher sieht er
wahrscheinlich einfach noch aus wie sau, da bevor ich ihn schick machen
kann ihn erstmal richtig verstehen muss ;)
1) meine pinwrite funktion habe ich mir geschrieben, weil ich von
arduino komme, fürs verständnis wollte ich es hinbekommen eine funktion
zu schreiben die einen einzelnen pin an und auschalten kann.
Wo liegt deiner meinung nach der vorteil von switch? ist etwas kürzer,
aber ansonsten seh ich da keinen Vorteil.
2) ok
3) gut normalerweise mache ich das aber bei einer variablen und einem
"ich probiere das jetzt einfach mal aus Code" war mir das relativ egal.
4) Alles klar
5) Ich bin wiegesagt neu in der Materie und wollte beide möglichkeiten
anwenden um dafür ein "gespür" zu bekommen
@spess nein noch nicht, mache ich mal
//edit
JTAG ausgemacht, jetzt funktionierts ;)
Martin Kathke schrieb:> Wo liegt deiner meinung nach der vorteil von switch? ist etwas kürzer,> aber ansonsten seh ich da keinen Vorteil.
Es wird übersichtlicher. Viel übersichtlicher.
zudem besteht ein kleiner Unterschied zwischen If/else und einer Switch
case abfrage: Während bei einer If/Else Abfrage beliebig viele boolsche
Ausdrücke geprüft werden können, wird bei einer Switch Case immer nur
GENAU der Ausdruck in der Klammer geprüft.
Zudem wage ich es mal zu behaupten, ein Compiler wandelt den Switch-Case
Code besser um als eine If/Else Abfrage, da er weiss dass immer die
selbe Variable geprüft wird. (Korrigiert mich, falls falsch!)
Gruss
Martin Kathke schrieb:> Mein "Programmierstil" ist keine Woche alt, daher sieht er> wahrscheinlich einfach noch aus wie sau, da bevor ich ihn schick machen> kann ihn erstmal richtig verstehen muss ;)
Die Sache ist die, das du im Grunde jetzt schon versuchst, ihn 'schick
zu machen. Denn wenn du das nicht versucht hättest, dann hättest du
geschrieben
1
intmain()
2
{
3
DDRC=(1<<PC1)|(1<<PC2);
4
5
PORTC|=(1<<PC0);// Pullup am Taster einschalten
6
7
while(1)
8
{
9
if(PINC&(1<<PC0))
10
{
11
PORTC&=~(1<<PC1);
12
PORTC|=(1<<PC2);
13
}
14
else
15
{
16
PORTC|=(1<<PC1);
17
PORTC&=~(1<<PC2);
18
}
19
}
20
21
return0;
22
}
und hättest die Funktion pinWrite überhaupt nicht gebraucht.
Um das ein wenig 'schöner' zu machen, musst du in die richtige Richtung
gehen. Der Schlüssel für die richtige Richtung ist nicht die Funktion
pinWrite, sondern die Beobachtung, dass du die Pinnummern nicht direkt
im Code stehen haben willst, sondern an einer Stelle 'sammeln' willst.
An dieser Stelle kommt dann der Präprocessor ins Spiel, der dir eine
Textersetzung vornehmen kann, so dass du in deinem Code die Pinnummern
nicht direkt im Code stehen hast, der eigentliche C Compiler das aber
genau so präsentiert bekommt, weil der Präprozessor die entsprechenden
Texte ersetzt hat
1
#define LED1 PC1
2
#define LED2 PC2
3
4
intmain()
5
{
6
DDRC=(1<<LED1)|(1<<LED2);
7
8
PORTC|=(1<<PC0);// Pullup am Taster einschalten
9
10
while(1)
11
{
12
if(PINC&(1<<PC0))
13
{
14
PORTC&=~(1<<LED1);
15
PORTC|=(1<<LED2);
16
}
17
else
18
{
19
PORTC|=(1<<LED1);
20
PORTC&=~(1<<LED2);
21
}
22
}
23
24
return0;
25
}
Und was mit den Pinbezeichnungen funktioniert, an denen die LEDs hängen,
funktioniert genausogut mit der kompletten Portbezeichnung ('PORTC'),
die man per Präprozessor abstrahieren kann, so dass sie nur noch in Form
eines #define auftaucht und im Programmierer-lesbaren Code nicht mehr
vorkommt.
1
#define LED_DDR DDRC
2
#define LED_PORT PORTC
3
#define LED1 PC1
4
#define LED2 PC2
5
6
intmain()
7
{
8
LED_DDR=(1<<LED1)|(1<<LED2);
9
10
PORTC|=(1<<PC0);// Pullup am Taster einschalten
11
12
while(1)
13
{
14
if(PINC&(1<<PC0))
15
{
16
LED_PORT&=~(1<<LED1);
17
LED_PORT|=(1<<LED2);
18
}
19
else
20
{
21
LED_PORT|=(1<<LED1);
22
LED_PORT&=~(1<<LED2);
23
}
24
}
25
26
return0;
27
}
Mit dem Schalter kann man genau das gleiche machen, und so das Programm
immer weiter verbessern, ohne dass man sich hier seltsam zu benutzende
Funktionen schreiben muss, bei denen man jedesmal wieder aufs neue
nachsehen muss, welcher der 3 Werte jetzt was bedeutet und bei denen man
durch das ganze Programm gehen muss, um alle Aufrufe zu finden die
angepasst werden müssen, wenn die LED auf einen anderen Port 'umziehen'.
Hier, mit den #define, brauchst du nicht viel machen. Sollen die LED auf
den PORTA, und zwar auf die Pins 4 und 7, dann passt du einfach die
#define an
1
#define LED_DDR DDRA
2
#define LED_PORT PORTA
3
#define LED1 PA4
4
#define LED2 PA7
und den Rest macht der Präprozessor. Und zwar quer durchs ganze
Programm, so dass du dich nicht zum Bleistift nicht mehr darum kümmern
musst, dass die LED bei den beiden Schalterstellungen gegenläufig
leuchten sollen. Du stellst in den #define nur noch ein, an welchen Pins
an welchem Port die LED angeschlossen sind. Der Präprozessor verteilt
diese Information dann im kompletten Programmtext, in dem er den Text
'LED1' durch den jeweils von dir angegebenen anderen Text 'PA4' ersetzt,
welcher dann durch den C Compiler geht.
Programmtext schön zu machen ist schon ok. Aber in deinem Fall
verschleierst du mit der Funktion viel zu viel ohne dafür etwas zu
kriegen.
> 1) meine pinwrite funktion habe ich mir geschrieben, weil ich von arduino komme,
Ja. Und die Funktion ist auch auf dem Arduino schon scheiße. Viel zu
langsam.
Zumal deine pinWrite Funktion noch nicht mal ein müder Abklatsch der
digitalWrite eines Arduino ist. Bei digitalWrite muss ich mir keine
Gedanken machen, welcher Port zu einer Nummer gehört, die auf der
Klemmleiste aufgedruckt ist, digitalWrite findet das selber raus. Bei
dir hingegen muss ich in pinWrite erst recht wieder den Port angeben.
Ich hab dadurch also nichts gewonnen, ausser das die eigentliche Absicht
verschleiert wird.
digitalWrite hat auf einem Ardunio schon seine Berechtigung, vor allem
in Hinblick darauf, sich damit von einer bestimmten Architektur zu
lösen. Wenn du der Funktion aber die Fähigkeit klaust, die Pin-Nummern
einfach von 0 beginnend durchzunummerieren ohne mich um die Ports
kümmern zu müssen, dann ist ein wesentliches Feature dieser Funktion auf
der Strecke geblieben und du hast die Funktion ad absurdum geführt.
Ok,
vielen dank schonmal für eure Tipps und erklärungen, ich werde mein Code
mal weitestgehend verbessern und überarbeiten.
Ich wüsste jedoch gerne warum du
die Pins so auschaltest
1
LED_PORT |= ( 1 << LED2 );
anstatt so:
1
LED_PORT = ( 0 << LED2 );
ich Persönlich finde variante 2 besser weil mir die 0 mehr ins auge
springt als das |
Ist das geschmackssache wie man das macht? oder hat das gewisse vor bzw
nachteile?
Martin Kathke schrieb:> Ok,> vielen dank schonmal für eure Tipps und erklärungen, ich werde mein Code> mal weitestgehend verbessern und überarbeiten.>> Ich wüsste jedoch gerne warum du> die Pins so auschaltest>
1
> LED_PORT |= ( 1 << LED2 );
2
>
> anstatt so:>
1
> LED_PORT = ( 0 << LED2 );
2
>
> ich Persönlich finde variante 2 besser weil mir die 0 mehr ins auge> springt als das |> Ist das geschmackssache wie man das macht? oder hat das gewisse vor bzw> nachteile?
Weil die Variante 2 nicht funktioniert und wenn ihr mal nicht nur blind
abschreiben würdet, sondern euch mal 2 sekunden überlegen würdet, was
genau diese Anweisung tut, dann wüsstet ihr auch warum.
Löschen tut man so: PORTB &= ~(1<<BIT)
Also verUNDEN mit der INVERTIERTEN Bitmaske, der Bits die man löschen
will.
weil 2 mal 0 immer noch 0 ist, genauso wie 3 mal 0 oder 5 mal 0.
Was hier steht ist also nichts anderes als
1
LED_PORT=0;
das kannst du auch einfacher haben :-). Macht allerdings nicht das
Beabsichtigte: einen Pin und NUR DIESEN EINEN Pin auf 0 zu setzen.
> Ist das geschmackssache wie man das macht? oder hat das gewisse vor bzw> nachteile?
Wenn du verstanden hast, was die OPeration << eigentlich macht, dann
stellt sich diese Frage nicht mehr.
VErschieb doch mal das Bitmuster
1
00000000
um zb 4 Bits nach links. Was kommt dabei raus?
Und was kommt raus, wenn du das Bitmuster
1
00000001
um 4 Bits nach links verschiebst? Was ist der fundamentale UNterschied
zwischen den beiden Ergebnissen?
Antwort: in dem einen Fall kriegst du ein Ergebnis, in dem genau an der
BItposition 4 ein 1 Bit landet. Im anderen Fall kannst du schieben so
viel du willst, das Ergebnis besteht immer nur aus einem Bitmuster
welches aus lauter 0 Bits besteht. (Denn mathematisch ist 0
mulitpliziert mit n immer 0, egal wie groß n ist)
Danke für eure Geduld und eure erklärungen,
ich habe das << anscheinend falsch verstanden, mir war nicht klar das
hier multipliziert wird, dachte hier wird einfach nur verschoben... Habs
jetzt verstanden. Vielen dank euch!
Martin Kathke schrieb:> Danke für eure Geduld und eure erklärungen,> ich habe das << anscheinend falsch verstanden, mir war nicht klar das> hier multipliziert wird, dachte hier wird einfach nur verschoben...
Es wird nur verschoben, aber was bewirkt denn ein bitweises schieben?
Was bewirkt das Schieben einer Stelle im Dezimalsystem? Was passiert
wenn du 30 (dez.) hast und dann eine Stelle nach links schiebst? Na?
Mann denk doch mal selber nach und rechne mal nach. Ist ja nicht zum
aushalten.
cyblord ---- schrieb:> Mann denk doch mal selber nach und rechne mal nach. Ist ja nicht zum> aushalten.
Wenn dich solche Dinge bereits an die Grenzen deiner nerven treiben,
dann respekt von mir dass du bis heute durchs Leben gekommen bist.
Martin Kathke schrieb:> Danke für eure Geduld und eure erklärungen,> ich habe das << anscheinend falsch verstanden, mir war nicht klar das> hier multipliziert wird, dachte hier wird einfach nur verschoben... Habs> jetzt verstanden.
Echt? Sieht noch nicht so aus.
Lass uns mal ein paar Bitmuster ansehen und ihre zugehörigen
Dezimalzahlen
1
Binär Dezimal
2
3
0000 0001 1
4
0000 0010 2
5
0000 0100 4
6
0000 1000 8
7
0001 0000 16
8
0010 0000 32
na, klingelts?
Binär schiebt sich das 1 Bit von rechts nach links um 1 Stelle weiter.
Als Dezimalzahl ausgedrückt, ist jede Zeile das Doppelte der
vorhergehenden Zeile.
1 mal nach links schieben ist also equivalent mit einer Multiplikation
mit 2.
Anderes Beispiel. Wir haben ein Bitmuster
1
0000 0101
das ist das Bitmuster für Dezimal 5
Jetzt schieb das mal 1 Stelle nach links
1
0000 1010
das ist das Bitmuster für dezimal 10 (oder Hexadezimal A). 10 ist aber
'zufällig' genau das Doppelte von 5.
Bei Binärzahlen entspricht also eine Verschiebung um 1 Stelle nach links
(und anhängen einer 0) einer Multiplikation mit 2. Das ist völlig
analog, wie in deinem gewohnten Dezimalsystem eine Verschiebung nach
links und Anhängen einer 0 einer Multiplkation mit 10 entspricht. Und so
wird dann im Dezimalsytem aus 0015 das Ergebnis 0150. Das kann man
erhalten, in dem man schiebt und eine 0 anhängt, oder in dem man mit 10
multipliziert. Nur das Schieben viel einfacher ist, weil man im Grunde
gar nicht rechnen muss.
Und das funktioniert in allen Stellenwert-Systemen. Denn die sind ja
genau so definiert, dass die Stelle weiter links das jeweils n-fache
ist, wenn n die Basis des Zahlensystems ist.
San Lue schrieb:> Zudem wage ich es mal zu behaupten, ein Compiler wandelt den Switch-Case> Code besser um als eine If/Else Abfrage, da er weiss dass immer die> selbe Variable geprüft wird. (Korrigiert mich, falls falsch!)
Ist falsch, kann auch mal genau andersrum sein.