Einzelne Bits vom Wert eines Array-Elem. auf Port-Pins ?

Gast #558458
Lesenswert?

Hallo,

ich muss eine Laufschrift für eine 8x15 LED-Matrix machen.

Bei einem Interrupt sollen auf einer Matrixspalte versch. Leds leuchten, 
damit  nach 6 Interrupts ein vollständiges Zeichen dargestellt werden 
kann. Die benötigte Segment-Belegung ist in einem Array gespeichert.

Bei jedem neuen Interrupt steht also ein 8 Bit Wert zur Verfügung,

z.B. 0b01100010

Entsprechend müssen dann in der aktuellen Spalte die Zeilen 2,6 und 7 
leuchten.

Die Zeilen, d.h. die zuständigen Pins in den Ports müssen anhand dieses 
Arrays entweder auf '0' oder '1' gesetzt werden.

Wie mach ich das? Bitte helft mir, Danke.

Mfg.
Gast #558468
Lesenswert?

Du willst also die LED-Matrix multiplexen?
16 SPalten zu je 8 Zeilen?

Wie findet die Spaltenaktivierung statt?

Das Programm muss etwa so aussehen:
1
global:
2
uint8_t   anzeige[16];   // hier müssen die anzuzeigenden Werte hin
3

4
ISR ( SPalteninterrupt )         // zB Timer overflow
5
{
6
     static   uint8_t    spalte;
7
     //-- neue Spalte errechnen--------
8
     spalte++;
9
     //-- Spalte auf 0..15 begrenzen---
10
     spalte   &=  0x0F;                      // 2*)
11
     //-- Ausgabe aktive Spalte--------
12
     PORT_wasweißich_1  = spalte;            // 1*)
13
     //-- Ausgabe LED-Anzeige----------
14
     PORT_wasweißich_2  = anzeige [ spalte ];
15
}


1*) Das muss evtl angepasst werden, abhängig von der Hardwareseitigen 
ansteuerung der Spalten.

2*) Falls du nur 15Spalten hast (also 0..14), dann muss das so aussehen:
if ( spalte == 15 ) spalte = 0x00;
Gast #558614
Lesenswert?

Hallo Matthias,

die Matrix hat [0..14] Spalten. Ich habe das Programm für 
Spaltenaktivierung schon geschrieben und es sieht bei mir so aus:
1
ISR(TIMER2_COMP_vect)              //Interrupt ausgelöst
2
 {
3
  Interrupt_Zaehler++;
4
  
5
  if (Interrupt_Zaehler < 15)
6
   {
7
    //---> HIER SOLL aktuelle Array-Bit-Belegung auf Zeilenports übertragen werden, aber WIE?
8
    //
9
    PORTB=Spalte_RAM [Spalten_Nr][0];   //Spalte
10
    PORTC=Spalte_RAM [Spalten_Nr][1];   //aktivieren
11
    Spalten_Nr++;
12
   }
13
    
14
  else if (Interrupt_Zaehler == 15)         //letzte Spalte
15
   {
16
    // HIER SOLL aktuelle Array-Bit-Belegung auf Zeilenports übertragen werden, aber WIE?
17
    //
18
    PORTB=Spalte_RAM [Spalten_Nr][0];    //Spalte 
19
    PORTC=Spalte_RAM [Spalten_Nr][1];    //aktivieren
20
    Spalten_Nr = 0;
21
    Interrupt_Zaehler = 0;
22
   }
23
 }


ich habe um Funktionalität zu prüfen alle Zeilenports in main() 
aktiviert, und auf der LED-Matrix laufen also volle Spalten. Das macht 
den Effekt,dass alle LEDS an sind, Spalten leuchten aber alle 
nacheinander mit ca. 130 Hz
http://rapidshare.com/files/30595793/video.rar
Aber es sollen eben nicht alle Zeilenbits aktiviert werden, sondern nur 
die, die benötigt werden um ein Zeichen darzustellen.

Diese Bits sind im Array [128][6] definiert (128 Zeichen, 6 Spalten pro 
Zeichen) Ein Element in [20][3] liefert z.B. 0b00001111  Das bedeutet 
dass nur die oberen 4 zeilen aktiviert werden müssen. Wie teile ich 
diese Bits den Ports mit ??

Ich muss für Zeile 0 in dem PORTD PD5 auf 0 setzten
         für Zeile 1        PORTD PD6 auf 0 setzten
...      für Zeile 7        PORTC PC4 auf 0 setzten ... usw.

Wenn ich weiß, wie sich das realisieren lässt, dann kann ich das 
Programm zu Ende machen (hoffe ich)
Gast #558682
Lesenswert?

Sieht auf den ersten Blick etwas konfus aus.
Poste doch mal bitte die KOMPLETTE Schaltung, dann kann ich dir sagen, 
wie du das machen musst.

PS: was ist das für ein komischer Link??
Hänge doch einfach Dateien hier an...

Nochmal zum Verständnis:
Das Display soll so angesteuert werden, dass alle LEDS (8*15=120Stück) 
für das Auge zugleich leuchten?

Gruß
Gast #558956
Lesenswert?

Hallo,

das Display soll so angesteuert werden, dass ein lesbarer laufender Text 
auf den Leds erscheint.

(zu meinem Problem:)
Es ist mir mttlerweile gelungen auf jeder Spalte immer nur die richtigen 
LEDS zu schalten:
1
        PORTC |= _BV(PC3);           // zuerst alle PORTs  
2
  PORTC |= _BV(PC4);       // für Zeilen        
3
  PORTD = 0b11111100;          // auf "1", d.h. "AUS"
4
  
5
  if (Array_ & 0b00000001) PORTD &= ~_BV(PD5);   // "Array_" entspricht dem Wert
6
  if (Array_ & 0b00000010) PORTD &= ~_BV(PD6);   // für PORT-Belegung, für irgendein Zeichen
7
  if (Array_ & 0b00000100) PORTD &= ~_BV(PD7);
8
  if (Array_ & 0b00001000) PORTD &= ~_BV(PD2);
9
  if (Array_ & 0b00010000) PORTD &= ~_BV(PD3);
10
  if (Array_ & 0b00100000) PORTD &= ~_BV(PD4);
11
  if (Array_ & 0b01000000) PORTC &= ~_BV(PC3);
12
  if (Array_ & 0b10000000) PORTC &= ~_BV(PC4);

Bei jeder Spalte schaltet dieser Code verschiede Leds und schon nach den 
ersten 6 Spalten erscheint das erste Zeichen des Textes.

Jetzt muss ich noch irgendwie hinkriegen, dass die Zeichen langsam 
wandern.
z.B. die ersten 5 Durchläufe durch die 15 Spalten bleibt der Text 
stehen, zum Anfang des 6. Durchlaufes verschiebt sich der Text um 1/6 
eines Zeichens nah links oder so ähnlich.

Ich bin für alle Tipps dankbar ;)
Mfg.
Gast #559352
Lesenswert?

Habe zwar den Schaltplan immer noch nicht gesehen, aber ich glaube du 
hast gegen einen wichtigen Grundsatz verstoßen:
Beim Entwickeln der Schaltung an die Software(seitige Ansteuerung) 
denken..

Wie auch immer.
Ich würde folgendes raten:
Ein Interruptprogramm (zB Timer Overflow)
Das tut nur ein
uint8_t Array[15];
ausgeben, etwa so, wie ich im ersten Post dargelegt habe.
Somit ist garantiert, dass immer die Information im array[0] auf Spalte 
Null,
array[1] auf Spalte Eins... ausgegeben wird.
Dies geschieht unabhängig von weiteren Programmteilen.

Das Hauptprogramm (main) tut jetzt in regelmäßigen Abständen den Inhalt 
von Array[15] nach rechts/links verschieben, neue Inhalte in dieses 
Array rein kopieren,....

SO ist das eine sehr saubere Lösung...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren