Danke euch dreien für die Ausführungen.
Zitat von
radbruch
... Das habe ich hier auch schon mal beschrieben ...
Ja, das hatte ich (leider nur) überflogen, bevor mich die Schnapsidee überkam das selbst zu machen. Und so läuft das ja auch bei mir. Die LED-Ansteuerung hatte ich mir zu Beginn meiner Überlegungen am Oskar angesehen (2-Kanal analog) und daraus Timing und Schaltweise entnommen. Die Funktion LED=an wenn A high und K low ist war dann Ausgangspunkt für die Steuerung.
Realisiert ist die Ansteuerung der LEDs in einer ISR die alle 250 µs aufgerufen wird. Darin wird die vorhergehende Zeile ausgeschaltet, das Schieberegister mit dem aktuellen Bitmuster versorgt, aktiv geschaltet und danach die neue Zeile eingeschaltet. Frisst rund 50% CPU-Zeit und ergibt eine augenfreundliche Frequenz von 400 Hz. Meine Annahme war dabei, dass die 2000 Maschinenzyklen zwischen zwei Interrupts genug wären um IRS und Hauptprogramm abzuarbeiten. Und das funktionierte schon prächtig : die beiden Rackets laufen mit Potisteuerung brav in ihren Grenzen auf und ab.
Code:
// ===============================================================================
// Interruptroutinen
// ===============================================================================
// ===============================================================================
// === Initialisierung der Ports auf ATMEGA8 AU auf Vektor 10 (1-19) TIMER0 OVF
// Timer/Counter0 Overflow mit ###>>> 250 µs bei 8 MHz
//TCCR0 |= (1<<CS01); // 1/8 Prescaler, 250 µs bei 8 MHz
// entsprechend 250*8 = 2000 Maschinenzyklen
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ISR (TIMER0_OVF_vect) // ISR schaltet LED der Reihe nach
{ //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SetBit (PORTD, 3); // Zeitnahmeblink ein
Izeit_1 ++; // Boardzeit hochtickern
if (Izeit_1 == 4001) Izeit_1 = 1; // ... und eingrenzen
TC ++; // ISR-Timercount incrementieren
if (TC == 11) TC = 1; // ... und eingrenzen
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Es beginnt die Schalterei der LEDs, Zeile für Zeile,
// Zuerst "alte Zeile" ausschalten (case), danach Zeilenmuster einlesen
// - - - - - - - - - - - - - - -
switch (TC) { //
case 1: //
ClrBit (PORTB, 1); // Zeile 0 aus - letzte Zeile
break; // switch verlassen
case 2: //
ClrBit (PORTC, 0); // Zeile 1 aus-
break; // switch verlassen
case 3: //
ClrBit (PORTC, 1); // Zeile 2 aus-
break; // switch verlassen
case 4: //
ClrBit (PORTC, 2); // Zeile 3 aus-
break; // switch verlassen
// - - - - - - - - - - - - - - -
case 5: //
ClrBit (PORTC, 3); // Zeile 4 aus-
break; // switch verlassen
case 6: //
ClrBit (PORTD, 4); // Zeile 5 aus-
break; // switch verlassen
case 7: //
ClrBit (PORTD, 5); // Zeile 6 aus-
break; // switch verlassen
case 8:
ClrBit (PORTD, 6); // Zeile 7 aus-
break; // switch verlassen
case 9:
ClrBit (PORTD, 7); // Zeile 8 aus-
break; // switch verlassen
case 10:
ClrBit (PORTB, 0); // Zeile 9 aus-
break; // switch verlassen
default:
break;
} // Ende switch (TC), Zeile TC ausschalten
// - - - - - - - - - - - - - - -
// "Alte Zeile" wurde ausgeschaltet, jetzt aktuelles Zeilenmuster einlesen
// Aktuell ist die Zeile TC
//
for (LPp = 4; LPp < 16; LPp++)
{ //
if (IsBitSet (L[TC], LPp)) //
{ ClrBit (PORTB, dta); } // Data low <=> LED on
else { SetBit (PORTB, dta); } // Data high <=> LED off
ClrBit (PORTB, clk); // Clock low
SetBit (PORTB, clk); // Clock high
} // Ende for (LPp = 0; LPp == 7; LPp++)
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Neue Zeilen einschalten mit case TC, danach strobe auf Schieberegister
// - - - - - - - - - - - - - - -
switch (TC) { //
case 1: //
SetBit (PORTC, 0); // Zeile 1 ein - erste Zeile
break; // switch verlassen
case 2: //
SetBit (PORTC, 1); // Zeile 2 einschalten
break; // switch verlassen
case 3: //
SetBit (PORTC, 2); //
break; //
case 4: //
SetBit (PORTC, 3); //
break; //
// - - - - - - - - - - - - - - -
case 5: //
SetBit (PORTD, 4); // Zeile 5 einschalten
break; // switch verlassen
case 6: //
SetBit (PORTD, 5); //
break; //
case 7: //
SetBit (PORTD, 6); //
break; //
case 8: //
SetBit (PORTD, 7); //
break; //
case 9: //
SetBit (PORTB, 0); //
break; //
case 10: //
SetBit (PORTB, 1); // Zeile 0 einschalten
break; // switch verlassen
default:
break;
} // Ende switch (TC), Zeile TC einschalten
// - - - - - - - - - - - - - - -
// Neue Zeilen sind eingeschaltet, jetzt strobe
//
ClrBit (PORTB, str); // Strobe low
SetBit (PORTB, str); // Strobe high
// Ende Ausgabe für Zeilen
// - - - - - - - - - - - - - - -
ClrBit (PORTD, 3); // Zeitnahmeblink aus
// Zeitnahme am 20. Feb. 2011: Routine x10 benötigt
return; // Ende ISR
} //
// ===============================================================================
So - aufgefallen ist mir dabei, dass mehrere LEDs in einer Reihe leuchten können - ist ja klar, weil mehrere eben mehr Strom brauchen als eine *ggg*. Einfachstes Beispiel: beide Schläger stehen auf gleicher Höhe, es leuchten zwei LEDs in einer Reihe und damit sieht man ein klitzekleines Einbrechen der Helligkeit. Das stimmt ja auch mit einfachsten Überlegungen überein. Es ist kaum merklich - aber ich wollte wissen, ob diese Matrixfahrweise eben die LEDs einzeln oder zeilenweise ansteuert.
Also - zeilenweise. Und der geringe Helligkeitseinbruch ist ja auch praktisch kaum zu sehen.
Nochmal danke für die Hilfe.
Lesezeichen