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
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.
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.
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
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.
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.
@ 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"
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.
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.
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
charx=0;
15
charz;
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
voidwriteLine(unsignedintx){
33
intj;
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
voidpushOut(void){
45
chari;
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).
Fast.
x brauchst du da nicht mehr und z muss auch wieder irgendwann 0 werden
1
Timer_ISR(){
2
staticuint8_tzeileCnt=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.
@ 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? ;-)
@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!
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
voidwriteLine(unsignedintx){
2
intj;
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
voidwriteByte(uint8_tbyte)
2
{
3
srcMirror=byte;
4
mirror();//Bits spiegeln
5
SSP1BUF=dstMirror;//schreibe lByte
6
while(SSP1STATbits.BF==0)
7
;
8
}
9
10
voidwriteLine(unsignedintx)
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
voidwriteLine(unsignedintx)
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.
@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.
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.
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.
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.
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.
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.