www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Hilfe beim Programmieren eines LED Cubes Atmega16


Autor: AlienX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich hoffe ihr könnt mir helfen.

Also ich habe mir vor kurzem einen 4x4x4 LED Würfel gelötet. Dieser wird 
mit einem Atmega 16 angesteuert

Er wird Folgendermaßen angesteuert, insgesamt laufen 20 Signalleitungen 
zu der Platine.

Diese sind wie folgt belegt,
-16 dieser Leitungen gehen an die verschiedenen Fußpunkte eines LED 
Türmchens, d.h. immer 4 LED's übereinander hängen an einem Port
-4 dieser Leitungen schalten die Masse für die verschiedenen Ebenen 
durch.


Jetzt versuche ich gerade ein Initialiserungsprogramm in C zu schreiben.
Es sollte jede LED einzeln ansteuern und 3 mal blinken lassen. Einfach 
als LED Test ob noch alle LED's funktionsfähig sind.

Leider komme ich hier gerade nicht weiter. Die for Schleifen führt er 
alle nicht sichtbar aus, er braucht zwar jetzt einen Moment nach dem 
Microcontroller Reset bevor die while schleife ausgeführt wird, 
allerdings ist von der for schleife nichts zu sehen, ich hoffe ihr könnt 
mir helfen.


#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>

void delay_ms(uint16_t ms)
{
for (uint16_t t=0; t<=ms; t++)
_delay_ms(1);
}


int ebene, tab, turmcd;

/* Blinkfunktion beginn */

void blinken()
{
int zaehler;
zaehler=0;
for (uint8_t zaehler=0; zaehler<=3; zaehler++)

PORTA = tab;
PORTB = ebene;
PORTD = turmcd;
_delay_ms(500);
PORTA = 0;
PORTB = 0;
PORTD = 0;
_delay_ms(200);


}

/*Blinkfunktion Ende */

//Globalvariablendeklaration
//int ebene, tab, turmcd;

//Hauptprogramm


int main()
{

//Variablendefinition

ebene=1;
tab=0;
turmcd=0;

DDRA=0xFF; // Turm A und B
DDRB=0xFF; // Ebene
DDRD=0xFF; // Turm C und D

for (ebene=1; ebene<=4; ebene++);
{
for (tab=0; tab<=8; tab++);
{
blinken();
}
for (turmcd=0; turmcd<=8; turmcd++);
{
blinken();
tab=0;
turmcd=0;
}
}

while (1)
{
PORTA = 0b11111111;
PORTB = 0b11111111;
PORTD = 0b11111111;
delay_ms (10000);
PORTA = 0b00001110;
PORTB = 0b00111100;
PORTD = 0b00111100;
delay_ms (500);
}


return 0;
}

Autor: Michi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiß nicht ob das so gewollt ist... laut syntax vermute ich mal 
nicht... aber wenn du eine for schleife mit ; abschließt, hast du eine 
leere schleife

Autor: ozo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In der Funktion "blinken" fehlen meines Erachtens nach geschweifte 
Klammern hinter der for-Schleife. An anderen for-Schleifen sind 
wahrscheinlich ungewollte Semikolons dran...

gute Nacht ;)

Autor: AlienX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

erstmal danke für die schnellen antwoten, nun das habe ich jetzt 
gemacht.. jetzt sind die LeD's mal für ne weile aus.. aber an und 
blinken geht trotzdem nicht?

habe ich da jetzt noch was übersehen??

Autor: Michi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
in blinken:

int zaehler;
zaehler=0;
for (uint8_t zaehler=0; zaehler<=3; zaehler++)


Du deklarierst zaehler doppelt.. einmal als int (4byte) und einmal als 
uint8_t (1byte)

wundert mich aber, dass der compiler nicht motzt...

Autor: AlienX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mh.. also ich compilier mit Avr Studio, 0 warnings..

aber jetzt wo du es sagst.. dann schmeiß ich mal den int raus..

Jetzt sieht der Quelltext wie folgt aus..

Muss ich die Ports anders ansteuern damit er die Ports richtig 
freischaltet??

#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>

void delay_ms(uint16_t ms)
{
for (uint16_t t=0; t<=ms; t++)
_delay_ms(1);
}


int ebene, tab, turmcd;

/* Blinkfunktion beginn */

void blinken()
{
uint8_t zaehler;
zaehler=0;
for (zaehler=0; zaehler<=3; zaehler++)
{
PORTA = tab;
PORTB = ebene;
PORTD = turmcd;
_delay_ms(500);
PORTA = 0;
PORTB = 0;
PORTD = 0;
_delay_ms(200);

}
}

/*Blinkfunktion Ende */

//Globalvariablendeklaration
//int ebene, tab, turmcd;

//Hauptprogramm


int main()
{

//Variablendefinition

ebene=1;
tab=0;
turmcd=0;

DDRA=0xFF; // Turm A und B
DDRB=0xFF; // Ebene
DDRD=0xFF; // Turm C und D

for (ebene=1; ebene<=4; ebene++)
{
for (tab=0; tab<=8; tab++)
{
blinken();
}
for (turmcd=0; turmcd<=8; turmcd++)
{
blinken();
tab=0;
turmcd=0;
}
}

while (1)
{
PORTA = 0b11111111;
PORTB = 0b11111111;
PORTD = 0b11111111;
delay_ms (10000);
PORTA = 0b00001110;
PORTB = 0b00111100;
PORTD = 0b00111100;
delay_ms (500);
}


return 0;
}

Autor: hmmmmmmm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michi schrieb:
> Du deklarierst zaehler doppelt.. einmal als int (4byte) und einmal als
> uint8_t (1byte)
>
> wundert mich aber, dass der compiler nicht motzt...

wird die erste Variable nicht einfach überdeckt und der zweite zaehler 
ist nach der for wieder sichtbar?
-> C++

Autor: Michi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja also in der Portansteuerung sehe ich jetzt keinen Fehler.
Aber mich macht dieser Teil stutzig:

for (ebene=1; ebene<=4; ebene++)
{
   for (tab=0; tab<=8; tab++)
   {
       blinken();
   }
   for (turmcd=0; turmcd<=8; turmcd++)
   {
       blinken();
       tab=0;       //Warum setzt du jeden durchlauf tab auf 0?
       turmcd=0;    //Deine Bedinung ist, mach solange turmcd <=8 ist.
                    //aber du "resetest" jeden durchgang turmcd -> eine
                    //endlosschleife
   }
}

Autor: Michi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmmmmmm schrieb:
> wird die erste Variable nicht einfach überdeckt und der zweite zaehler
> ist nach der for wieder sichtbar?
> -> C++

Naja der GCC kann doch kein C++ oder?
Ich bin mir nicht zu 100% sicher, ob die variable überdeckt wird, aber 
im zweifelsfall würde ich micht nicht darauf verlassen.

Mich wunderts sowieso, dass er
for(int i=0; i<8;i++)
zulässt, da bei C imho die variable vor der schleife bereits deklariert 
sein muss

Autor: AlienX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, da hatte ich dann einen denkfehler als ich die geschweiften 
Klammern gesetzt habe, ich habe grad das Gefühl ich sehe den Wald vor 
lauter Bäumen nicht mehr.

Mh.. ja.. aber was ich mich gerade frage, kann ich einen INT auf einen 
Port schreiben und er gibt ihn mir dann richtig aus, muss ich da nicht 
eher eine Binär bzw. Hex Zahl schreiben??

also zum Beispiel

for(ebene=0x00; ebene<=0x0F; ebene+0x04) ??

Vielen Dank für die schnellen Antworten.

Autor: hmmmmmmm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michi schrieb:
> Naja der GCC kann doch kein C++ oder?

http://www.mikrocontroller.net/articles/AVR-GCC 2ter Absatz.

Autor: ozo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das macht schon der Compiler für dich. Ob du nun 0x10 oder dezimal 16 
schreibst, ist Reh wie Hirsch.

Autor: Michi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nö, da dir eh alles umgerechnet wird... wenn du zum beispiel

PORTA = 0x3A;
 schreibst, dann ist es genau das gleiche wie

PORTA = 0b00111010;

und das ist das genau das gleiche wie

PORTA = 58;

Da dein Port aber genau 8Bit breit ist (also 1 Byte) werden die oberen 3 
Byte deiner INT-Variable (die hat nämlich 4Byte) entweder abgeschnitten, 
oder es wird der überlauf in deinen Port geschrieben

Autor: Michi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmmmmmm schrieb:
> http://www.mikrocontroller.net/articles/AVR-GCC 2ter Absatz.

Alles klar.
Nur wie gesagt, ich würde mich nicht wetten trauen, das als Fehlerquelle 
auszuschließen... von der Übersichtlichkeit des Codes ganz zu schweigen

Autor: AlienX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mh.. also irgendwie komm ich grad nich mehr weiter...

scheint so als wär ich zu doof dafür grad..



Ja ich weiß die leserlichkeit..

Irgendwie hab ich da was verplant.. viel stückwerk gewesen.. dachte ich 
schreib das mal eben schnell un dann wurd es hier nichts und da nichts.. 
un so hat sich das dann über tage hingezogen..

ergebnis ist ja jetzt zu bewundern.. argh..

naja.. noch irgendwleche Ideen??


wenn er seine Routinen durch hat springt er inzwishcen wieder in die 
while schleife... nur die LED's wollen nicht angehen

Autor: ozo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja,
schreibs dir in Pseudocode auf ein Blatt Papier und übersetze es erst 
anschließend in c.
Also in der Art:

main:
initialisiere Ports
for all x 0...dimX
for all y 0...dimY
for all z 0...dimZ
blinkeLED(x, y, z)
rof
rof
rof

blinkeLED(u_int8 x, y, z):
for all c 0...3
LED_ON(x, y, z)
warte
LED_OFF(x, y, z)
warte
rof

Autor: hmmmmmmm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie steht es denn um die Genauigkeit des _delay ()? Ist mir gerade nicht 
im Detail bekannt, muss doch aber mit CPU oder Timer Takt angepasst 
werden?

Autor: AlienX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das delay passt, das sholt sich über das makefile den cpu Takt. das ist 
für die Anwendung hier ausreichend.

Werde mich heute nochmal dran setzen und das ganze verushcen neu zu 
Programmieren. die schleifen und die Inits werden umgemodelt. Und dann 
wird das ganze nochmal getestet..

Vielen Dank für eure Hilfe

Autor: Michael W (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo
Bin zwar spät dran, aber
int main()
{

//Variablendefinition

ebene=1;
tab=0;
turmcd=0;

macht zwar korrekterweise die ausführung der schleifen möglich, jedoch 
kennt deine funktion blinken() meiner Meinung nach die Werte dieser 
Variablen NICHT.
Schreibe dann lieber deine Funktion blinken() um wie folgt:
void blinken(uint8_t tab, uint8_t ebene, uint8_t turmcd)
{
    uint8_t zaehler;
    zaehler=0;
    for (zaehler=0; zaehler<=3; zaehler++)
    {
        PORTA = tab;
        PORTB = ebene;
        PORTD = turmcd;
        _delay_ms(500);
        PORTA = 0;
        PORTB = 0;
        PORTD = 0;
        _delay_ms(200);
    }
}

und rufe dann
blinken(tab, ebene, turmcd);
an all den bisherigen vorkommen von blinken() auf

Anndere Möglichkeit: Verwende diese Variablen GLOBAL

Hoff das bringt dich weiter

MFG

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AlienX schrieb:

> Er wird Folgendermaßen angesteuert, insgesamt laufen 20 Signalleitungen
> zu der Platine.
>
> Diese sind wie folgt belegt,
> -16 dieser Leitungen gehen an die verschiedenen Fußpunkte eines LED
> Türmchens, d.h. immer 4 LED's übereinander hängen an einem Port
> -4 dieser Leitungen schalten die Masse für die verschiedenen Ebenen
> durch.


Wie sieht deine Verdrahtung konkret aus?
Wie ist da der Zusammenhang mit den Portpins?

Sind da zb in den Ebenen 8-aus-3-Dekoder drinnen?
(Du verwendest 'ebene' bzw damit den PORTB als ob da welche wären)

> Ja ich weiß die leserlichkeit..

Dann tu was dagegen! Jammern bringt dich nicht weiter. Das absolute 
Minimum ist, das deine Einrückungen stimmen. Dass dein Code 
fehlerverseucht ist, wundert mich kein bischen.


Fang nicht damit an gleich mal alle LED nacheinander blinken zu lassen.
Fang damit an, 1 LED aufleuchten zu lassen. Wie müssen dann laut deinem 
Schaltplan die Portbits stehen? Stell sie ein, nimm ein Multimeter und 
verfolg das in deiner Schaltung.
Auch du machst den Kardinalfehler: Du gehst davon aus, dass du ein 
relativ komplexes Gebilde auf Anhieb fehlerfrei hinkriegst. Und damit 
meine ich sowohl Hardware als auch Software.

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.