Hallo,
ich habe in den letzten Wochen mir ein 20x7 LED Display aufgebaut und
momentan propleme bei der Programmierung.
Den Schaltplan und Quelcode hab ich aus dem Buch "AVR Hardeware und
C-Programmierung in der Praxis" von Florian Schäffer.
Feines Buch für Anfänger übrigens...
Verwendete Bauteile
CD74HCT164E Schieberegister für die Spalten
ULN2003A für die Zeilen
TA20-11CGKWA DOT MATRIX Anzeige 5x7 LED mit gemeinsame Anode
volatileuint8_tmemory[Spalten];// Speicher für Display, Spaltenweise
19
// orientiert, Index 0=links
20
21
voidset_row(uint8_trow)
22
{
23
uint8_ti;// Alle Spalten des Displays durchlaufen
24
// Mit rechten Spalte beginnen
25
for(i=Spalten-1;i>=0;i--)
26
{
27
if((memory[i]>>(6-row))&1)// Bit in der Spalte an der übergebenen Zeile gesetzt?
28
{
29
PORTC|=(1<<PC4);// Data Bit setzen
30
}
31
else
32
{
33
PORTC&=~(1<<PC4);// Data Bit löschen
34
}
35
PORTC|=(1<<PC5);// Takt HIGH -> Flanke => schreiben
36
PORTC&=~(1<<PC5);// Takt LOW
37
}
38
}
39
40
voidwrite_rows()
41
{
42
uint8_ti;
43
44
for(i=0;i<=6;i++)// Alle Zeilen durchlaufen
45
{
46
PORTB=0;// alle Zeilen aus
47
set_row(i);// Daten für aktuelle Zeile in Schieberegister schieben
48
PORTB=(1<<i);// aktuelle Zeile an
49
_delay_ms(2);// Zeile Leuchten lassen
50
}
51
}
52
53
intmain(void)
54
{
55
56
// *** Ausgänge definieren und ausschalten ***
57
DDRC|=(1<<PC4)|(1<<PC5);// PC4 und PC5 als Ausgang
58
// PORTC &=~((1<<PC4) | (1<<PC5)); // PC4 und PC5 aus
59
DDRB=0xFF;// PortB als Ausgang
60
// PORTB = 0; // PortB aus
61
62
lcd_init();// LCD aktivieren
63
lcd_clear();
64
65
lcd_setcursor(2,2);
66
lcd_string("20x7 LED Matrix");
67
lcd_setcursor(3,4);
68
lcd_string("Muster ausgeben");
69
70
// beliebeiges Muster Spaltenweise definieren
71
// Spalte = -7654321
72
memory[0]=0b01111110;
73
memory[1]=0b01010101;
74
memory[2]=0b00101010;
75
memory[3]=0b01010101;
76
memory[4]=0b01010101;
77
memory[5]=0b01100110;
78
memory[6]=0b00011001;
79
memory[7]=0b01001100;
80
memory[8]=0b01100110;
81
memory[9]=0b01111111;
82
memory[10]=0b01010101;
83
memory[11]=0b00101010;
84
memory[12]=0b01010101;
85
memory[13]=0b00101010;
86
memory[14]=0b00011100;
87
memory[15]=0b01111001;
88
memory[16]=0b01001001;
89
memory[17]=0b01001001;
90
memory[18]=0b01001001;
91
memory[19]=0b01001111;
92
93
while(1)
94
{
95
write_rows();
96
}
97
return0;
98
}
Den Code hab ich soweit vom Buch abgeschrieben und auf 20 Zeilen
geändert(Buch waren nur 15Zeilen) doch nix tat sich hinterher, keine LED
war an.
Ich hab momentan in einem Testprogramm die Zeilen einzeln ein und
ausgeschalten, sprich
while(1)
{
PORTB |=(1<<PB0);
_delay_ms(500);
PORTB &=~ (1<<PB0);
_delay_ms(500);
}
und siehe da es leuchtet die erste Zeile, allerdings komplett alle 20.
Auch die restlichen Zeilen (PB1 bis PB6) leuchten alle LEDs auf.
Nun ist meine Frage, kann der oben gezeigte Code so funktionieren,
zumindest sollte das ja laut Buch, oder hab ich doch noch irgendwo einen
Fehler übersehen ?
Würde mich freuen wenn ihr mir weiterhelfen könntet.
Liebe Grüße Hendrik
@ Hendrik Brade (hendrik_b456)
>Den Schaltplan und Quelcode hab ich aus dem Buch "AVR Hardeware und>C-Programmierung in der Praxis" von Florian Schäffer.>Feines Buch für Anfänger übrigens...
OK, aber wir haben das nicht, genausowenig wie einen Schaltplan. der ist
aber wichtig. Siehe Netiquette.
>void set_row (uint8_t row)>{> uint8_t i; // Alle Spalten des Displays durchlaufen> // Mit rechten Spalte beginnen> for (i=Spalten-1; i>=0; i--)
Das knallt. ein uint8_8 ist IMMER >=0. besser so, ohne u!
> int8_t i; // Alle Spalten des Displays durchlaufen> {> if ((memory[i] >>(6-row)) & 1) // Bit in der Spalte an der übergebenen Zeile
gesetzt?
> {
Kann man so machen, ist aber lahm. Dein Problem liegt woanders.
>und siehe da es leuchtet die erste Zeile, allerdings komplett alle 20.
Zuerst solltest du mal zwischen Zeilen und Spalten unterscheiden,
sprachlich wie auch gedanklich!
>Auch die restlichen Zeilen (PB1 bis PB6) leuchten alle LEDs auf.
Das warf nicht sein, es muss immer nur eine Zeile leuchten. Ansonsten
hast du möglicherweise einen Hardwarefehler.
>Nun ist meine Frage, kann der oben gezeigte Code so funktionieren,>zumindest sollte das ja laut Buch, oder hab ich doch noch irgendwo einen>Fehler übersehen ?
Bis auf sie Sache mit dem uint sollte das passen.
Danke für die schnelle Antwort und ich bitte um Verzeihung, hatte heute
Morgen im der Eile den schaltplan ganz vergessen. Hab ihn jetz nur mit
dem Handy fotografiert aus dem Buch heraus.
Die Zeilen werden über den Zeilentreiber ULN2003AN geschalten
(wagerecht).
Die Spalten werden über die Schieberegister 74HCT164 geschalten
(senkrecht).
Danke, das hab ich übersehen,bzw. falsch abgeschrieben vom Buch,
soll auch int8_t i lauten.
Wie gesagt ist ja nur ein Beispielprogramm was die Funktion der
Schieberegister verdeutlichen soll, sicherlich gibt es bessere
möglichkeiten das zu schreiben. Paar Seiten Weiter geht es ja dann
weiter mit Textausgabe. Wie gesagt Anfängerbuch mit vielen Beispielen.
Auch die restlichen Zeilen (PB1 bis PB6) leuchten alle LEDs auf.
Ich meinte damit nur das ich testweise alle Pins an Port B nacheinander
auf 1 gesetzt habe, um festzustellen ob ich irgendwas falsch gelötet
habe. Ich war halt erstaund das wagerecht alle 20 LEDs leuchten.
Grüße Hendrik
Guten Morgen,
kann das obrige Bild allerdings nicht mehr löschen, bzw. bearbeiten.
Hier nun mein Schaltplan.
ATmega8 PB0 - PB6 ---> ULN2003AN
ATmega8 PC4 ---> 74HCT164 Pin DS1 und DS2 (DATA)
Atmega8 PC5 ---> 74HCT164 Pin CLK (Takt)
Grüße Hendrik
@ Hendrik B. (hendrik_b456)
> 20x7_Matrix.png>ATmega8 PB0 - PB6 ---> ULN2003AN>ATmega8 PC4 ---> 74HCT164 Pin DS1 und DS2 (DATA)>Atmega8 PC5 ---> 74HCT164 Pin CLK (Takt)
OK, damit ist das nun klar. Aber das Problem bleibt das Gleiche.
Zuerst musst du prüfen, ob du die ZEILEN einzeln schalten kannst.
Sprich, lade in das Schieberegister 3x0xFF und schalte danach die Zeilen
einzeln durch. Die müssen dann einzeln leuchten. Zum Glück sind die
Widerstände für die LEDs schwach dimensioniert, dort fließen maximal
13mA/Spalte, in Summe 260mA pro Zeile. Das hälten die LEDs problemlos
aus, auch ohne Multiplexing.
eigentlich reicht es, die Pause von _delay_ms(2) auf _delay_ms(500) zu
ändern, dann sieht man das.
Also!
Hallo Falk,
Die Wiederstände hab ich auf 150ohm hochgesetzt, da mir die 100ohm laut
Buch etwas zu wenig waren. Der ULN2003 verträgt pro Ausgang 500mA.
Ich hatte bereits die Schieberegister so getestet
while(1)
{
PORTC |= (1<<PC4); // Bit 1 Setzen
PORTC |=(1<<PC5); // Takt HIGH -> Flanke => schreiben
PORTC &=~(1<<PC5); // Takt LOW
PORTC |= (1<<PC4); // Bit 1 Setzen
PORTC |=(1<<PC5); // Takt HIGH -> Flanke => schreiben
PORTC &=~(1<<PC5); // Takt LOW
PORTC |= (1<<PC4); // Bit 1 Setzen
PORTC |=(1<<PC5); // Takt HIGH -> Flanke => schreiben
PORTC &=~(1<<PC5); // Takt LOW
PORTC &=~ (1<<PC4); // Bit 0 Setzen
PORTC |=(1<<PC5); // Takt HIGH -> Flanke => schreiben
PORTC &=~(1<<PC5); // Takt LOW
for (i=0; i<=6; i++) // Alle Zeilen durchlaufen
{
PORTB = 0; // alle Zeilen aus
PORTB = (1 << i); // aktuelle Zeile an
_delay_ms(2); // Zeile Leuchten lassen
}
}
Es leuchten so jeweil 3 Spalten und die 4. bleibt aus.
@ Hendrik B. (hendrik_b456)
>Die Wiederstände hab ich auf 150ohm hochgesetzt, da mir die 100ohm laut>Buch etwas zu wenig waren.
100 Ohm gehen auch, erst recht beim aktiven Multiplexing.
> Der ULN2003 verträgt pro Ausgang 500mA.
Ja, aber nicht an allen Ausgängen gleichzeitig.
>Ich hatte bereits die Schieberegister so getestet
Auch als Hobbyprogrammierer wirst du nicht nach der Anzahl der Zeilen
bezahlt oder bewertet. Also nutze sinnvollerweise Schleifen. Dein
Programm oben ist nahezu korrekt. Jetzt heißt es, den Fehler zu finden.
>Es leuchten so jeweil 3 Spalten und die 4. bleibt aus.
Leuchten den die 7 Zeilen einzeln, wenn du die Pause auf 500ms
verlängerst?
Falk B. schrieb:> Leuchten den die 7 Zeilen einzeln, wenn du die Pause auf 500ms> verlängerst?
ja leuchten schön der Reihe nach einzeln
Falk B. schrieb:> Hobbyprogrammierer
lach, glaub soweit bin ich noch lange nicht das ich mich so bezeichnen
kann.
Ich erarbeite mir alles mit dem was ich bereits weiß und nehme neues
dazu.
Bis jetzt hat ja auch alles aus dem Buch funktioniert, "7 Segmentanzeige
Multiplexing" z.B.
Nur bei diesem Thema ist der Wurm irgendwo versteckt und bis auf das
eine "u" hab ich ja alles mehr oder weniger abgeschrieben, Quellcode
steht ja im Buch, bzw. auch online downloadbar.
@ Hendrik B. (hendrik_b456)
>> Leuchten den die 7 Zeilen einzeln, wenn du die Pause auf 500ms>> verlängerst?>ja leuchten schön der Reihe nach einzeln
Gut, dann kannst du ja dein Ursprungsprogramm in Betieb nehmen, aber
immer noch mit 500ms Pause. Dann siehst du die Muster der einzelnen
Zeilen aufleuchten. Wenn das passt, dann wieder 2ms und du siehtst alles
auf einmal.
Danke , super es funktioniert einwandfrei jetzt. Vermute mal das vorher
das Muster nicht richtig zugeordnet werden konnte... egal jetzt gehts
und ich bin erstmal ein Stück weiter.
Nochmals vielen Dank