hey leute,
also ich bin ein ziemlicher anfänger, bitte nicht auslachen,
also ich habe da meinen atmel at89c5131a controller und eine led matrix
an P0 vom controller sind die zeilen angeschlossen und an P2 die
splaten, ich versuche jetz lediglich das auf der matrix auszugeben was
ich ins array eintrage. igendwie klappts aber überhaupt nicht, ich hab
bestimmt fatale logikfehler drin
entschuldigung hierfür
for (j=0;j=5;j++)
for (i=0;i=6;i++)
if(spielfeld[i][j]=1)
Diese drei Zeilen enthalten Fehler, ich sag aber nicht welche.
Dann solltest du beim multiplexen Spalten- und Zeilenbits
auch mal wieder auf 0 setzen. So geht es jedenfalls nicht.
wie wäre es damit:
unsigned char j=0;
isr_t0()interrupt 1
{
unsigned char row_data = 0;
unsigned char i;
for (i=0; i=<6; i++)
if (spielfeld[i][j]==1) row_data |=(1<<i);
P0 = 0; // avoid smear
P2 = ~ (1<<j); // set active row cathode to low
P0 = row_data; // set active column anodes to high
// next interrupt call will process next row
j++;
(if j>5) j=0;
}
a) wenn du die LEDs direkt an die ports angehängt hast, fließt strom,
wenn an dem Annotden-Pin eine 1 liegt, und am Anoden-Pin eine 0.
In meinem Beispiel würdest du die Anoden an P0 anschließen.
b) Die Schleifenbedingung ist bei dir falsch
c) Der "Verleich" "spielfeld[i][j]=1" setzt in deinem Code die Variable,
anstatt sie zu vergleichen.
d) Du hast irgendwelche Portkonfigurationen in der Interrupt Funktion.
Der Code im Interrupt muss möglichst schnell sein. Daher alles da
rausnehmen, was auch in main() gemacht werden kann.
e) in meinem Beispiel bleibt die "aktive" spalte solange an, bis der
nächste Interrupt kommt (indem die Schleife "j" erst beim nächsten
Interrupt weiterzählt). Ansonsten blinkt dein Display evtl. kurz auf,
und dann bleibt die letzte Spalte an, bis der nächste Interrupt kommt...
Ein Byte pro Bit ist Verschwendung und auch Blödsinn (kostet viel zuviel
Code).
Mach ein Array "unsigned char pattern[6]", auch wenn es nur 7 Bit sind.
Und im Timerinterrupt wird immer ein komplettes Byte ausgegeben.
Daß P0 noch externe Pullups benötigt, weißt Du?
Du brauchst in jedem Fall Treibertransistoren für die Spalten und die
Zeilen.
Peter
Willst du dir wirklich nen 8051 antun?
Nimm lieber nen AVR oder gleich nen arm (mbed) (is auch nich mehr schwer
zu benutzen) und geniess den hohen durchsatz
Max schrieb:> Willst du dir wirklich nen 8051 antun?
Das mußte ja kommen.
Der 8051 ist immer noch für viele Aufgaben mehr als ausreichend und
bewährt.
Der einzige Nachteil ist, daß der Keil C51-Compiler sehr teuer ist.
Wie gut der SDCC im Vergleich zum WINAVR ist, weiß ich nicht. Ich hab ja
ne Keil Lizenz, auch wenn die uralt ist (1995).
Im Unterschied zum AVR werden neue 8051 immer vom alten Compiler
unterstützt (da 100% Code kompatibel), man muß sich nur das neue Include
(die IO-Register Definition) kopieren oder einfach selber editieren.
Ich compiliere z.B. den AT89C51CC03 mit meinem 1995-er Keil.
Peter
Max schrieb:> Willst du dir wirklich nen 8051 antun?> Nimm lieber nen AVR oder gleich nen arm (mbed) (is auch nich mehr schwer> zu benutzen) und geniess den hohen durchsatz
Lieber nen Atom Prozessor und dann in Java oder html.
Einfacher gehts nicht :-)
Gruß an MAX Gast
also ich habe jetz die variante von layouter mal ausprobiert,
funktioniert leider immer noch nicht, und bei dem controller hab ich
keine wahl, ich habe ein controller aus der schule und eine matrix aus
der schule, mein ziel ist es 4-gewinnt zu programmieren, mit einer
mehrfarbigen led-matrix, jetzt wollt ich aber erst mal das 2d array auf
der matrix ausgeben, es funktioniert aber nicht, ich sehe nichts. Welche
zeit muss ich den für den Timer nehmen das man etwas sieht?
noch ne andere frage: warum kann ich kein array von bit oder boolean
machen?
hier mein jetztiger code
ich hab jetz noch and der ausgabe bisschen gedrecht, aber ich weiß
einfach nicht mehr was ich jetz noch falsch sein könnte und warum es
einfach nicht funtionieren will
1
P0=0;
2
P2=(1<<j);
3
P0=~(row_data);
die zeilen sind ja low aktiv bei meiner matrix und die spalten high
aktiv
hab an p0 die zeilen und an p2 die spalten
BITTE UM HILFE!!!
also erstens musst du row_data in der interrupt funktion auf 0 setzen,
bevor deine schleife läuft.
isr_t0()interrupt 1
{
row_data=0;
(...)
Als nächstes solltest du mal prüfen, ob deine Interrupt funktion
überhaupt ausgeführt wird, und wie oft.
Wenn du ein einigermaßen flimmerfreies Display haben willst, solltest du
mit min. 25 Updates pro Sekunde arbeiten.
Multipliziert mit 6 Spalten ergibt das min. 300 Hz für deinen Interrupt.
Hast du ein Oszilloskop?
Dann könntest du in der Interruptfunktion die Zeile
P2 = ~ (1<<j);
mal durch
P2 = P2 ^ 0xff;
ersetzen. Dann solten an P2 alle Pins einen schönen Rechteckpuls zeigen,
jede Flanke ist ein Interrupt.
Ausserdem ist es natürlich Unsinn, in main() in der while(1) schleife
ständig auf den Timer Registern rumzumachen.
Besser so:
main()
{
(...) // setze spielfeld
(...) // setze timer interrupt
while (1)
{
}
}
Ich kenne mich mit Atmel nicht aus, aber TH0 und TL0 sind wohl die
Delay-Werte des Timers. 0 scheint mir hier kein vernünftiger Wert.
Ich denke, als ersten Schritt solltest du erstmal schaffen, deine
Interruptfunktion zuverlässig und mit der gewünschten Spaltenfrequenz
ausführen zu lassen, bevor du dir um den restlichen Code gedanken
machst.
>die zeilen sind ja low aktiv bei meiner matrix und die spalten high>aktiv>hab an p0 die zeilen und an p2 die spalten
Welche Treiber benutzt du für die Matrix?
Keine? Dann geht das so nicht. P2 kann bei
High nur ein paar uA liefern. Das reicht nicht
für eine LED und für Multiplex schon gar nicht.
ich hab da so ne fertige matrix muss funktioniert auch jetz eigenlich
fast alles, also wenn ich die zeit vom teimer auf 2^16 mikrosekunden
einstelle sehe ich auch wie der interrupt zeile für zeile durchgeht.
jedoch kommmt auf row_data nicht das was im array steht sondern immer
nur 0xff als die ganze spalte an, was stimmt da nicht?
row data soll ja eigentlich immer nur daß was im array steht übertragen
1
isr_t0()interrupt1
2
{
3
row_data=0;
4
TR0=0;
5
TH0=0xFE;
6
TL0=0x0C;
7
TR0=1;
8
9
for(i=0;i<=6;i++)
10
{
11
if(spielfeld[i][j]==1)row_data|=(1<<i);
12
}
13
P0=0;
14
P2=(1<<j);
15
P0=~(row_data);
16
17
18
j++;
19
if(j>5)j=0;
20
21
22
23
}
ich habe ja werte in das array eingetragen, die sind aber nicht auf der
anzeige zu sehen
das array
> for (i=0; i<=6; i++)> {> if (spielfeld[i][j]==1) row_data |=(1<<i);> }
Du musst dich mal mit dir selber einig werden, welche Dimension des
Arrays wie gross ist.
Dein i läuft in der Schleife durch:
0, 1, 2, 3, 4, 5, 6
zähl nach, das sind 7 Werte
Dein Array hat aber in der ersten Dimension nur 6 Werte:
0, 1, 2, 3, 4, 5
Hinweis: Ein <= in einer for-Schleife, die noch dazu dient ein Array
abzuarbeiten, ist meistens einfach nur falsch.
> nur 0xff als die ganze spalte an
wie genau hast du aufgepasst?
Die meisten deiner Werte sind 0. WEnn du hier
P0 = ~(row_data);
das auszugebende Byte invertierst, dann darfst du dich nicht wundern,
wenn die Portpins praktisch ständig 1 sind. Die 0, die da ab und zu
auftritt, kann man ganz leicht übersehen.
Und da ein 2D-Array dafür zu benutzen, ist nach wie vor Unsinn. Du
fürchtest dich da vor etwas, wovor du dich nicht fürchten musst: nämlich
beim LED ein/ausschalten Bitoperationen anwenden zu müssen. Als
Ausgleich dafür machst du jetzt dafür deine ISR maximal kompliziert,
wenn du es eigentlich genau umgekehrt machen solltest: Die ISR so
einfach wie möglich und dafür ein bischen Bit-"Magie" beim
setzen/löschen von LED
(Und lass den Timer in der ISR in Ruhe!)
So sollte deine ISR eigentlich aussehen:
1
volatileunsignedcharspielfeld[6];
2
3
isr_t0()interrupt1
4
{
5
P0=0;
6
P2=(1<<j);
7
P0=spielfeld[j];// oder P0 = ~spielfeld[j]; je nachdem wie die Matrix
8
// hardwaremässig aufgebaut ist
9
10
j++;
11
if(j>5)
12
j=0;
13
}
und dazu noch 2 Funktionen um LED gezielt in einem x/y Koordinatensystem
ein/auszuschalten, die diese x/y Koordinaten in eine Bitposition in
diesem Array umrechnen. X ist leicht, das kann man direkt übernehmen und
y muss man eben in eine Bitmaske umrechnen mit der man dann gezielt 1
Bit setzt/löscht.
dude123 schrieb:> jedoch kommmt auf row_data nicht das was im array steht sondern immer> nur 0xff als die ganze spalte an, was stimmt da nicht?
Na dann lade es dochmal mit ner Konstante, z.B. 0xAA.
Peter
zu dem post von karl heinz buchenegger,
das mit der isr so einfach wie möglich machen is ja schön und gut, aber
mein ziel ist es später die spielstände von 4 gewinnt auf einem array zu
speichern und das array ohne große umstände dann auszugeben in der isr
des programms, in die main kommt dann das eigentliche programm, aber ich
will jetz hald ersteinmal diese blöde multiplexanzeige zum laufen
bekommen.
und den timer kann ich in der isr nicht in ruhe lassen weil er kein
auto_reload hat, also muss ich immer wieder den startwert reinschreiben,
das ich row_data invertiert habe stimmt, aber das ist weil die leds auf
port0 low aktiv sind, also kein grund warum die spalten immer nur an
sind.
>und den timer kann ich in der isr nicht in ruhe lassen weil er kein>auto_reload hat, also muss ich immer wieder den startwert reinschreiben,
Ne, dann hast du ihn nicht nach deinen Anforderungen konfiguriert. Da
musst du nochmal schauen - Thema "Timer". Was sonst noch an Tips
geschrieben wurde, ist absolut richtig und das solltest du auch
beherzigen.
Gruß Jonas
dude123 schrieb:> das mit der isr so einfach wie möglich machen is ja schön und gut, aber> mein ziel ist es später die spielstände von 4 gewinnt auf einem array zu> speichern und das array ohne große umstände dann auszugeben in der isr> des programms, in die main kommt dann das eigentliche programm
Ein 2-dimensionales Array ist deutlich umständlicher als ein 6 Byte
großes Array.
Sowohl vom Schreiben her und erst recht für den Compiler.
Und die CPU hat auch deutlich mehr zun ackern (Multiplikation).
jonas biensack schrieb:> Ne, dann hast du ihn nicht nach deinen Anforderungen konfiguriert.
Das mit dem Timer laden ist schon richtig so. Man muß ihn aber nicht
anhalten. Da er ja gerade übergelaufen ist, kann kein Low-Byte-Überlauf
während des Ladens passieren.
Du könntest aber auch T2 nehmen.
Nur wenige 8051 können auch ein 16-Bit Autoreload für T0/T1, z.B.
AT89LP4052.
Peter
kannst du mal einen schaltplan posten, wie du die matrix angeschlossen /
getrieben hast? das macht es uns einfacher zu erkennen, was an den ports
anliegen muss.
Also Z= Die Steuerung der Zeilen
SG= Spalten Grün
SR= Spalten Rot
auf der Spalte muss eine 1 sein und auf der Zeile eine null
mein Primärziel ist es wie gesagt erst einmal ein 2D-array auszugeben,
später dann 3D-array also grün und rot in der dritten dimension, für
vier gewinnt hald, das ich im main code alles auf ein array speicher
kann, dies dann ausgebe und auch im array die gewinnabfrage machen soll,
habe bisher keine andere idee wie ich 4-gewinnt programmieren soll
--------------------- ----------------------
| | |
2-Farbige | | Atmel |
LED- Matrix 6x8 | | Mikrocontroller |
| | AT89C5131A |
__ ___ __ | | __ ___ __ |
|Z | |SG | |SR | | | |P0 | |P1 | |P2 | |
| | | | | | | | |
| | | | | | | | |
| | | | | | | | |
---|------|----|----- ----|-----|-----|----
| | | | | |
| | ---------------------------|----- |
| | | |
| |--------------------------------|-----------
| |
| |
----------------------------------------
Wie Holger am 26.06.2011 / 18:58 bereits schrieb, brauchst du Spalten-
und Zeilen-Treiber.
Zum Beispiel so:
Beitrag "LED-Matrix Treiber"
Wenn du es tatsächlich so angeschlossen hast wie in deiner Zeichnung
(ohne Vorwiderstände & direkt an die Mikrocontroller-Pins), hast du eine
gute Chance deinen Controller und/oder die Matrix bereits "gebraten" zu
haben - nimm einen neuen, um kaputte Ports als Fehlerquelle
auszuschließen.