www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LED Matrix Ansteuerung - Denkanstoß


Autor: matrix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe eine 10x11 LED Matrix aufgebaut. Über einen Timer wird in jeder 
Millisekunde eine Zeile aktiv geschaltet. GLeichzeitig habe ich ein 11 
Felder großes Array für das "Spaltenmuster" welches ich für die grade 
aktive Zeile auf den Port des uC lege.
void schreibe_matrix() {
  maske = (1 << aktive_zeile); //wird in der Timer ISR hochgezählt
  PORTA = maske;
  if(aktive_zeile > 7) {
    PORTF = maske >> 8;
  }
  PORTC = ~spaltenmuster[aktive_zeile];
  PORTD = ~spaltenmuster[aktive_zeile] >> 8;
}

Diese Lösung ist leider sehr unflexibel in der Ansteuerung der Spalten.

Jemand einen Tipp wie ich ein 2-dimensionales Array LED[11][10] nun in 
meine Funktion für die Ansteuerung übersetzen könnte?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
matrix schrieb:

> Diese Lösung ist leider sehr unflexibel in der Ansteuerung der Spalten.

Warum?

> Jemand einen Tipp wie ich ein 2-dimensionales Array LED[11][10] nun in
> meine Funktion für die Ansteuerung übersetzen könnte?

Keine gute Idee.

Abgesehen davon, dass man

   (1 << aktive_zeile)

nicht macht, weil man nicht mit einer variablen Bitzahl schieben will, 
ist der Rest so schon in Ordnung. (Fast: Erst die LED abschalten, so 
dass nichts leuchtet, dann die neue Zeile setzen und erst dann die LED 
in der neuen Spalte einschalten. Ansonsten hast du Geisterleuchten)

Die Daten werden so zurecht gelegt, dass man in der ISR möglichst 
einfach, effizient und schnell darauf zugreifen kann. Die ISR soll so 
schnell wie möglich laufen, damit sie den restlichen Programmfluss 
möglichst wenig beeinflusst.

Was versprichst du dir von einem 2D Array, was du von 2 Funktionen
void SetPixel( uint8_t x, uint8_t y )
{
  ...
}

void ClearPixel( uint8_t x, uint8_t y )
{
  ...
}
nicht kriegst?

Autor: matrix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mhh eigentlich hast du recht. Aber müsste ich bei den Funktionen nicht 
auch mit einer variablen Bitzahl schieben? (Warum sollte man das 
überhaupt vermeiden?)
void setPixel(uint8_t x, uint8_t y) {
      spaltenmuster[y] = (1 << x); //wobei hier das Problem wäre das 0,0 nicht links oben ist?
}

Ich glaub ich steh auf dem Schlauch!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
matrix schrieb:
> Mhh eigentlich hast du recht. Aber müsste ich bei den Funktionen nicht
> auch mit einer variablen Bitzahl schieben? (Warum sollte man das
> überhaupt vermeiden?)

Weil dein AVR auf Assembler Ebene dafür keine Instruktion hat, sondern 
der Compiler das mit einer Schleife umsetzen muss.

>
>
void setPixel(uint8_t x, uint8_t y) {
>       spaltenmuster[y] = (1 << x); //wobei hier das Problem wäre das 0,0
> nicht links oben ist?
> }

* Das Problem lässt sich aber lösen.
  Du bist der Programmierer, du kannst das zurechtbiegen

* Ja, du musst auch hier variabel schieben. Klar.
  In der Programmierung gibt es aber eine schöne 'Faustregel', die da
  "Time for Space" lautet.
  Man meint damit: Durch den Einsatz von Speicherplatz kann man oft
  Laufzeit sparen und umgekehrt.
uint8_t Shift[] = ( 1 << 0, 1 << 1, 1 << 2, 1 << 3,
                    1 << 4, 1 << 5, 1 << 6, 1 << 7 };

das sind zb alle Bitmuster, die mit Verschiebungen on 0 bis 7 Bit 
möglich sind.

   Anstelle von

   1 << x

kann man daher auch schreiben

   Shift[x];

und kriegt dasselbe. Nur eben schneller.

Allerdings muss das in deiner ISR nicht so aufwändig gemacht werden. Du 
weißt ja, dass active_zeile nicht wild hin und her springt, sondern 
geordnet immer um 1 höher wird. WEnn du dir daher die Maske aufhebst und 
die Maske immer nur um 1 Stelle nach links verschiebst, hast du dasselbe 
Ergebnis, als wie wenn du 1 << active_zeile jedesmal neu berechnest.
ISR( .... )
{

  PORTC = 0xFF;
  PORTD = 0xFF;

  aktive_zeile++;
  maske <<= 1;

  if( aktive_zeile == 11 ) {
    aktive_zeile = 0;
    maske = 0x01;
  }
  
  PORTA = maske;
  PORTF = maske >> 8;

  PORTC = ~spaltenmuster[aktive_zeile];
  PORTD = ~spaltenmuster[aktive_zeile] >> 8;
}

Autor: matrix (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles klar, Danke!
Ich denke darauf kann sogar ich aufbauen ;)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.