Hallo Leute,
ich sitze hier gerade und steh total auf dem Schlauch.
Zum Problem:
Ich habe eine LED Matrix aus 32 7x5 LED Bausteinen. Jetzt möchte ich
eigentlich nur das Zeile für Zeile angeschalten wird und die vorherige
Zeile auch an bleibt. Wenn ihr unten meinen Code betrachtet werdet ihr
sehen, das es momentan für 7 Zeilen einfach durchläuft. Jetzt hätte ich
aber gerne, das wenn die Schleife durchlaufen ist alle 7 Zeilen
leuchten. Es soll immer eine mehr dazukommen.
Für Tipps bin ich euch dankbar, wie gesagt bin gerade total verwirrt und
hab auch momentan keinen Lösungsansatz mehr bereit. Alle versuche sind
bis jetzt gescheitert oder führten nicht zu einem ferfolgreichen
Ergebnis.
1
#include<avr/io.h>
2
#include<util/delay.h>
3
4
5
intmain(void)
6
{
7
DDRA=0xff;
8
DDRC=0xff;
9
DDRB=0xff;
10
11
inti,z;
12
13
PORTB|=(1<<PB2)|(1<<PB4);// Schieberegister SRCLR, RCLR auf High
14
PORTB|=(1<<PB0);// logische 1 wird in das Schieberegister gegeben
15
PORTC|=(1<<PC5);// D-Ausgang des Multiplexer auf 1
16
while(1)
17
{
18
19
for(i=0;i<=40;i++)
20
{
21
PORTB|=(1<<PB1);// Schieberegister SRCLK, RCLK im Wechsel High => Low (Takt)
Kann es sein, dass die Zeilen über einen 8-aus-3 Dekoder angesteuert
werden? Zumindest lässt dein Code das so vermuten.
Wenn ja, dann hast du so überhaupt keine Chance, weil per
Hardware-Design immer nur eine Zeile leuchten kann.
Du musst die Zeilen multiplexen!
Ja ist korrekt, ich benutze für die Zeilen Ansteuerung einen 8-aus-3
Dekoder (74HC138). Für die Spalten nehme ich 5 Schieberegister.
Das heißt ich kann mit meiner Schaltung nicht mehrere Zeilen leuchten
lassen, so ich es mir ursprünglich gedacht hatte??
M.Hauser wrote:
> Das heißt ich kann mit meiner Schaltung nicht mehrere Zeilen leuchten> lassen, so ich es mir ursprünglich gedacht hatte??
Exakt gleichzeitig nicht.
Aber du kannst die Zeilen so schnell hintereinander einschalten, dass
ein Mensch nicht merkt, dass nur 1 Zeile leuchtet. Genau das nennt man
Multiplexen.
Edit: Ist ja auch nicht schlimm, dass du nicht mehrere Zeilen exakt
gleichzeitig leuchten lassen kannst. Den Fall, dass alle Zeilen genau
dasselbe Muster anzeigen sollen, hast du ja in der Praxis nicht. Das ist
ja jetzt nur aus deiner speziellen 'Ich-probier-mal-was'-Situation
heraus entstanden.
Edit2:
Sag mal, was hast du denn da für einen Saustall bei der Adressierung der
Zeilen veranstaltet? Da ist ja überhaupt kein System drinn. Warst du so
in Routing-Nöten, dass du die Leitungen wild durcheinander würfeln
musstest?
>Aber du kannst die Zeilen so schnell hintereinander einschalten, dass>ein Mensch nicht merkt, dass nur 1 Zeile leuchtet. Genau das nennt man>Multiplexen.
Das habe ich versucht, ich bin folgendermaßen vorgegangen:
Zeile für Zeile schnell anschalten, nur wenn ich in der _delay-Funktion
einen kleineren Wert eingebe, dann habe ich nur ein schwaches flackern
in den jeweiligen Zeilen. Bekomme ich das irgendwie anders in den Griff?
>Den Fall, dass alle Zeilen genau>dasselbe Muster anzeigen sollen, hast du ja in der Praxis nicht. Das ist>ja jetzt nur aus deiner speziellen 'Ich-probier-mal-was'-Situation>heraus entstanden.
Leider doch. Ich benötige den Fall, das Zeile für Zeile angeschalten
wird(immer mit dem selben Spaltenmuster)und die vorher geschaltene
wieder leuchtet. Am Ende sollen alle 28 Zeilen leuchten. Nicht
gleichzeitig aber eben so das man nicht erkennt das diese nacheinander
angeschaltet werden, wo wir wieder beim Multiplexen wären.
M.Hauser wrote:
>>Aber du kannst die Zeilen so schnell hintereinander einschalten, dass>>ein Mensch nicht merkt, dass nur 1 Zeile leuchtet. Genau das nennt man>>Multiplexen.>> Das habe ich versucht, ich bin folgendermaßen vorgegangen:> Zeile für Zeile schnell anschalten, nur wenn ich in der _delay-Funktion> einen kleineren Wert eingebe, dann habe ich nur ein schwaches flackern> in den jeweiligen Zeilen. Bekomme ich das irgendwie anders in den Griff?
Mit delay wird das sowieso nichts.
Was du brauchst ist ein Timer, der einen regelmässigen Interrupt
generiert. In der ISR wird dann reihum immer die nächste Zeile mit
Werten versorgt und eingeschaltet.
> Leider doch. Ich benötige den Fall, das Zeile für Zeile angeschalten> wird(immer mit dem selben Spaltenmuster)und die vorher geschaltene> wieder leuchtet. Am Ende sollen alle 28 Zeilen leuchten. Nicht> gleichzeitig aber eben so das man nicht erkennt das diese nacheinander> angeschaltet werden, wo wir wieder beim Multiplexen wären.
Willst du nicht Buchstaben oder Grafiken ausgeben?
Oder ist die einzige Anwendung deiner Matrix darin, so einen Vorhang
Effekt zu erreichen? Den hättest du auch einfacher haben können :-)
Du solltest Dich mal mit den Grundlagen der Matrixansteuerung vertraut
machen. Und wie das Softwareseitig angesteuert wird. Mit Timern, ohne
delay.
Sieh dazu hier im Tutorial
>Willst du nicht Buchstaben oder Grafiken ausgeben?>Oder ist die einzige Anwendung deiner Matrix darin, so einen Vorhang>Effekt zu erreichen?
Ich muss auch Buchstaben ausgeben aber in erster Linie sollte der
"Vorhand Effekt" funktionieren.
>Wie sieht deine Hardware aus?>Wie ist das Schieberegister angeschlossen?
Als Controller verwende ich einen Atmega16. 5 Schieberegister (74HC594)
sind an PortB angeschlossen und kaskadiert. Für die Zeilen benutze ich,
wie oben schon erwähnt vier 3 zu 8 Decoder an Port A und C angeschlossen
(74HC138).
M.Hauser wrote:
> Als Controller verwende ich einen Atmega16. 5 Schieberegister (74HC594)> sind an PortB angeschlossen und kaskadiert.
Welcher Pin ist SCLK und welcher RCLK?
Kann das aus deinem Code nicht entnehmen.
M.Hauser wrote:
> sind an PortB angeschlossen und kaskadiert. Für die Zeilen benutze ich,> wie oben schon erwähnt vier 3 zu 8 Decoder an Port A und C angeschlossen> (74HC138).
Das war keine so gute Idee eine Zeile in 4 Teile zu zerteilen.
Das bedeutet, dass du einen 28:1 Multiplex brauchst. Das könnte
a) vom Timing her schon mächtig eng werden
b) die Leds werden fast bis zur Unkenntlichkeit dunkel sein.
Welche Prozessorfrequenz benutzt du?
>Welche Prozessorfrequenz benutzt du?
Interner Oszillator 1Mhz
>Welcher Pin ist SCLK und welcher RCLK?>Kann das aus deinem Code nicht entnehmen.
SCLK ist PB1
RCLK ist PB3
M.Hauser wrote:
>>Welche Prozessorfrequenz benutzt du?>> Interner Oszillator 1Mhz
Mal etwas rechnen.
Mit dem Timer0 kannst du im besten Fall alle 256 Taktzyklen einen
Interrupt auslösen lassen.
1000000/256 = 3906.25 Interrupts pro Sekunde
3906.25/28 = 139.5 Hz
Das wäre an und für sich noch akzeptabel. 139Hz Refreshfrequenz pro
Matrixteil.
Aber: Du hast für jeweils ein Ausgabepaket nur 256 Takte Zeit zur
Verfügung. 40 Bit aus dem Speicher schaufeln und auf die Schieberegister
ausgeben, Schleifenverwaltung und alles drum herum ... dazu reicht die
zur Verfügung stehende Zyklenzahl nicht. Wenn ich mich nicht verzählt
habe, dann brauchst du dafür mindestens 320 Zyklen (und das hab ich
jetzt nur grob im Kopf überschlagen, genaueres kann man erst sagen, wenn
die ISR steht).
Also gehts nur mit einem Vorteiler im Timer. Der nächst mögliche
Vorteiler im Timer 0 ist 8. Damit kriegst du von einer ISR zur nächsten
immerhin ein Polster von 256 * 8 = 2048 Taktzyklen. Das sollte
überschlagsmässig reichen.
Aber die Refreshfrequenz
1000000/256/8/28 = 17
17Hz ist zuwenig. Das flackert wie Sau.
-> Du musst was mit den 1Mhz machen. Damit wirst du nicht glücklich
werden.
Und ob die Led bei einem 28:1 Multiplex noch einigermassen lesbar
leuchten? Meine Hand würd ich nicht dafür ins Feuer legen. Mit welchem
Strom gehst du denn an eine Led ran? Rein rechnerisch müsstest du mit so
um die 280 bis 300mA in eine LED reinbuttern (pro LED hab ich mal 10mA
Konstantstrom angenommen). Wehe wenn da mal der Multiplex ausfällt. Dann
sterben die LED wie die Fliegen. Und ob die LED diesen Spitzenstrom
überhaupt mitmachen ... Datenblatt gibt Auskunft.
Aber seis drum:
Ich versuch mal hier im Trockendock, ob ich dir was zusammenstellen
kann.
>Mit welchem Strom gehst du denn an eine Led ran?
gut 400mA
Die einzelnen Zeilen leuchten schön erkennbar auf, wenn ich mit dem
oberen Code das ganze ansteuer.
Soll ich vielleicht noch einen externen Quarz an den Controller hängen?
12Mhz hätte ich da grad auf Lager.
M.Hauser wrote:
>>Mit welchem Strom gehst du denn an eine Led ran?>> gut 400mA>> Die einzelnen Zeilen leuchten schön erkennbar auf, wenn ich mit dem> oberen Code das ganze ansteuer.
Da ist ja auch noch kein Multiplex drauf!
Im Endeffekt sind deine einzelnen Zeilenfragmente nur 1/28 der
kompletten Zeit eingeschaltet!
In einer Sekunde ist jede LED nur 30 Millisekunden an und 970
Millisekunden auf jeden Fall aus. Vielleicht kannst du dir jetzt
vorstellen, was das für die Helligkeit heissen wird.
> Soll ich vielleicht noch einen externen Quarz an den Controller hängen?> 12Mhz hätte ich da grad auf Lager.
Auf jeden Fall. Das befreit dich ein wenig aus der Zeitnot die entstehen
wird.
Jag das mal durch den Compiler. Ich hab hier kein AVR-Studio und kein
WinAvr installiert. Der Code wurde daher nicht compiliert und auch nicht
getestet. Gut möglich dass kleine Flüchtigkeitsfehler drinnen sind.
Von den 160 möglichen Spalten kümmert sich der Code nur um die ersten
40.
1
#include<avr/io.h>
2
#include<util/interrupt.h>
3
#include<util/delay.h>
4
#include"inttypes.h"
5
6
// Displayorganisation
7
// Jedes Byte stellt eine Spalte dar. Das komplette Display ist
8
// 32*5 (=160) Spalten breit
9
// Der Index ins Array ist also die x-Koordinate eines Punktes
10
// Die Bits 0 bis 6 stellen die y-Koordinate des Punktes dar.
11
// Bit 7 eines jeden Bytes bleibt unbenutzt.
12
//
13
// Grund: Das Timing ist so schon verdammt eng. Es bleibt keine Zeit für
14
// aufändige Optimierungsversuche so dass jedes Bit benutzt
M.Hauser wrote:
> Hm....hab den Code mal so übernommen. Die ersten 7 Zeilen sind jetzt an,> nur eben fast nicht sichtbar und mit einem höllischen flackern.
Geh mal mit den 100 MilliSekunden in der Hauptschleife höher. Da war ich
etwas zu knausrig. Damit kann man das Flackern vom Multiplexen nicht
mehr vom Flackern der Malroutine unterscheiden. Mit 1000 sollte sich
eigentlich ein ruhigeres Bild ergeben. Die 7 Zeilen müssen sich eine
nach der anderen dazuschalten mit jeweils einer 1 Sekunden Pause
dazwischen. Sind alle 7 Zeilen da, wird die komplette Anzeige gelöscht
und das Spielchen geht von vorne los.
>Die 7 Zeilen müssten sich eine nach der anderen dazugeschaltet haben,>wenn du das nicht siehst, dreh mal die 100 Millisekunden in der>Hauptschleife hoch
Habe ich gemacht, doch die LEDs fangen alle gleichzeitig an zu flackern
:(
Kann ich in den Fuses Einstellungen im AVR-Studio den Internen 8Mhz
Oszillator auswählen?
(Int RC Osc. 8 MHz; Start-up time: 6CK + 64 ms)
M.Hauser wrote:
> Stopp>> War doch noch nicht Perfekt der Code.
:-)
Wundert mich nicht wirklich. Mangels Compiler konnte ich ihn nie
compilieren.
> Der Compiler meckert gerade an dem>
1
#include<util/interrupt.h>
> rum.
Fehlermeldung?
>> Und noch etwas was ich nicht ganz versteh. Was ist das?>
Sorry.
Hab mir gerade AVR-Studio und WinAvr gezogen.
Aber auf dieser Vista-Maschine funktioniert das Zeugs nicht (warum auch
immer) und ich hab jetzt nicht die Zeit diesem Problem nachzugehen.
Werds in der Nacht mal auf meiner Entwicklungsmaschine zu Hause
probieren. Dort funktioniert AVR-Studio/WinAvr
Kann aber nicht viel sein. Immerhin hattest du ja schon mal ein paar
Leds am Leuchten. Alternativ kannst du ja mal selbst im Simulator
nachsehen, ob die richtigen Pins zum richtigen Zeitpunkt wie erwartet
ihren Zustand wechseln. Breakpoint in die ISR setzen und mit F10
durchsteppen und im I/O View die Portpins beobachten.
Fährst du eigentlich schon auf 8Mhz?
Habe das Beispiel (dankbarerweise) gleich benutzt, um mein neues
Linuxenvironment zu testen :-)
Ein paar Kleinigkeiten sind schon angesprochen worden
("avr/interrupt.h"). Für "trockenes" Coding wirklich bemerkenswert, Hut
ab! :-)
Wenn dennoch nichts passiert könnte es auch noch daran liegen:
* Statt TCCR0 ("Null" hinten) stand TCCRO ("Oh" hinten) im Code von Karl
Heinz (zumindest ergab sich das bei mir beim herauskopieren). Das SFR
ist wichtig, sonst läuft der Timer nicht los und es gibt keine
Interrupts. Unbedingt richtig setzen.
* CurRow wird IMHO nicht initialisiert. Wenn der Wert beim Start im
Speicher zufällig größer 7 ist, geht das setzen der Zeile danach schief
und der Arrayzugriff geht "ins Leere" (ev. crash). Zumindest dauert es
einige increments, bis er sich fängt.
Entweder vor "sei()" (unbedingt davor) noch ein "CurRow=0;" im Code
einfügen. Zusätzlich würde ich die Abfrage in der ISR von "if( CurRow ==
7 )" auf "if( CurRow > 6 )" ändern, dann "fängt" sich die ISR auch
selbst.
Ist aber auch nur mal kompiliert + grob überprüft. Bei Bedarf kann ich
den Code auch gerne anhängen, aber ich denke dass hast Du ja im Griff.
Hope it helps. :-)
Hmm. Hab gestern in der Nacht noch ein paar Runden im Simulator gedreht
und hab die Portpins beobachtet.
Da ist mir nichts aufgefallen. Eigentlich sollte das klappen.
Angenommene Pins an PortB
PB0 Datenleitung zu den Schieberegistern
PB1 SCLK Leitung der Schieberegister
PB3 RCLK Leitung der Schieberegister
Angenommene Pins an PortA
PA0 - PA3 sind die Leitungen die zum 8-aus-3 Dekoder gehen
Der Dekoder ist so verschaltet, dass ein Datenwort von
PA3 PA2 PA1 PA0
1 0 0 0 Zeile 1
1 1 0 0 Zeile 2
0 1 1 0 Zeile 3
1 0 1 0 Zeile 4
0 0 0 0 Zeile 5
0 1 0 0 Zeile 6
0 0 1 0 Zeile 7
anspricht. Diese Zuordnung hab ich mir aus dem ursprünglichen Programm
zusammengesucht und ich geh davon aus, dass das auch so stimmt.
Die ISR wird aufgerufen, ich kann in der Simulation sehen, dass die Bits
entsprechend rausgetaktet werden und ein abschliessender RCLK Puls
kommt. Was jetzt sein könnte: Das die Puls etwas zu kurz ausfallen. Da
könnte man mal ein zusätzliches NOP einfügen. Glauben tu ich aber
ehrlich gesagt nicht daran. Hab schon Schieberegister mit 12Mhz full
speed angefahren und hat tadellos geklappt.
Auch die Leitungen am Port A werden nacheinander auf die oben
angegebenen Werte gebracht.
Was man jetzt mal machen könnte: Den Timer Vorteiler auf einen sehr
grossen Wert setzen (1024, ergibt knapp 4 ISR Aufrufe in der Sekunde)
und mit einem Messgerät (kann auch eine einzelne Led+Vorwiderstand
sein), mal die A-Leitungen beobachten. Da müsste man deutlich Blinken
sehen. Auch an den Ausgängen des 3-zu-8 Dekoders müsste man mit einer
Led sehen können, wie nacheinander ein Ausgang nach dem anderen aktiv
wird. Damit könnte man mal sicher gehen, dass dieser Teil funktioniert.
Durch den grossen Vorteiler gewinnt man dann etwas Zeit in der ISR und
könnte mal testweise(!) bei der Pulsgenerierung (SCLK bzw. RCLK)
zwischen dem Setzen und dem Rücksetzen einen delay einbauen. Sinn der
Sache ist es wieder direkt am Pin mit einem Messgerät (Led) die Pulse zu
sehen und auch nachzusehen, was am Datenausgang rauskommt.
Du siehst schon. Testen bedeutet hier sich die Dinge soweit zu
verlangsamen, dass man extern mit irgendwelchen geeigneten Messmitteln
was sehen kann. Vielleicht hast du ja auch ein Oszi zur Verfügung, das
wär natürlich optimal. Aber das hättest du wahrscheinlich auch ohne mich
schon mal an die Ausgänge angehängt um zu sehen was da abgeht.
Wie gesagt: Im Simulator sieht alles gut aus. Wenn ich die Hardware aus
deinem Originalprogramm richtig rekonstruiert habe, sollte es eigentlich
klappen.
Noch was: Wenn die Verlangsamung dann immer noch nicht reicht, dann kann
man die ISR noch weiter verlangsamen:
1
uint8_tISRCnt=0;// :-)
2
3
ISR(...)
4
{
5
ISRCnt++;
6
if(ISRCnt<10)
7
return;
8
ISRCnt=0;
9
10
....weiterwiegehabt
Damit wird dann nur noch alle 2.5 Sekunden (Vorteiler 1024) eine neue
Zeile ausgegeben (und entsprechend die A-Leitungen umgeschaltet)
Wolfgang Scherr wrote:
> * Statt TCCR0 ("Null" hinten) stand TCCRO ("Oh" hinten) im Code von Karl> Heinz (zumindest ergab sich das bei mir beim herauskopieren). Das SFR> ist wichtig, sonst läuft der Timer nicht los und es gibt keine> Interrupts. Unbedingt richtig setzen.
Yep. Hab ich im Editor nicht gesehen. Ist immer wieder ein leidiges
Problem 0 und O, l und 1
Da stolpert aber der Compiler drüber, sollte also kein Problem gewesen
sein.
> * CurRow wird IMHO nicht initialisiert.
Doch wird es.
Globale Variablen werden in C immer auf 0 initialisiert, wenn nichts
anderes angegeben.
> Entweder vor "sei()" (unbedingt davor) noch ein "CurRow=0;" im Code> einfügen.
Schaden kanns nicht.
> Zusätzlich würde ich die Abfrage in der ISR von "if( CurRow ==> 7 )" auf "if( CurRow > 6 )" ändern, dann "fängt" sich die ISR auch> selbst.
Das ist sowieso immer eine gute Idee (=defensiv programmieren).
Danke für den Fix.
>Sag mal, was hast du denn da für einen Saustall bei der Adressierung der>Zeilen veranstaltet? Da ist ja überhaupt kein System drinn. Warst du so>in Routing-Nöten, dass du die Leitungen wild durcheinander würfeln>musstest?
Da ist schon ein System drin etwas verwirrend geb ich zu aber man kommt
damit zurecht. PA0 ist ein analloger Eingang, somit hab ich den nicht
nochmal verwendet.
Decoder 1 hängt an PA1, PA2 ,PA3
Decoder 2 hängt an PA4, PA5 ,PA6
Decoder 3 hängt an PA7, PC0, PC1
Decoder 4 hängt an PC2, PC3, PC4
Data an PC5
LE an PC6
ME an PC7
______________________________________________________________________
hab den Code nochmals nach euren Empfehlungen geändert, doch leider
leuchtet immernoch nichts auf meinem Display auf :(
Hast du schon kontrolliert, ob die ISR überhaupt aufgerufen wird
(innerhalb der ISR einfach irgendeine andere LED einschalten oder einen
Pin auf High oder Low setzen. Irgendwas tun, so dass du von aussen mit
einem Messgerät sicher sagen kannst: Ja die ISR wird aufgerufen)
Hast du dich vielleicht vertan und SCLK und RCLK vertauscht?
Warte mal.
Was hat es damit
PORTB |= (1<<PB2) | (1<<PB4); // Schieberegister SRCLR, RCLR auf High
PORTC |= (1<<PC5); // D-Ausgang des Multiplexer auf 1
auf sich.
PORTC wird in meinem Programm nicht benutzt und um PB2 und PB4 hab ich
mich nicht gekümmert.
Hallo Laute,
so hat ein wenig länger gedauert aber jetzt bin ich mal wieder am
rumwerkeln.
Habe mit ein Oszi besorgt und mal die Eingänge des Decoders sowie die
Schieberegister angeschaut.
Die Schieberegister sehen super aus vom Timing. Sprich 40 Bits laden und
dann RCLR auf 1. So wie es sein soll.
Beim Decoder allerdings komm ich nicht aus dem Zustand 111 (0x0E) raus.
Hab schon fast alles Probiert irgendwie wollen die Zeilen aber nicht
blinken.
Anbei nochmal mein Code, so wie er momentan aussieht. Hat jemand von
euch noch einen Tipp? Wäre euch sehr dankbar.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<util/delay.h>
4
#include"inttypes.h"
5
6
// Displayorganisation
7
// Jedes Byte stellt eine Spalte dar. Das komplette Display ist
8
// 32*5 (=160) Spalten breit
9
// Der Index ins Array ist also die x-Koordinate eines Punktes
10
// Die Bits 0 bis 6 stellen die y-Koordinate des Punktes dar.
11
// Bit 7 eines jeden Bytes bleibt unbenutzt.
12
//
13
// Grund: Das Timing ist so schon verdammt eng. Es bleibt keine Zeit für
14
// aufändige Optimierungsversuche so dass jedes Bit benutzt
Hallo,
ich bin hier gerade auf den Thread gestoßen.Ich möchte so etwas
ähnliches mache. Wenn ich mir den Code von Karl heinz Buchegger
anschaue. Frage ich mich, wie bekomme ich es hin ein Spaltenmuster für
Buchstaben zu bekommen.
1
2
uint8_tDisplay[160];
3
.
4
.
5
.
6
7
// 40 Bits ausgeben
8
for(i=0;i<40;++i){
9
if(Display[i]&Mask)
10
PORTB|=(1<<PB0);
11
else
12
PORTB&=~(1<<PB0);
13
14
PORTB|=(1<<PB1);// SCLK Puls
15
PORTB&=~(1<<PB1);
So wie ich das sehe werden hier ja 40 mal eine "1" ausgegeben. Wenn ich
jetzt zum Beispiel mehrere Buchstaben ausgeben will benötige ich ja "0"
und "1" im Spaltenmuster. Wie kann ich so etwas realisieren? Über tipps
wäre ich euch sehr dankbar.
mfg
P.B
M.Hauser wrote:
> Beim Decoder allerdings komm ich nicht aus dem Zustand 111 (0x0E) raus.
Das ist der Ansatzpunkt.
Wusste doch, dass ich was übersehen habe beim blinden programmieren.
> // -> damit leuchtet die nächste Zeile> PORTA |= 0x0E; // 3-8 Dekoder auf einen Wert, so dass nichts> leuchtet
Klar, hier werden die 0x0E gesetzt. Also Pins auf 1
> PORTB |= ( 1 << PB3 ); // Schieberegister zum durchschalten der Bits> bringen> PORTB &= ~( 1 << PB3 );>> PORTA |= RowCodes[CurRow]; // 3-8 Dekoder auf die aktuelle Zeile
Tja. Das wird wohl nichts. Wenn die Pins erst mal auf 1 sind, kann man
1-en rausschreiben soviel man will. Die werden dadurch nicht zu 0, wenn
man sie vorher nicht resettet.
PORTA &= ~0x0E;
PORTA |= RowCodes[CurRow]; // 3-8 Dekoder auf die aktuelle Zeile
Das hat jetzt natürlich den Nachteil, dass am Dekoder kurzzeitig alle
Pins 0 sind und wenn ich mich richtig erinnere, ist mit 0 eine Auswahl
verbunden.
Besser ist es daher das so zu machen
P.B. wrote:
> So wie ich das sehe werden hier ja 40 mal eine "1" ausgegeben.
Äh nein.
Woraus liest du das?
Das jeweils als nächstes auszugebende Pixel kommt aus dem Display Array.
> Wenn ich> jetzt zum Beispiel mehrere Buchstaben ausgeben will benötige ich ja "0"> und "1" im Spaltenmuster. Wie kann ich so etwas realisieren? Über tipps> wäre ich euch sehr dankbar.
Indem du die 0-en und 1-en so ins Display Array schreibst, wie du das
brauchst, damit sich ein Buchstabe formt.
Hint: Für Buchstaben mag das leichter Overkill sein, aber um einzelne
'Pixel' zu setzen bzw. zu löschen hab ich die Funktionen SetPixel bzw.
ClearPixel angegeben.
>Äh nein.>Woraus liest du das?>Das jeweils als nächstes auszugebende Pixel kommt aus dem Display Array.
Die Schleife läuft von 0 bis 40 und für jedes i wird PB0 auf 1 gesetzt
=> somit 40x 1-en oder sehe ich das Falsch??
Btw. Ich seh das wohl falsch was macht den dieses & Mask in der
If-Bedingung??
P.B. wrote:
>>Äh nein.>>Woraus liest du das?>>Das jeweils als nächstes auszugebende Pixel kommt aus dem Display Array.>> Die Schleife läuft von 0 bis 40 und für jedes i wird PB0 auf 1 gesetzt> => somit 40x 1-en oder sehe ich das Falsch??
Das siehst du falsch.
1
if(Display[i]&Mask)
2
PORTB|=(1<<PB0);
3
else
4
PORTB&=~(1<<PB0);
Abhängig vom Zustand des i-ten Bits in Display[i] wird entweder eine 1
oder eine 0 an den Ausgabeport gelegt.
> Btw. Ich seh das wohl falsch was macht den dieses & Mask in der> If-Bedingung??
Dann solltest du mal Grundlagen in Bitmaskierungen lernen, ehe du dich
an Led-Matrizen wagst. Auf einem µC ist der Umgang mit & | und ^
tägliches Brot.
http://www.mikrocontroller.net/articles/Bitmanipulation
Hallo,
wie ich sehe wurde hier schon wieder fleißig gepostet. Ich habe das Ding
mittlerweile am laufen. Das ganze läuft nur noch nicht so wie ich es
gerne hätte. Kurze Beschreibung des momantanen Szenario:
Wie schon oben Beschrieben besteht die Matrix aus 40 Spalten und 28
Zeilen. Es laufen nun immer die 4 Blöcke parallel los. Wir haben nun
schon mehrere Varianten getestet, um die Blöcke nacheinander
anzuschalten. Mit klaren Worten: Zeile 1-7 danach 8-14 usw. Das ist uns
aber nicht gelungen. Frage wie bekomme ich es hin das ich jeden
Matrixblock mit den 7 Zeilen nacheinander aufrufen kann? Hatten schon
versucht mit Zähler und If-Abfragen (usw.) Hier ist der momentane Code,
der dafür sorgt das die 4 Blöcke (a 7 Zeilen) parallel starten.
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<util/delay.h>
4
#include"inttypes.h"
5
#include<stdbool.h>
6
7
// Displayorganisation
8
// Jedes Byte stellt eine Spalte dar. Das komplette Display ist
9
// 40 Spalten breit
10
// Der Index ins Array ist also die x-Koordinate eines Punktes
11
// Die Bits 0 bis 6 stellen die y-Koordinate des Punktes dar.
12
// Bit 7 eines jeden Bytes bleibt unbenutzt.
13
//
14
// Grund: Das Timing ist so schon verdammt eng. Es bleibt keine Zeit für
15
// aufändige Optimierungsversuche so dass jedes Bit benutzt