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


von AlienX (Gast)


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;
}

von Michi (Gast)


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

von ozo (Gast)


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

von AlienX (Gast)


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

von Michi (Gast)


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

von AlienX (Gast)


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;
}

von hmmmmmmm (Gast)


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

von Michi (Gast)


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

von Michi (Gast)


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

von AlienX (Gast)


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.

von hmmmmmmm (Gast)


Lesenswert?

Michi schrieb:
> Naja der GCC kann doch kein C++ oder?

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

von ozo (Gast)


Lesenswert?

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

von Michi (Gast)


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

von Michi (Gast)


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

von AlienX (Gast)


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

von ozo (Gast)


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

von hmmmmmmm (Gast)


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?

von AlienX (Gast)


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

von Michael W (Gast)


Lesenswert?

Hallo
Bin zwar spät dran, aber
1
int main()
2
{
3
4
//Variablendefinition
5
6
ebene=1;
7
tab=0;
8
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:
1
void blinken(uint8_t tab, uint8_t ebene, uint8_t turmcd)
2
{
3
    uint8_t zaehler;
4
    zaehler=0;
5
    for (zaehler=0; zaehler<=3; zaehler++)
6
    {
7
        PORTA = tab;
8
        PORTB = ebene;
9
        PORTD = turmcd;
10
        _delay_ms(500);
11
        PORTA = 0;
12
        PORTB = 0;
13
        PORTD = 0;
14
        _delay_ms(200);
15
    }
16
}

und rufe dann
1
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

von Karl H. (kbuchegg)


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.

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.