Forum: Mikrocontroller und Digitale Elektronik LED-Matrix; glimmen nicht aktiver LEDs


von wep (Gast)


Lesenswert?

Moin,

ich habe eine LED-Matrix aufgebaut, bei der ich mich an diesem Beispiel 
orientiert habe:
http://www.mikrocontroller.net/wikifiles/6/62/LED-Matrix-MOSFET.png
Die IRF7014 werden mit 74HC595 Angesteuert, und die Spalten direkt mit 
TPIC6B595N.

Jetzt habe ich das Problem, dass in den aktiven Zeilen, die LEDs der 
alten Zeilen auch noch leicht glimmen.

Ich schiebe die Schuld geistig gerade auf die Miller-Kapazität der 
74HC595. Stimmt das?

Die Frage ist natürlich, wie ich das verhindern könnte. Hardwareseitig 
wäre für die nächste Schaltung interessant, im Moment kann ich das sonst 
nur Softwareseitig lösen.

Die Zeilen vorher erstmal dunkel zu schalten ist eine schlechte Lösung, 
da dadurch alles wieder dunkler wird. Da könnte ich zur Not aber noch 
etwas an den Vorwiderständen drehen.

Ich habe ca. eine Frequenz von 1200Hz (für die komplette Matrix). Ist 
das zu Schnell? Ich wollte die Matrix noch mit 10 Dimmstufen beschalten, 
daher die ~1200Hz.

MfG

von Karl H. (kbuchegg)


Lesenswert?

wep schrieb:

> Ich schiebe die Schuld geistig gerade auf die Miller-Kapazität der
> 74HC595. Stimmt das?

Ich würde die Schuld erst mal auf dein Programm schieben.

Gehst du so vor?
1
ISR( .... )
2
{
3
   alte LED ausschalten, alle Zeilen deaktivieren
4
   Buchhaltung machen, wie zb das Incrementieren des Zeilenzählers
5
   Muster für die nächste Zeile ausgeben
6
   die nächste Zeile aktivieren
7
}

> Die Zeilen vorher erstmal dunkel zu schalten ist eine schlechte Lösung,

nö. das ist genau die Art und Weise wie man das macht. Wenn natürlich 
dein Aufbau stimmt.

> da dadurch alles wieder dunkler wird.

Ah geh. Die paar µs in denen nichts leuchtet, siehst du gar nicht. Das 
sind 10-tel Promille, worüber wir hier reden.

von MaWin (Gast)


Lesenswert?

Du kannst ja mal ausrechnen oder simulieren, wie lange der 74HC595 
braucht um das Gate des 7104 umzuladen, und kontrollieren, ob du so 
lange wartest.

von Martin S. (sirnails)


Lesenswert?

wep schrieb:
> Die IRF7014 werden mit 74HC595 Angesteuert, und die Spalten direkt mit
> TPIC6B595N.
>
> Jetzt habe ich das Problem, dass in den aktiven Zeilen, die LEDs der
> alten Zeilen auch noch leicht glimmen.

Und wie steuerst Du die 595 an? Vermutlich mit einem µC der halt eben 
nicht bei Low sofort 0V macht, sondern eine gewisse Zeit zum Setzen 
braucht.

1,2kHz wären ja gerade 833µs. Das ist nicht wirklich schnell. Bei einem 
1:10 Tastverhältnis hättest du nach jeder Zeichnung immernoch 33µs Zeit, 
um die Zeilen erstmal auf Low- und dann auf High zu ziehen. Das musst Du 
beim Dimmen doch eh machen... dann hast Du halt keinen Duty-cicle von 
100%, sondern nur 99%. Das merkst Du als Mensch gar nicht.

von wep (Gast)


Lesenswert?

Ich arbeite nicht mit einer ISR, sondern nur mit ner while(1)-Schleife.
- Matrix löschen
- Matrix beschreiben
- Matrix schreiben ( Zeile schreiben; Spalte schreiben; Zähler erhöhen; 
Clk für schieberegister; nächste Zeile...)

Das war bisher, also mit Glimmen. Vll habe ich das mit dem Deaktiveren 
auch falsch verstanden:

- Zeile schreiben
- Spalte schreiben
- Clk
- Zeile schreiben (LEDs aus)
- Spalte schreiben
- Zähler erhöhen
- Clk

Jetzt ist kein Glimmen mehr da. Aber ich habe ja z.B. aus einer 10 
Zeiligen Matrix eine virtuelle 20 Zeilige gemacht, da ich jede Zeile 
doppel schreibe.
Daher sinkt auch meine Helligkeit von 75 auf 44 LUX. Das ist nicht nur 
ein bisschen.

Oder ist mit deaktivieren gemint den "Output Enabled" der TPIC auf low 
zu ziehen (deaktivieren)?
Das wäre etwas blöd, da hier mein PWM dran hängt.

Achja ich Multiplex übrigens die Zeilen.

@MaWin
Ich Simuliere das mal wenn ich daheim bin.

MfG

von Martin S. (sirnails)


Angehängte Dateien:

Lesenswert?

Siehe Bild.

Mal ganz allgemein und ohne zu wissen, welchen Prozessor Du überhaupt 
nimmst.

Die Flanken wie Du sie gerne hättest in rot, und so wie sie sind in 
grün.

Je nachdem, welchen Prozessor Du nimmst fällt die Zeit zwischen dem im 
Programm aufgerufenen logischem 0 und dem realen 0V am Ausgang, 
unterschiedliche lange aus.

Wenn Du jetzt zu schnell auf die nächste Zeile umschaltest, ist der 
Ausgang am Prozessor noch gar nicht richtig auf low, das nächste 
Zeilensignal aber schon auf high. Und dann glimmt es.

von wep (Gast)


Lesenswert?

Ich verwende einen PIC mit 8MHz (mit nem PLL von 4)

Ich habe das Ansteuern der Schieberegister per SPI realisiert. Das 
überschneiden sollte also nicht auftreten. Ich hab die Frequenz damals 
mit nem Oszi bestimmt, und nicht ausgerechnet. Leider steht mir das im 
Moment nicht mehr zur Verfügung, da müsste ich wieder an die FH fahren 
um eins zu benutzen.

von Falk B. (falk)


Lesenswert?

@ MaWin (Gast)

>Du kannst ja mal ausrechnen oder simulieren, wie lange der 74HC595
>braucht um das Gate des 7104 umzuladen, und kontrollieren, ob du so
>lange wartest.

Kann man besser messen. AVR hat zwar weniger Ausgangswiderstand als ein 
74HC, aber grob kommt das hin.

Beitrag "Re: Transistor, 1A, 4MHz Schaltfrequenz"

von Karl H. (kbuchegg)


Lesenswert?

wep schrieb:
> Ich arbeite nicht mit einer ISR

warum nicht?

>, sondern nur mit ner while(1)-Schleife.

Na dann: viel Spass das ganze jemals vernünftig zum Laufen zu kriegen


Multiplexing ohne Timer-Interrupt ist wie Bergsteigen in Sandalen.
Flachlandtiroler glauben auch, das das funktioniert würde, weil sie ja 
zu Hause auf dem Rodelhügel auch keine Probleme damit hätten.


> Das war bisher, also mit Glimmen. Vll habe ich das mit dem
> Deaktiveren auch falsch verstanden:

Hast du

> - Zeile schreiben
> - Spalte schreiben
> - Clk
> - Zeile schreiben (LEDs aus)
> - Spalte schreiben
> - Zähler erhöhen
> - Clk

Genau anders rum.
Das ganze ist ja eingebettet in eine Schleife
1
    while( 1 ) - Schleife  
2
3
      xxxxxx
4
5
6
      - Zeile schreiben (LEDs aus)
7
      - Clk                            ------+
8
                                             |
9
      - Zeile schreiben                      | yyyyyy
10
      - Spalte schreiben                     |
11
      - Clk                            ------+
12
13
      - Zähler erhöhen
14
15
      xxxxxxx
16
17
    ende Schleife


In den Programmteilen xxxxxxxx leuchtet eine Zeile deiner Matrix (jedes 
mal eine andere). Nur während das Abschnitts yyyyyyy leuchtet überhaupt 
nichts.

D.h. die Leuchtdauer der gerade angezeigten Led-Zeile wird (im 
wesentlichen) von den Programmteilen xxxxxxxx bestimmt und nicht von 
yyyyyyyy. Denn yyyyyyy (der Zeitraum, in dem nichts leuchtet) geht so 
schnell, dass du das ganz sicher nicht mitkriegst.


Und dann geht man eben her und verlagert den Teil
1
      - Zeile schreiben (LEDs aus)
2
      - Clk                            ------+
3
                                             |
4
      - Zeile schreiben                      | yyyyyy
5
      - Spalte schreiben                     |
6
      - Clk                            ------+
7
8
      - Zähler erhöhen
in eine Interrupt Routine, die vom Timer regelmässig aufgerufen wird. 
Pro Aufruf wird die gerade leuchtende Zeile abgeschaltet, die nächste 
Zeile bestückt und eingeschaltet und raus gehts aus dem Interrupt. 
Während dann der Rest des Programms weiter vor sich hin wurschtelt, 
leuchtet diese eine Zeile. Bis dann eben ein paar hundert µs später der 
nächste Interrupt vom Timer erfolgt, in dem die gerade leuchetende Zeile 
wieder abgeschaltet wird und die nächste bestückt und eingeschaltet 
wird. Und so geht das Timer-getrieben immer weiter. Reihum Zeile für 
Zeile. Bei jedem Interrupt Aufruf eine andere.

Vorteil:
* Das Hauptprogramm muss sich um die Matrix nicht mehr kümmern. Die 
setzt einfach in den Variablen die entsprechenden Bits für die LEDs die 
sie leuchten haben will oder löscht sie. Das es einen Mechanismus gibt, 
der die Hardware ansteuert, braucht das Hauptprogramm nicht kümmern. Für 
das Hauptprogramm SIND diese Variablen die LED der Led-Matrix.
* Der eigentliche Hardware Update ist absolut gleichmässig, weil ja auch 
die Interrupt Aufrufe vom Timer gleichmässig kommen. D.h. da flackert 
nichts oder hat unterschiedliche Basishelligkeiten, wie es bei deiner 
Schleifenlösung möglich ist, weil eben die Programmteile xxxxxxx eben 
nicht immer gleich viel Zeit beanspruchen.

von Peter D. (peda)


Lesenswert?

wep schrieb:
> Ich arbeite nicht mit einer ISR, sondern nur mit ner while(1)-Schleife.

Aha, Du willst also Sisyphos nacheifern.

von Karl H. (kbuchegg)


Lesenswert?

Ich kann mich hier im Forum an KEINEN EINZIGEN Frager erinnern, bei dem 
tatsächlich die Schaltzeiten in den Ausgangsstufen eine Rolle beim 
Geisterleuchten in einer Matrix oder bei 7-Segment Anzeigen durch 
Multiplexing gespielt hätten.

Ich kann mich aber an Zig (wenn nicht Hunderte) Frager erinnern, die 
ganz einfach das Multiplexing softwaremässig falsch angegangen sind.

Wenn man ihn auch noch darin bestärkt, dass das ganze irgendwas mit 
HW-Laufzeiten zu tun hat, dann führt man ihn erfahrungsgemäss auf eine 
falsche Fährte. Wenn der Programmaufbau Mist ist, dann muss man das auch 
so ansprechen und nicht eine falsche Spur legen.

Und es sind immer wieder die gleichen Punkte, die beim Multiplexing 
falsch gemacht werden
* Angst vor einem Timer bzw. Timerinterrupt
* der gedankliche Übergang von
1
     Led Treiber umstellen
2
     Led ein
3
     Led aus
4
     mach was
bei dem die Leds nur zwischen 'ein' und 'aus' leuchten und daher während 
des Teiles 'mach was' aus sind, hin zu
1
     Led aus
2
     Led Treiber umstellen
3
     Led ein
4
     mach was
bei dem die Leds während des Teiles 'mach was' leuchten und eben nicht 
aus sind.

Das sind die beiden Hauptpunkte, wobei der Punkt 'Angst vor Timer' der 
schwerwiegendere ist, denn der zweite Punkt löst sich softwaremässig 
sowieso dann im Nichts auf, wenn man erst mal beim Timerinterrupt ist.

von wep (Gast)


Lesenswert?

Anbei mal mein Code, wie ich ihn vorerst geschrieben habe. Einzelne 
Funktionen hab ich hier mal fast alle zusammen kopiert. Ich benötige 
Maximal 6 Zeilen von meiner matrix, daher prüfe ich auf 0, und wenn ich 
keine 6 Zeilen geschrieben habe, schreibe ich dummys damit sie immer 
gleich hell leuchtet.
1
while(1){
2
  //Matrix löschen
3
  for(i=0;i<10;i++)
4
    {
5
      matrix[i]=0x00;
6
    }
7
8
  //Matrix füllen
9
  matrix[1] |= 0b1110000000000000
10
  matrix[2] |= 0b0001110000000000
11
[...]// das hier ist unterschiedlich. Nur exemplarisch
12
13
  //Matrix schreiben
14
  char x=0;
15
  char z;
16
  for(z=0;z<10;z++)
17
    {
18
      if(matrix[z]!=0)
19
      {
20
        writeLine(zeile[z]);  //zeile schreiben
21
        writeLine(matrix[z]);  //spalte schreiben
22
        x++;
23
        pushOut();    
24
      }
25
    }
26
    if(x<6){
27
      for(x;x<6;x++){
28
        clearOut();
29
      }
30
    }  
31
32
  void writeLine(unsigned int x){
33
      int j;
34
      for(j=0;j<2;j++){
35
        srcMirror=x;  
36
        mirror();    //Bits spiegeln  
37
        SSP1BUF=dstMirror;  //schreibe lByte  
38
        while(SSP1STATbits.BF==0);
39
        dummy=SSPBUF;      
40
        x=(x>>8);  //hByte ins lByte schieben
41
      }
42
  }
43
44
  void pushOut(void){
45
    char i;
46
    TRISDbits.TRISD4=0;
47
    for(i=0;i<10;i++);
48
    TRISDbits.TRISD4=1;
49
    for(i=0;i<10;i++);
50
    TRISDbits.TRISD4=0;
51
    for(i=0;i<10;i++);  
52
  }
53
}

Ich habe überhauptkeine Probleme mit Interrupts. Ich dachte nur einfach, 
dass es hier nicht notwendig ist. Dass es nicht unbedingt schön 
programmiert ist, ist mir klar. Aber ich dachte das ist so einfach, das 
geht auch ohne Interrupts.

Bzw. hatte, habe, ich ein Problem damit zu verstehen, wie ich die 
SPI-Routine richtig per Interrupt abarbeiten soll.
Ich sollte also:
1
Timer_ISR(){
2
writeLine(0x00);  //LEDs aus
3
pushOut();
4
writeLine(zeile[z]);  //LEDs aus
5
writeLine(matrix[z]);  //spalte schreiben
6
x++;
7
z++;
8
pushOut();
9
}
10
11
main(){
12
//Überprüfen ob zeile leer, wenn ja nächste zeile
13
if(matrix[z]==0)z++;
14
//sechs zeilen geschrieben? wenn nein dummys schreiben
15
if(z>=10 && x<6){
16
 zeile[0]=0xFFFF;
17
 matrix[0]=0x0000;
18
 z=0; 
19
}else{z=0}
Ist das von der Überlegung her jetzt besser, bzw. richtig?
Jetzt ist meine Frequenz nicht mehr abhängig von der Frequenz meines 
SPI-Moduls(naja fast) und dem rest, sondern von meinem Timer. Jetzt muss 
ich aber sicherstellen, dass meine SPI auch schnell genug ist, nicht das 
meine Überprüfung in der main-Funktion übersprungen wird (da ich nur 6 
Zeilen benötige).

von Karl H. (kbuchegg)


Lesenswert?

wep schrieb:


> Ich sollte also:
>
1
> Timer_ISR(){
2
> writeLine(0x00);  //LEDs aus
3
> pushOut();
4
> writeLine(zeile[z]);  //LEDs aus
5
> writeLine(matrix[z]);  //spalte schreiben
6
> x++;
7
> z++;
8
> pushOut();
9
> }
10
>

Fast.
x brauchst du da nicht mehr und z muss auch wieder irgendwann 0 werden

1
Timer_ISR(){
2
  static uint8_t zeileCnt = 0;
3
4
  writeLine(0x00);  //LEDs aus
5
  pushOut();
6
7
  zeileCnt++;
8
  if( zeileCnt == 6 )
9
    zeileCnt = 0;
10
11
  writeLine(zeile[zeileCnt]);   //Zeile aktivieren
12
  writeLine(matrix[zeileCnt]);  //spalte schreiben
13
  pushOut();
14
}

bzw. müssten das am Anfang der Funktion nicht 2 writeLines sein, damit 
die 0-er auch wirklich die Transistoren erreichen? Denn mit nur einem 
writeLine schiebst du ja nur 16 Bit rein.

> main(){
> //Überprüfen ob zeile leer, wenn ja nächste zeile
> if(matrix[z]==0)z++;

interessiert dich an dieser Stelle alles nicht mehr.
Du schreibst einfach nur noch in matrix rein, ob eine LED grundsätzlich 
leuchten soll oder nicht. Was es mit dem z hier auf sich hat, ist in 
main() alles schon uninteressant geworden

Die eigentliche Ausgabe an die Hardware erledigt die Interrupt Funktion 
ganz alleine. Unabhängig von allem anderen.

> Jetzt ist meine Frequenz nicht mehr abhängig von der Frequenz meines
> SPI-Moduls(naja fast) und dem rest, sondern von meinem Timer.

Ganz genau

> Jetzt muss
> ich aber sicherstellen, dass meine SPI auch schnell genug ist

das ist sie sicherlich. Die SPI kann full Speed fahren. Die 595 haben da 
kein Problem damit.

> Timer .... Ich dachte nur einfach, dass es hier nicht notwendig ist.
Aber nur wenn man sich mehr Arbeit und mehr Ärger einhandeln will als 
unbedingt notwendig.

von Falk B. (falk)


Lesenswert?

@ Karl Heinz Buchegger (kbuchegg) (Moderator)

>Ich kann mich hier im Forum an KEINEN EINZIGEN Frager erinnern, bei dem
>tatsächlich die Schaltzeiten in den Ausgangsstufen eine Rolle beim
>Geisterleuchten in einer Matrix oder bei 7-Segment Anzeigen durch
>Multiplexing gespielt hätten.

Doch, da gab es schon einige, bis in den einstelligen us Bereich. Aber 
auch diese langsamen Schaltstufen kann man durch passende Programmierung 
nachleuchtfrei ansteuern.

>Das sind die beiden Hauptpunkte, wobei der Punkt 'Angst vor Timer' der
>schwerwiegendere ist,

Chronometerphobie, eine neue HighTec Krankheit? ;-)

von wep (Gast)


Lesenswert?

@kbuchegg
Habe es vorerst zum testen mal so übernommen, und jetzt glimmt nix mehr 
:)

Ich hab überhaupt keine Probleme mit Timern, im Gegenteil ich hab fast 
alle verbraucht.
Wie gesagt, hatte nen falschen Gedanken. Ab jetzt mach ich es wirklich 
so wie ich es an der FH gelernt habe. Kommt davon wenn man im Internet 
Bsp. sieht und "übernimmt" -.-

Mein SPI ist aber mit 8MHz/4 zu langsam, bzw. meine Routine zum 
schreiben der Byte zu lang. Da Sitz ich dann in ner endlos 
Interruptschleife.
Also doch wieder nen PLL von 4, dann bin ich intern auf 32MHz und jetzt 
läuft alles. Ich werd den Code hier posten sobald ich das alles nochmal 
überarbeitet habe. Da lassen ich auch noch ne einige Maschinenzyklen 
sparen wenn ich mir das Disassembly so anschau.

Danke für die Hilfe!

von Karl H. (kbuchegg)


Lesenswert?

wep schrieb:


> Mein SPI ist aber mit 8MHz/4 zu langsam, bzw. meine Routine zum
> schreiben der Byte zu lang.

Ja, die hat mir auch nicht besonders gefallen. Aber ich denke, da bist 
du sowieso drann.

Ein paar Dinge
1
void writeLine(unsigned int x){
2
      int j;
3
      for(j=0;j<2;j++){
4
        srcMirror=x;  
5
        mirror();    //Bits spiegeln  
6
        SSP1BUF=dstMirror;  //schreibe lByte  
7
        while(SSP1STATbits.BF==0);
8
        dummy=SSPBUF;      
9
        x=(x>>8);  //hByte ins lByte schieben
10
      }

int ist ganz schlecht.
Übeleg dir, wieviele Bits du tatsächlich brauchst. Und dann nimm die 
Bitzahl, die du brauchst.
j muss hier kein int, also 16 Bit, sein. 8 Bit reichen. Also ein uint8_t

Die ganze Schleife ist im Grunde unnötig. Mach die eine Funktion, die 1 
Byte raustaktet und ruf die dann von WriteLine 2 mal auf
1
void writeByte( uint8_t byte )
2
{
3
  srcMirror = byte;  
4
  mirror();    //Bits spiegeln  
5
  SSP1BUF = dstMirror;  //schreibe lByte  
6
  while(SSP1STATbits.BF==0)
7
    ;
8
}
9
10
void writeLine(unsigned int x)
11
{
12
  writeByte( x );
13
  writeByte( x >>> 8 );
14
}

Die ganze Sache mit dem mirror. Muss das wirklich hier sein? Oder wäre 
das nicht besser an der Stelle aufgehoben, wo du die Bits in der Matrix 
setzt bzw. setzten wirst?
Bedenke: das wird 1000 mal in der Sekunde gemacht. Mit im Grunde immer 
den gleichen Werten! Es macht keinen Sinn, das immer wieder hier zu 
machen. Solche Dinge macht man an der Stelle, an der die Bits in die 
Matrix geschoben werden. Man möchte sich die Werte in den globalen 
Variablen so zurecht legen, dass es hier, im Code der viele tausend mal 
abgearbeitet wird, nur das Allernotwendigste zu tun gibt. Im Grunde ist 
ja auch der unsigned int für die Matrix schon zweifelhaft, aber ok, ein 
>>8 ist jetzt nicht die Welt, weil er trivial umsetzbar ist. Immer drann 
denken: ein 8_Bit µC hat am liebsten 8 Bit Einheiten zum bearbeiten. 16 
Bit ist schon wieder mehr Aufwand! Und das beginnt schon damit, dass 
doppelt so viele Register frei geschaufelt werden müssen um die 
Variablen vom Speicher in die CPU zu laden. Compiler sind gut, aber ein 
schlechtes Design können sie auch nicht schadlos ausbügeln.


Deine writeLine Funktion könnte im einfachsten Fall so aussehen
1
void writeLine(unsigned int x)
2
{
3
  SSP1BUF = x;
4
  while(SSP1STATbits.BF==0)
5
    ;
6
7
  SSP1BUF = x >> 8;
8
  while(SSP1STATbits.BF==0)
9
    ;
10
}
das ist das mehr oder weniger das absolute Minimum. Weniger geht nicht 
(von 16 Bit, 8 Bit abgesehen). Alles andere müssen die Pixel-setz/lösch 
Funktionen zuarbeiten, was ja dort auch kein Problem ist.

von Falk B. (falk)


Lesenswert?

@wep (Gast)

>Wie gesagt, hatte nen falschen Gedanken. Ab jetzt mach ich es wirklich
>so wie ich es an der FH gelernt habe.

Soll mangar nicht glauben, dass die einem dort was sinnvolles beibringen 
. . .

> Kommt davon wenn man im Internet
>Bsp. sieht und "übernimmt" -.-

Hat dir das deine Mutti nicht beigebracht? ;-)

>Mein SPI ist aber mit 8MHz/4 zu langsam,

Es gibt den Double Speed Modus.

> bzw. meine Routine zum
>schreiben der Byte zu lang.

Wieviele Millionen Bytes musst du denn für die Matrix schreiben? Kann 
ich mir nicht vorstellen. Ich denke eher, den Code ist sehr 
verbesserungsfähig.

>Also doch wieder nen PLL von 4, dann bin ich intern auf 32MHz und jetzt
>läuft alles.

Jaja, mit viel Firepower kann man solche Fehler überdecken, es bleibt 
aber ein Fehler bzw. schlechte Programmierung.

> Ich werd den Code hier posten sobald ich das alles nochmal
>überarbeitet habe. Da lassen ich auch noch ne einige Maschinenzyklen
>sparen wenn ich mir das Disassembly so anschau.

Ich tippe mal, da lässt sich bedeutend mehr sparen, wenn man das 
richtige Konzept wählt.

von wep (Gast)


Lesenswert?

Mir ging es jetzt erstmal drum zu testen ob das Glimmen weg ist.
Jetzt setzt ich mich an den Code.


> Soll mangar nicht glauben, dass die einem dort was sinnvolles beibringen
> . . .
Jaja...du wirst lachen wie viele Profs es gibt wo man nur mit dem Kopf 
schütteln kann. Ich erinnere mich an die Vorlesung Realtime Systems für 
AVRs aus dem Masterstudiengang der Informatiker. Die wusste nicht mehr 
als im Skript stand und auf meine Frage, wie ich denn ein Register binär 
beschreibe (in MPLAB eben REGISTER=0b00000000) kam nur ein Achselzucken.

Zum Glück sind das die absoluten Ausnahmen.

> Es gibt den Double Speed Modus.

Afaik nicht bei einem PIC.

> Wieviele Millionen Bytes musst du denn für die Matrix schreiben? Kann
> ich mir nicht vorstellen. Ich denke eher, den Code ist sehr
> verbesserungsfähig.

4 Schieberegister also 32Bit. Ich sag ja mein Code is murks.


@kbuchegg

Werde mir die Tipps zu Herzen nehmen.
Das mirror muss theoretisch gar nicht sein und du hast recht, an dieser 
Stelle ist es absolut überflüssig.

von Peter D. (peda)


Lesenswert?

wep schrieb:
> 4 Schieberegister also 32Bit.

Also hast Du eine 16*16 Matrix aus 256 LEDs.

Solche grundsätzlichen Informationen sollte man immer gleich am Anfang 
klarstellen, damit die Leser nicht rumraten müssen.

Beim AVR kann man die Schiebezeit völlig aus dem Timerinterrupt 
rausnehmen. Er kann nämlich die UART als gepuffertes SPI nehmen, d.h. 
man schreibt die 2 * 8Bit ohne Pause rein.

Man lädt dann die 16Bit der Spalten am Ende des Handlers ins SPI und 
beim nächsten Interrupt ist das SPI fertig und man muß sie nur noch mit 
einem RCLK-Puls latchen.
Die Zeilen muß man dagegen nicht 16bittig schreiben, es wird ja immer 
nur auf die nächste Zeile geschaltet, also reicht ein einzelner 
Schiebetakt aus.

Wenn Dein PIC kein gepuffertes SPI hat, dann mußt Du einmal auf das SPI 
warten.
Ist doch aber auch schon eine ganz hübsche Einsparung, einmal aufs SPI 
warten statt 4-mal.

von Peter D. (peda)


Lesenswert?

wep schrieb:
> Ich wollte die Matrix noch mit 10 Dimmstufen beschalten,

Fürs Dimmen legst Du einfach einen PWM-Ausgang auf den /OE-Pin der 
Spaltenregister.
Die PWM muß natürlich synchron zum Multiplextakt sein, also nimmst Du 
den selben Timer für beides.

von Karl H. (kbuchegg)


Lesenswert?

Peter Dannegger schrieb:

> Die Zeilen muß man dagegen nicht 16bittig schreiben, es wird ja immer
> nur auf die nächste Zeile geschaltet, also reicht ein einzelner
> Schiebetakt aus.

Leider hat er den Fehler gemacht, alles in einem 32 Bit Schieberegister 
zusammenzufassen (dem Code nach zu urteilen). Damit geht das nicht mehr.

von Nosnibor (Gast)


Lesenswert?

Natürlich ist es im allgemeinen sinnvoll, fürs Multiplexen einen 
Timerinterrupt zu nehmen, denn damit stellt man sicher, daß das Timing 
immer präzise eingehalten wird, so daß keine Helligkeitsschwankungen 
auftreten, egal was das Hauptprogramm unterdessen macht. Für einige 
Anwendungen mag es aber auch anders gehen; das klassische (und 
inzwischen veraltete) Beispiel ist ein Taschenrechner.

Da werden einfach der Reihe nach die einzelnen Stellen der Anzeige 
geschaltet; eine Warteschleife sorgt dafür, daß jede gleich lange 
leuchtet, und wenn alle durch sind (sozusagen in der Austastlücke), 
kommt die Tastaturabfrage dran. Als Folge "blinzelt" möglicherweise die 
Anzeige bei jeder Taste kurz, was den Benutzer aber nicht stört, weil er 
ja sowieso eine Reaktion erwartet; man kann das als beabsichtigtes 
Bestätigungssignal auffassen. Bei längeren Berechnungen bleibt dann eben 
die Anzeige so lange dunkel, aber was soll sie auch anzeigen, solange 
das Ergebnis noch nicht fertig ist? Alles andere will der Benutzer jetzt 
sowieso nicht sehen.

Der technische Vorteil lag einst (Anfang der 1980er) darin, daß ein 
Prozessor ohne Interruptfähigkeit einfacher und daher billiger war.

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.