Nabends,
ich bin mit meinem mega2560 auf dem STK600 am Üben und will mir so
Schritt für Schritt einige Beispielprogramme (Bibliothek) anlegen.
So, die ersten Schritte mit dem AVR wollte ich an den acht vorhandenen
LEDs tätigen.
Ich habe die DDR mit 0xff auf Ausgang gestellt und die Boardspannung auf
3V festgelegt.
Fragen:
1.) Warum leuchten allein durch auf "Ausgang gesetzt" die PortPin
(verbunden mit LED) auf? - Ich dachte, ich setzte das Register auf
Ausgang, lege jedoch die Spannung noch nicht an, also:
Register auf Ausgang setzen
1
DDRE = 0xff;
Die Spannung hätte ich dann mit
1
DDE = 0xff;
an die PortPins angelegt.
2.) Lauflicht von rechts nach links, sowie von links nach rechts
bewerkstellige ich mittels Bit-schifting und einer Zählvariable samt
for-Schleife. Daraus folgend- Wenn ich nun auf den Port ein Bit setzen
möchte muss ich immer negativieren, um das gewünschte Muster zu erzeugen
(sonst geht die angesteuerte LED aus anstatt an, da Grundstellung alle
an), Bsp. so:
1
uint8_t i=0;
2
3
for(i=0,i<8,i++)
4
{
5
PORTE = ~(1<<i);
6
_delay_ms(10);
7
}
Ich kann zwar so arbeiten, jedoch erschließt sich mir die Logik dahinter
noch nicht so recht. Was mache ich falsch, bzw. denke ich nur das ich
was falsch mache???
Ansteigender LED-Lichtbalken:
Um den ansteigenden Balken zu generieren wollte ich nun mit einer
Hex-Matrix und einer zweiten Zählvariablen arbeiten, so:
1.)Warum kann ich nicht mit den Hex-Werten arbeiten? I-was raff ich
gerade überhaupt nicht. Der schaltet einfach LED0, LED1, LED3, LED7,
LED0, LED1, LED3, LED7 durch.
2.) Wollte ich mit der Oder-Logik die Hex-Werte aufaddieren, um eben den
Lichtbalken ansteigen zu lassen. Funktioniert aber auch nicht so wie
gedacht, wobei ich wieder leicht verzweifel.
3.) Nach dem die Hex-Werte nicht wollen, dacht ich an die Ganzzahlen
0-255, wobei ich gleich in der Matrix gedanklich addiert habe und somit
wieder nur "i" als Zählvariable nutze, so:
1
uint8_t i=0;
2
uint8_t j=0;
3
uint8_t LED[9] = {1, 3, 7, 15, 31, 63, 127, 255};
4
5
for(i=0;i<8;i++)
6
{
7
//j = j | i;
8
PORTE = ~LED[i];
9
_delay_ms(10);
10
}
Alles gut soweit, denn er lässt jede LED-Stelle somit addiert
aufleuchten. Damit könnte ich mich eigentlich zufrieden geben, aber das
Addieren muss doch auch mit einer Hilfsvariablen funktionieren. Hab also
die gleiche Vorgehensweise [wie (1.)] nur mit Ganzzahlen probiert, so:
1
uint8_t i=0;
2
uint8_t j=0;
3
uint8_t LED[9] = {1, 2, 4, 8, 16, 32, 64, 128};
4
5
for(i=0;i<8;i++)
6
{
7
j = j | i;
8
PORTE = ~LED[j];
9
_delay_ms(10);
10
}
Funktioniert auch nicht wie gedacht, warum???
Für Hinweise und Fehlerfindung bzw. Erklärungen zu meinen Denkfehlern
wäre ich euch wiedermal sehr verbunden.
THX, LG
Das STK600 wird die LEDs gegen Plus geschaltet haben, deswegen leuchten
die wenn du eine Null ausgibst.
Ich bin mir nicht ganz sicher was du mit "aufsteigendem Balken" meinst,
wenn du meinst, dass die LEDs nacheinander angehen und an bleiben, dann
denk mal nach was PORTE = ~LED[j]; macht. Kleiner Tipp: Man würde es
etwa so "sprechen": "schaue an j-ter Stelle im Array LED nach,
invertiere das Ergebnis und schreibe es dann in das register PORTE." =>
In dem Array muss das fertige Bitmuster stehen....
j = j | i; Dieses ODER macht so herzlich wenig sinn, ich bin mir ehrlich
gesagt nichtmal sicher warum das dasteht ^^
Wenn es irgendwie die Ausgegebene sequenz verodern soll, dann muss das
ergebnis dieses oders auch irgendwann in das reg rein (und nicht durch
iein Array geschickt werden).
Max D. schrieb:> Das STK600 wird die LEDs gegen Plus geschaltet haben, deswegen leuchten> die wenn du eine Null ausgibst.
Demnach muss ich alles was ich mit den Board anstelle (I/O-Ports)
invertieren um das gewünschte Ergebnis zu bekommen. Warum denk man sich
bei der Entwicklung des Boardes so etwas aus?
Wenn ich aber für Ausgang das Register entsprechend beschreiben soll und
dann laut Datenblatt erst anschließend mit dem nächsten Befehl die
Spannung anlege, dann macht es doch gar keinen Sinn, wenn bei dem
Schreiben des Registers schon alle LEDs leuchten!!????
> Ich bin mir nicht ganz sicher was du mit "aufsteigendem Balken" meinst,> wenn du meinst, dass die LEDs nacheinander angehen und an bleiben,...
Ja genau das habe ich auch gemeint.
> denk mal nach was PORTE = ~LED[j]; macht. Kleiner Tipp: Man würde es> etwa so "sprechen": "schaue an j-ter Stelle im Array LED nach,> invertiere das Ergebnis und schreibe es dann in das register PORTE." =>> In dem Array muss das fertige Bitmuster stehen....>> j = j | i; Dieses ODER macht so herzlich wenig sinn, ich bin mir ehrlich> gesagt nichtmal sicher warum das dasteht ^^> Wenn es irgendwie die Ausgegebene sequenz verodern soll, dann muss das> ergebnis dieses oders auch irgendwann in das reg rein (und nicht durch> iein Array geschickt werden).
Das beides war mein Ausführfehler. Gedanklich war ich richtig gestrickt,
jedoch völlig verblödet hingeschriebn.
Ich wollte i als Zählvariable für die Array-Stellen benutzen, so dass
eben immer eine Stelle weiter im Array ausgelesen wird. Dananch wollte
ich diesen Wert mit j verodern und anschließend dem Port übergeben. Da
ich diesen Gedanken hatte, es aber falsch geschrieben habe und es nicht
SAH, bin ich auch fast verzweifelt.
Mit:
1
uint8_t i=0;
2
uint8_t j=0;
3
uint8_t LED[9] = {1, 2, 4, 8, 16, 32, 64, 128};
4
5
for(i=0;i<8;i++)
6
{
7
j = j | LED[i];
8
PORTE = ~j;
9
_delay_ms(10);
10
}
funktioniert das jetzt einwandfrei. Hab es heute morgen noch schnell
probiert, da beim Lesen deiner Antwort mir das Licht meiner verheerenden
Schreibweise aufgegengen ist.
Muss es jetzt nur noch mal den den Hex-Werten schreiben und probieren.
Dann wäre ich mit der Ausübung aller Schreibweisen sehr zufrieden und
kann mich weiter robben in der AVR-Welt.
Danke
batty man schrieb:> Warum denk man sich> bei der Entwicklung des Boardes so etwas aus?
Ganz einfach:
Im STK kann man die Targetspannung von 1,8..6,0V einstellen. Damit die
LEDs trotzdem immer gleich hell sind, liegen sie an +5V.
Das ist ja schön, dass ich dir helfen konnte :)
Das Array kannst du dir bei dieser spezifischen Anwendung übrigens
eigtl. ganz sparen.
(1<<i) liefert auch 1, 2, 4, 8, 16, 32, 64, 128 nacheinander (halt
abhängig von i). Wobei man sagen muss, dass da in dem Array nur 8
Stellen stehen sich das im letzendlichen ASM-Code nicht viel schenken
wird ^^
Ich finde es übrigens gut, dass du "richtiges" C auf den AVRs
programmierst und nicht diese Krücke Arduino bemühst :).
Edit: Passage über stk600 gelöscht, da war wohl wer schneller als ich ^^
batty man schrieb:> Demnach muss ich alles was ich mit den Board anstelle (I/O-Ports)> invertieren um das gewünschte Ergebnis zu bekommen.
Nicht bei allem.
Nur bei Leds und das auch nur, weil die eben genau so angeschlossen
wurden.
Im übrigen ist das in der Praxis ein viel kleineres Problem als du jetzt
annimmst.
Denn ob man eine LED in einem realen Programm dann mit
1
PORTE|=(1<<PE0);
einschaltet, oder mit
1
PORTE&=~(1<<PE0);
spielt keine Rolle. Auch wenn das zweite komplizierter aussieht, wird es
trotzdem in einen einzigen Assemblerbefehl übersetzt.
Stören einen die Schreibweisen, dann macht man sich dafür eben Makros
1
#define LED_ON(led) PORTE &= ~( 1 << (led) )
2
#define LED_OFF(led) PORTE |= ( 1 << (led) )
und schreibt dann im Programm zum Beispiel
1
#define ERROR_LED PE0
2
#define READY_LED PE1
3
4
intmain()
5
{
6
....
7
8
LED_OFF(ERROR_LED);
9
LED_ON(READY_LED);
10
11
while(1)
12
{
13
...
14
if(irgendwas)
15
LED_ON(ERROR_LED);
16
17
if(irgendwasanderes)
18
{
19
LED_OFF(READY_LED);
20
...
21
LED_ON(READY_LED);
22
}
23
}
24
}
und wie du siehst, ist die ganze Thematik, ob da jetzt eine 1 oder eine
0 die LED einschaltet insoweit vom Tisch, dass ich mich beim
eigentlichen Programm überhaupt nicht mehr darum kümmern muss. Wie rum
die Einstellung sein muss, damit die LED leuchtet, ist an einer Stelle
konzentriert und ein ...
1
LED_ON(ERROR_LED);
ist in jedem Fall um vieles anschaulicher und leichter zu begreifen als
die dahintersteckenden Ver-undungen bzw. Ver-oderungen. Egal wie rum es
dann wegen dem elektrischen Anschluss der LED tatsächlich sein muss.
D.h. eine vernünftige Code-Organisation fängt dir diese ganze
Problematik mit 0 oder 1 alles auf und liefert dir zusätzlich noch einen
'Mehrwert', der dein Programm als ganzes in eine ganz andere
Qualitätskategorie anhebt.
Ein Dank an euch und euren Antworten. Nun muss ich erstmal wieder in
mein stilles Kämmerlein und mich zum Ausprobieren ran setzen.
>Ich finde es übrigens gut, dass du "richtiges" C auf den AVRs>programmierst und nicht diese Krücke Arduino bemühst :).
Ehrlich gesagt weiß ich nicht mal was dieses Arduino ist, von daher gab
es für mich da auch keine Wahl ;-)
Exkurs:
Ich habe mal mit VB für Excel-, Acces- und Word-Projekte gearbeitet und
mich darin etwas fit gemacht.
Letzten Frühling war es dann mal soweit, dass ich mich mit einem alten
C8051 befasst habe und dort ging nur so "C". Wobei das doch i-wie alles
noch etwas anders aussieht und ich auch anders an die Sachen, fehlende
Bibliotheken geschuldet, ran gegangen bin. Naja durch mein LED-Projekt
war der C8051 dann leider aufgrund seines Alters und damit leicht
dezemierter Ausstattung schnell an die Grenzen gekommen. Ich habe mir
aber auf diesen ein Lichtszenario für 28 LEDs geschrieben, mit eben
Lauflicht, Lichtbalken, Blinken und Dauerlicht mit den dargestellten
Farben (R, G, B, Ma, Cy, Ge, W). Dabei wollte ich damals schon die
Szenarien per Schalter auswählen, wobei bei einer Schalterstellung ein
"echter" Zufallsgenerator die Farbverläufe bestimmen sollte. Der µC
wollte aber nur den pseudo Zufall erzeugen und hatte somit immer den
gleichen Durchlauf. Weiterhin wollte ich mich nach der erfolgreichen
Erstellung mein Projekt mit einer PWM erweitern. Problem dabei war, dass
der Programmcode die Kapazität des µC überschreiten würde. Dadurch habe
ich mich etwas mehr mit der Materie befasst und hab mich letztendlich
für das STK600 + ATmega2560 entschieden.
Wo die Unterschiede zw. C, C++ oder C# liegen weiß ich leider nicht.
Ich habe mich nur den sehr schön geschrieben Tutorials (AVR und AVR-GCC)
hingewandt und darin geschmöckert. Da ich Assembler nicht kann und ich
auch kein Interesse an einem Basic-Compiler hatte, blieb mir also C
übrig :D
Jetzt bin ich also erstmal immer am Üben, um mit den Befehlen klar zu
kommen und deren Logik zu verstehen. Nur die gut 400 Seiten Tutorial
zzgl. den 400 Seiten Datasheet mega2560 überfordern mich doch etwas.
Demnach mach ich mal kleine Schritte und gehe von einem Kapitel zum
anderen und stelle mir Szenarien auf und möchte dann dort die
verschiedenen Schreibweisen unterbringen, so dass ich auch immer mal
wieder dort reinschauen kann um es nachzuvollziehen, wenn ich an
anderen/verknüpften Projekten arbeite. -> Ich vergess leider immer so
viel.
Weiteres Bsp., bei dem ich auf eine Frage stoße:
Beim C8051 musste ich "code" an mein unsigned char hängen, um das
nachfolgende Array auf den Flash auszulagern. Damit hatte ich ja wieder
mehr Programmcodeplatz frei.
Wenn ich jetzt mein Datasheet richtig verstehe, würde ich nun EEPROM
hinter uint8_t schreiben. Ist das richtig oder eher unintelligent,
weil...?
Da ich 28 LEDs auf 4 Ports (Farbe-LED sind dabei gemixt pro Port)
verteilt habe, habe ich pro Farbe (RGB) 4 Arrays zusammengeschrieben,
so:
// usw. für die drei Farben pro Port eben ein eigenes Array...
7
// die anderen darstellbaren Farben werden durch Ver-oderung im Code
8
// selbst erzeugt
nun würde ich als ersten Schritt versuchen ein zweidimensionales Array
pro Port zu bauen, ungefähr so:
1
uint8_t EEPROM LED_B_PA[9,3] = {{ x - Hex-Wert-Zuordnung Pin},
2
{ y - Hex-Wert-Zuordnung Farbe}};
3
4
5
//usw. für die anderen 3 Ports.
Das mit dem Bit-shifting ist an sich ja super, jedoch denke ich mir mal
das genau jetzt bei meiner Anwendung eher kontraproduktiv sein wird, da
unübersichtlicher - weiß es aber nicht.
Wenn so etwas auch mit Zählvariablen, Bit-shifting und Ver-oderungen
besser bzw. einfacher aufgestellt werden kann, wär ich natürlich nicht
abgeneigt neue Wege zu beschreiten.
Vorher musste ich auch mit der ISR und einem Timer arbeiten, wodurch
eben alle Variationen gleichschnell/-langsam durchgelaufen waren. Nun
kann ich den Befehl delay_ms verwenden. Tolle Sache, aber was wird
eigentlich verzögert? Denn die Leuchtdauer oder Bit-Ansprechverhalten
sind nicht die geschriebenen Millisekunden. Ich gehe auch schwer davon
aus, dass sich das Delay auf die definierte Taktfrequenz bezieht. In
meinem Fall sind es 2MHz, also 0,5ns Bearbeitungsdauer. Was ich leuchten
sehe sind z.b. niemals 10ms bei _delay_ms(10);
for(i=7i>0;i--) //for-Schleife Lichtbalkenaufbau von rechts nach links
6
{
7
j = j | LED[i];
8
PORTE = ~j;
9
_delay_ms(20);
10
}
Leider wird die erste LED nicht eingeschaltet. Und ich seh schon wieder
nicht mein Problem??!!
Der nächste Schritt wieder das arbeiten mit dem Vordefinierten, denn den
muss ich unbedingt noch raffen.
batty man schrieb:> Demnach muss ich alles was ich mit den Board anstelle (I/O-Ports)> invertieren um das gewünschte Ergebnis zu bekommen. Warum denk man sich> bei der Entwicklung des Boardes so etwas aus?
Das wird aus einem sehr einfachen Grund gemacht:
LEDs werden in der Regel dauerhaft mit + verbunden, damit die LEDs
immer die "gleiche Helligkeit" haben.
Jetzt wirst du Fragen: Warum sollte die Helligkeit nicht immer gleich
sein, wenn man die LED andersherum anschließt?
Auch hier, ganz einfach:
Ein Mikrocontroller bzw. Logikbausteine geben einen Pegel aus. Ein AVR
(dein Mega2560 zum Beispiel) gibt bei einem HIGH eine Spannung im
Bereich von 4,5V bis 5,5V aus. Das heißt beim ersten mal Schalten kann
die Spannung 5V betragen, beim nächsten mal nur 4,5V und beim dritten
mal 5,5V. Daraus resultiert eine Unterschieldiche Helligkeit der LED,
Ok, das die Helligkeitsunterschiede dabei eher maginaler Größe sind, sei
jetzt mal dahin gestellt.
Und das wird auch nicht erst seit heute so gemacht ;)
Grüße
Wat, das Board hat eine Spannungsdifferenz von ±0,5V. Das sind bei 5V
gute 10%. Absolut betrachtet sogar 20%. Ist das normal bei µC? oder
hängt das hier eher von der Spannungsquelle ab?
Mein Problem war nur eher die logische Denkweise bei der Programmierung
und auch den Kommandos, da ich eher so der C-Laie bin. Ich habe zwar
auch Visual Studio 2012, nur ich weiß immer nicht so recht was ich dort
an Aufgaben, Programmen schreiben soll um mich eben in C zu üben. Bei
den µC sehe ich wenigstens gleich ein Ergebnis und entweder (wie auch in
diesem Fall) ist mein Gedanke falsch niedergeschrieben oder es
funktioniert wie gewünscht.
Mir ist ja eben auch noch nicht ganz klar, warum ich die STK600-LEDs von
0-7 ansprechen und dauerhaft leuchten lassen kann, aber nicht von 7-0,
da die letzte leuchtende LED immer die LED1 ist.
Edit:
Ich glaube doch zu wissen wo mein Fehler ist. Ich denk mal ich muss
meine Zählvariable auf 9 initialisieren und von dort aus meine
for-Schleife durchlaufen. Ich glaube ich bin immer eine LED-Stelle
zufrüh mit i bei 0.
1
//Hex-Werte für die STK600-Board befindlichen LED's
batty man schrieb:> for-Schleife durchlaufen. Ich glaube ich bin immer eine LED-Stelle> zufrüh mit i bei 0.
Nö.
Dir ist die Reihenfolge nicht klar, in der in einer for-Schleife die 3
Einzelteile angewendet werden
1
for(init;bedingung;anweisung)
2
...
wird so
1
init
2
while(bedingung)
3
{
4
...
5
anweisung
6
}
aufgeöst.
Daraus folgt etwas. Nämlich dass nach Durchlauf des Schleifenkörpers in
deinem Fall das i-- kommt. Unmittelbar danach gehts aber wieder hoch zur
Überprüfung der Schleifenbedingung, in deinem Fall i > 0
hat i den Wert 1, dann wird für diese 1 der Schleifenkörper ausgeführt
und dann um i um 1 verringert. Dadurch wird i zu 0. 0 ist aber (in der
Abfragebedingung) nicht mehr größer als 0. D.h. der Schleifenkörper wird
für i gleich 0 gar nicht mehr ausgeführt.
> mhh, wenn ich immer noch falsch bin
ja du bist falsch.
Verfolg halt einfach mal am Papier die Werte der Variablen! Du darfst
mit Papier und Bleistift Computer spielen und dir so klar machen, welche
Zahlenwerte welche Variablen haben und wie das läuft. Das ist kein
Verbrechen und ist auch nicht verboten!
Und dann achtest du mal darauf, welche Werte i hier
1
j=j|LED[i];
haben wird und fragst dich ganz einfach mal: gibt es denn dieses
Array-Element überhaupt? Gibt es überhaupt ein LED[9]?
Nein. Gibt es nicht.
Dein Array ist 8 Elemente groß.
LED[0], LED[1], LED[2], LED[3], LED[4], LED[5], LED[6], LED[7]
Zähl nach. Sind genau 8 Stück. Der größte verfügbare Index ist aber 7!
Alle Zugriffe (in deinem Fall), bei denen der angegebene Ausdruck Werte
ausserhalb von 0 bis 7 liefert, sind illegal.
Hi
>Das wird aus einem sehr einfachen Grund gemacht:>LEDs werden in der Regel dauerhaft mit + verbunden, damit die LEDs>immer die "gleiche Helligkeit" haben.
Ja.
>Ein Mikrocontroller bzw. Logikbausteine geben einen Pegel aus. Ein AVR>(dein Mega2560 zum Beispiel) gibt bei einem HIGH eine Spannung im>Bereich von 4,5V bis 5,5V aus. Das heißt beim ersten mal Schalten kann>die Spannung 5V betragen, beim nächsten mal nur 4,5V und beim dritten>mal 5,5V. Daraus resultiert eine Unterschieldiche Helligkeit der LED,
Unsinn. Das ist kein Zufallgenerator. Die Spannung am Pin ist vom VCC
des Controllers und dem Strom abhängig. Die Temperatur spielt auch noch
eine Rolle. Siehe
http://www.atmel.com/Images/doc2549.pdf
S.397ff.
Den wirklichen Grund für die Beschaltung der LEDs findest du in der
Beschreibung des STK600:
4.2.1 On-board VTG source
The on-board VTG source is set from AVR Studio. To use this source, the
VTARGET jumper must be mounted. The on-board supply can be adjusted from
0.9 to 5.5V in steps of 0.1V.
Die Beschaltung stellt sicher, das die LEDs in dem
Betriebsspannungsbereich gleich hell leuchten. Und nichts anderes.
MfG Spess
Karl Heinz schrieb:> Dein Array ist 8 Elemente groß.> LED[0], LED[1], LED[2], LED[3], LED[4], LED[5], LED[6], LED[7]> Zähl nach. Sind genau 8 Stück. Der größte verfügbare Index ist aber 7!> Alle Zugriffe (in deinem Fall), bei denen der angegebene Ausdruck Werte> ausserhalb von 0 bis 7 liefert, sind illegal.
Zähl ich denn auch die Array-Stellen bei 0 los? Als Zahlenwert wäre es
doch keine Null sondern die erste. Ich komme da wirklich immer wieder
ins grübeln. Bei den Port-Pins habe ich mittlerweile begriffen dass
immer die Null der erste Adresszahlenwert ist. Ergo, zähl ich nach
deiner Aussage auch immer die Array-Inhalte beginnend mit Null -
{0,1,2,3,4,5,6,7} und nicht {1,2,3,4,5,6,7,8}. Das wären ja in beiden
Fällen immer noch 8 Werte.
Gedanke der for-Schleife war für mich so:
- ich initialisiere i = 9;
- für ( von i=9, bis i>0, ziehe von i immer einen ab).
Heißt für mich dann eben wenn i ≠ 9 , dann wird die Schleife nicht
durchlaufen. So wenn i = 9, dann hüpf in die Schleife, zieh von 9 einen
ab und für das aus, usw. bis i = 1, denn dann wird zu Null.
batty man schrieb:> Zähl ich denn auch die Array-Stellen bei 0 los?
Ja.
Du brauchst wirklich ganz dringend ein C-Buch und ein paar Übungsstunden
am PC.
> Als Zahlenwert wäre es> doch keine Null sondern die erste. Ich komme da wirklich immer wieder> ins grübeln.
Wir fangen in C immer bei 0 an zu zählen!
Die Idee ist ganz einfach, dass man aus einem ominösen Startwert und
einer Element-Breite, den Abstand des i-ten Elementes von diesem
Startwert ermitteln kann, indem man
1
Abstand = Startwert + i * Element_Breite
rechnet.
Und dazu ist es erfoderlich, dass das erste Element ein i von 0 hat.
Denn es ist ja dasjenige Teil, welches genau am Startwert beginnt. Ob
das jetzt Arrays sind, oder Postkästen die in einer Reihe hängen oder
Tapetenbahnen an der Wand oder ... spielt keine Rolle. Das jeweils erste
in der Kette hat die Nummer 0.
Alles andere ist auf lange Sicht gesehen nämlich komplizierter und auch
fehleranfälliger, denn irgendwann vergisst man nämlich, dass man vom
'Index' noch 1 abziehen muss, damit man rechnen kann wo dieses Teil in
Bezug auf den Anfang der Kette liegt.
Also gewöhn dich daran: in C fangen wir bei 0 zu zählen an. Immer. Das
'erste' Element ist das mit dem Index 0.
Alles klar. Zähle somit nun immer von NULL, egal bei welchen Projekt,
etc.
Frage zur for-Schleife noch mal.
Habe ich deine Ausführung richtig verstanden, dass:
- Programm kommt an der for-Anweisung an
- geht in die for-Anweisung und bekommt den Start-, sowie Endwert direkt
initialisiert
- geht in die { rein
- führt alles aus was so drin steht
- und erst wenn ich unmittelbar vor } bin wird die Anweisung Bsp. i--
ausgeführt
???
Hüpft denn mein Programm somit unten aus der Schleife, da an dieser
Stelle erst die i=1 zu 0 wird und somit nicht mehr größer wie 0 ist?
Bisher - auch unter Basic (leider wirklich nie echt gerafft) - habe ich
die for-Schleife als eine Art "Von-Bis-Bereich - führe aus und mach dann
das was innerhalb der geschweiften Klammer steht" angesehen. Das würde
für mich ja dann bedeuten das ich gleich zu Anfang mit i etwas mache und
wenn die Randbedingungen erfüllt bzw. eben überschritten werden ich das
was in der Klammer steht nicht mehr ausführe.
Warum ich welchen Schleifentyp wann verwende ist mir natürlich in diesem
Zug auch noch nie wirklich so klar geworden und demnach auch nicht
welche Schleife zu den "oben" bzw. "unten" rausspringenden zählt.
Ja, die Anschaffung eines C-Buches ist in Planung, leider
verstehe/interpretiere ich mein gelesenes oft falsch. Ist ein Problem,
wodurch ich einfach mehr als nur eine Buchquelle für Wissen brauche.
Jeder erklärt gewisse Sachen anders oder stellt sie anders
veranschaulicht dar. Das hilft mir persönlich ungemein.
Edit: hab ja die Buch-Empfehlungen, werd mir dort mal eins raussuchen
Deswegen bin ich auch auch wirklich sehr dankbar und freue mich
ebenfalls darüber wenn mir mal was wirklich einleuchtendes klar wird.
batty man schrieb:> Gedanke der for-Schleife war für mich so:> - ich initialisiere i = 9;> - für ( von i=9, bis i>0, ziehe von i immer einen ab).> Heißt für mich dann eben wenn i ≠ 9 , dann wird die Schleife nicht> durchlaufen.
Mag ein Tippfehler von dir sein.
Nicht ungleich 9. Ungleich 0. Genauer gesagt eigentlich: größer 0. Denn
genau das steht ja da.
1
for(....;i>0;...)
da steht eindeutig: führe den Schleifenkörper aus, solange i größer als
0 ist, wenn die Abfrage das nächste mal ausgewertet wird.
> So wenn i = 9, dann hüpf in die Schleife, zieh von 9 einen> ab und für das aus
Aber die Reihenfolge ist entscheidend!
Dieses 1-Abziehen findet am Ende des Schleifenkörpers statt und nicht am
Anfang.
Also nicht
1
...
2
{
3
i=i-1;
4
alleanderenAnweisungen;
5
}
sondern
1
....
2
{
3
alleanderenAnweisungen
4
i=i-1;
5
}
6
....
Und das macht einen Unterschied welchen Wert i gerade hat, wenn der
Abschnitt 'alle anderen Anweisungen' abgearbeitet wird.
Karl Heinz schrieb:> batty man schrieb:>>> Gedanke der for-Schleife war für mich so:>> - ich initialisiere i = 9;>> - für ( von i=9, bis i>0, ziehe von i immer einen ab).>> Heißt für mich dann eben wenn i ≠ 9 , dann wird die Schleife nicht>> durchlaufen.
Nein, war jetzt kein Schreibfehler. Für mich galt bis eben, der Ausdruck
"VON - BIS" und nicht "dieser Wert bist du und bis dahin soll Anweisung
getätigt werden". Für mich also, wenn beim Ankommen zur for-Schleife i
den Startwert nicht hat, so wird die Schleife einfach übergangen. Ähm,
also ich soll in Raum 302 und so lange ich den Raum nicht erreicht habe
öffne ich auch die Tür nicht. So ungefähr. Demnach meine ich wenn i ≠ 9,
passiert eben gar nichts. Das war meine Interpretation, sorry.
>Also nicht
1
...
2
{
3
i = i - 1;
4
alle anderen Anweisungen;
5
}
>sondern
1
....
2
{
3
alle anderen Anweisungen
4
i = i - 1;
5
}
6
....
> Und das macht einen Unterschied welchen Wert i gerade hat, wenn der> Abschnitt 'alle anderen Anweisungen' abgearbeitet wird.
Und genau dieser Schritt, wann welche Schleife was macht "Vergleich"
Anfang oder Ende war mir bis heute wirklich nicht klar. Nun ist er es
wenigstens für die for-Schleife ;-)
So bekommt es auch eher Logik, mit dem was ich so am Board sehe.
batty man schrieb:> passiert eben gar nichts. Das war meine Interpretation, sorry.
Ich denke mal da steckt was anderes dahinter. :-)
= ist in C eine Zuweisung
== ist in C ein Vergleich auf Gleichheit.
d.h.
hier
1
for(i=9;....
steht kein Vergleich der dafür sorgen könnte, dass irgendwas nicht
gemacht wird. Das ist eine Zuweisung! i kriegt den Wert 9 zugewiesen.
Und damit erhebt sich die Frage ob gleich oder ungleich 9 gar nicht
mehr. Denn i HAT hier am Anfang den Wert 9. Per Definition. Denn der
wird i zugewiesen.
> Für mich galt bis eben, der Ausdruck "VON - BIS"
Vergiss das ganz schnell. Eine for-Schleife in C funktioniert nicht so.
die 3 Ausdrücke im for sind einfach nur:
* der erste Ausdruck wird ausgeführt, noch ehe die Schleife überhaupt
irgendwas macht
* der zweite Ausdruck regelt ob die Schleife wiederholt werden soll oder
nicht. Er wird am Beginn des Schleifenrumpfes ausgewertet und nur dann
wenn der Ausdruck den Wahrheitswert TRUE ergibt, wird der
Schleifenkörper ein weiteres mal ausgeführt (kann aber auch gar nicht
sein, wenn die Bedingung von Anfang an schon nicht zutrifft).
* der dritte Ausdruck wird am Ende des Schleifenkörpers ausgewertet,
also noch ehe die Schleife dann wieder von vorne mit dem Auswerten der
Bedingung neu beginnt.
YES!!! Thanks...
Nun habe ich es endlich erstmal geschafft, dass die LEDs pro erhöhten
Bit ansteigend angehen und an bleiben. Das geht nun von rechts nach
links an und anschließend auch in selbige Richtung wieder aus. Danach
wird das ganze von links(höchste Bit) nach rechts (kleinste Bit)
durchgeführt.
Das Problem was ich mit dem letzten (kleinsten) Bit hatte war die
Endrandbedingung. Aber das war ja nun schon der Allgemeinheit klar :-)
Mit
1
for(i=7; i>0; i--)
2
{
3
j = j - LED[i];
4
PORTE = ~j;
5
_delay_ms(30);
6
}
kam ich ja nur bis zu "i==1"->TRUE, wodurch ich eben die erste LED nie
anbekommen habe. Wenn ich jetzt aber die Randbedingung
1
for(i=7; i>=0; i--)
benutzen wollte um das i auf Null runter zählen lassen zu können, hatte
ich das Problem, dass vor dem beenden des letzten Durchganges ja das i
auf -1 zählt. Durch meine Deklaration als pos. Ganzzahl ist dies aber ja
nicht zulässig.
So nun wollte ich aber nicht auf int8_t deklarieren, da ich dann nur 7
statt aller 8 LEDs ansprechen kann (zumindest auf dem Weg der Ganzzahl).
Auf int16_t wollte ich aus Speicherersparnis nicht rauf, da dieser dann
vergeudet ist.
Meine Lösung ist jetzt, dass ich noch eine if-Anweiseung in die
for-Schleife mit integriert habe, so:
1
for(i=7; i>0; i--)
2
{
3
j = j - LED[i];
4
PORTE = ~j;
5
_delay_ms(30);
6
if (i==0)
7
{
8
break;
9
}
10
11
}
1.)Ist das eine gute Lösung oder würdet ihr das anders Hand haben um
vernünftig aus der Schleife zu kommen???
2.)Ich habe mein j-Wert gleich aus der vorhergehenden for-Schleife
verwendet, da ich diese durch die Ver-oderung aufaddiert habe. Wie hier
zu sehen habe nun mein j-Wert minus dem ausgelesenen i-Wert gerechnet.
Ist die vorgehensweise i.O., oder wäre eine Ver-oderung mit invertieren
die bessere Alternative? - gebe ich lieber pro for-Schleife mein
j-Startwert direkt vor, um bei späteren Umstellungen oder
Code-Durchsichtung das sofort sehe und damit auch klar ist was ich mir
mal dachte???
Frage noch zu der Anbindung der STK600-Board-LEDs. Wenn die nun alle auf
Masse geschaltet sind. Kann ich dann eigentlich mit denen ein
PWM-Programm testen?