Forum: Mikrocontroller und Digitale Elektronik STK600 8bit LED-Logik?


von batty m. (battyman)


Lesenswert?

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
   uint8_t i=0;
2
   uint8_t j=0;
3
   uint8_t LED[9] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
4
   
5
   for(i=0;i<8;i++)
6
   {
7
      j = j | i;
8
      PORTE = ~LED[j]; 
9
      _delay_ms(10);
10
   }
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

von Max D. (max_d)


Lesenswert?

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

: Bearbeitet durch User
von batty m. (battyman)


Lesenswert?

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

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

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.

von Max D. (max_d)


Lesenswert?

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

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

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
int main()
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( irgendwas anderes )
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.

: Bearbeitet durch User
von batty m. (battyman)


Lesenswert?

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:
1
unsigned char code LED_B_P0[9] = {0x01,0x08,0x40,0x00,0x00,0x00,...};
2
unsigned char code LED_B_P1[9] = {0x00,0x00,0x00,0x02,0x40,0x00,...};
3
unsigned char code LED_B_P2[9] = {Hex-Wert-Zuordnung};
4
unsigned char code LED_B_P3[9] = {Hex-Wert-Zuordnung};
5
6
// 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);

von batty m. (battyman)


Lesenswert?

Super, das mit den Hex-Werten hat nun doch wieder geklappt, war wohl zu 
doof. Sorry!
Hab leider aber wieder ein Verständnisproblem:
1
//Hex-Werte für die STK600-Board befindlichen LED's
2
uint8_t LED[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};  
3
  
4
i = 7;
5
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.

von Kaj (Gast)


Lesenswert?

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

von batty m. (battyman)


Lesenswert?

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
2
uint8_t LED[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};  
3
  
4
i = 9;
5
for(i=9i>0;i--)  //for-Schleife Lichtbalkenaufbau von links nach rechts
6
{
7
   j = j | LED[i];
8
   PORTE = ~j;
9
   _delay_ms(20);
10
}
mhh, wenn ich immer noch falsch bin einfach mal berichtigen. Kann es 
leider nicht gerade ausprobieren. Danke

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

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.

von spess53 (Gast)


Lesenswert?

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

von batty m. (battyman)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

: Bearbeitet durch User
von batty m. (battyman)


Lesenswert?

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.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

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

von batty m. (battyman)


Lesenswert?

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.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

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.

: Bearbeitet durch User
von batty m. (battyman)


Lesenswert?

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

von batty m. (battyman)


Lesenswert?

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?

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.