Hallo, ich möchte gerne einen Scroller auf zwei oder mehr Platinen zu verteilen. D.h. die erste scroll, bis der Rand erreicht ist und gibt die anzuzeigenden Werte dann an die zweite Platine, die wiederum bis zu Rand scrollt. Dass könnte man auf >2 Platinen erweitern. Aber wie mache ich das? Ich würde gerne diese Code von Sasche Bader dazu anpassen: http://www.elo-web.de/xattachment/Laufschrift.zip Artikel: http://www.elo-web.de/elo/mikrocontroller-und-programmierung/ping-pong/laufschrift Kann man soetwas in den o.g. Code implementieren? ATMega8 Pins sind ja noch welche frei: http://www.elo-web.de/elo/mikrocontroller-und-programmierung/ping-pong/erweiterung-fuer-die-ping-pong-platine# Ich danke Euch für die Unterstützung.
Hier der Code: <code> /* * laufschrift.c * * Ein einfache "Laufschrift" auf dem Ping-Pong Board. * * Kompilierbar mittels AVR Studio 4 oder WinAVR * * Der Sourcecode und das Hexfile dürfen frei verwendet werden. * Nutzung erfolgt auf eigene Gefahr. * * Ver. Date Author Comments * ------- ---------- -------------- ------------------------------ * 1.00 07.11.2009 Sascha Bader initial */ /* ----------------------------------------- * Defines (Präprozessor Makros) * -----------------------------------------*/ #define F_CPU 8000000UL /* CPU Takt (für delay-Routine) */ #define WIDTH 12 /* Breite des Displays */ #define HEIGHT 10 /* Höhe des Displays */ #define FONTWIDTH 8 /* Breite des Zeichensatzes */ #define FONTHEIGHT 10 /* Höhe des Zeichensatzes */ #define GetPixel(x,y) leds[y]&(1<<x) /* Makro: Ein "Pixel" auslesen */ #define SetPixel(x,y) leds[y]|=1<<x /* Makro: Ein "Pixel" setzen */ #define ClearPixel(x,y) leds[y]&=~(1<<x) /* Makro: Ein "Pixel" löschen */ /* ----------------------------------------- * Includes * -----------------------------------------*/ #include <inttypes.h> /* Definition der Datentypen uint8_t usw. */ #include <avr/interrupt.h> /* Interruptbehandlungsroutinen (für Timerinterrupt) */ #include <avr/delay.h> /* Definition der Verzögerungsfunktionen (_delay_ms) */ #include <avr/pgmspace.h> /* Hilfsfunktionen um Daten aus dem Flash zu lesen */ #include "font.h" /* Definition des Zeichensatzes */ /* ----------------------------------------- * Globale Variablen * -----------------------------------------*/ uint16_t leds[WIDTH]; /* Inhalt der LED-Matrix */ prog_uint8_t * fnt = (prog_uint8_t *) font; /* Zeiger auf den Zeichensatz im Flash */ volatile uint8_t col = 0; /* Aktuelle Spalte (für Interruptroutine) "volatile", da durch Interrupt verändert */ /* ----------------------------------------- * Text der Laufschrift (Globele Variable) * -----------------------------------------*/ prog_uint8_t text[] = " Es gibt eine Theorie, die besagt, wenn jemals irgendwer genau herausfindet,\ wozu das Universum da ist und warum es da ist, dann verschwindet es auf der Stelle\ und wird durch noch etwas Bizarreres und Unbegreiflicheres ersetzt.\ - Es gibt eine andere Theorie, nach der das schon passiert ist. \ ~"; /* Ende-Kennzeichen (nicht vergessen) */ /* ----------------------------------------- * Prototypen der Funktionen * -----------------------------------------*/ void PrintScrollColumn(uint8_t c, int pixelx, int y); void ScrollLeft(void); /* ------------------------------------------------------------------------ - * Main Funktion * * Initialisiert den Timer Interrupt und * behandelt die Laufschrift * ------------------------------------------------------------------------ -*/ int main(void) { uint8_t * tpos; uint8_t softx; cli(); // Interrupts sperren (damit keiner dazwischenfunkt) /*--------------------------------------------------- * Ports konfigurieren (Ein-/Ausgänge) *---------------------------------------------------*/ DDRC = 0x0f; // ( 0x0f PORTC als AD-Eingang) DDRB = 0xff; // Portb = Output DDRD = 0xff; // Portd = Output /*---------------------------------------------------------------------- ----- * 8-Bit Timer TCCR0 für das Multiplexing der LEDs initialisieren * Es wird ca. alle 2 Mikrosekunden ein Overflow0 Interrupt ausgelöst * Berechnung: T = Vorteiler * Wertebereich Zähler / Taktfreuenz * = 64 * 256 / ( 8000000 Hz ) = 2,048 ms *----------------------------------------------------------------------- ----*/ TCCR0 |= (1<<CS01) | (1<<CS00); // 8-bit Timer mit 1/64 Vorteiler TIFR |= (1<<TOV0); // Clear overflow flag (TOV0) TIMSK |= (1<<TOIE0); // timer0 will create overflow interrupt sei(); // Interrupts erlauben /*--------------------------------------------------- * Hauptschleife (Laufschrift erzeugen) *---------------------------------------------------*/ while(1) // Endlosschleife { for (tpos=text;pgm_read_byte(tpos)!='~';tpos++) // Aktuelles Zeichen lesen { for (softx=0;softx<FONTWIDTH;softx++) // Pixel des Zeichens abarbeiten { ScrollLeft(); // Platz schaffen und Zeilen nach links schieben PrintScrollColumn(pgm_read_byte(tpos),softx,0); // Ganz rechts eine Spalte des Zeichens ausgeben _delay_ms(35); // Ein bischen warten damit es nicht zu schnell wird } } } return 0; } /* ------------------------------------------------------------------------ - * Funktion PrintScrollColumn * * Aktualisiert die Spalte ganz rechts mit * einem 1 "Pixel" breitem Ausschnitt des * Lauftextes. * * \param c Auszugebendes Zeichen * \param pixelx Auszugebende Spalte des Zeichens * \param y Vertikale Vverschiebnung * ------------------------------------------------------------------------ -*/ void PrintScrollColumn(uint8_t c, int pixelx, int y) { unsigned char fontbyte = 0; uint8_t pixelpos; uint8_t fonty; uint8_t mask; pixelpos = pixelx & 0x07; /* Auf 8 Pixel pro Zeichen limitieren */ for (fonty=0;fonty<FONTHEIGHT;fonty++) { fontbyte = pgm_read_byte_near(fnt+c*FONTHEIGHT+fonty); /* Ein Byte (Zeile) des aktuellen Zeichens lesen */ mask = 1<<pixelpos; /* Maske auf die gewünschte Spalte zurechtschieben */ if ((fontbyte & mask) != 0) /* Prüfen ob das Bit in der Spalte des Zeichens gesetzt ist */ { leds[WIDTH-1]|=1<<fonty; /* Setzen eines Pixels im Display ganz rechts */ } else { leds[WIDTH-1]&=~(1<<fonty); /* Löschen eines Pixels im Display ganz rechts */ } } } /* ------------------------------------------------------------------------ - * Funktion ScrollLeft * * Verschiebt den Inhalt LED-Matrix um eine Spalte nach links. * Die erste Spalte tritt dabei an die Position der letzten Spalte. * ------------------------------------------------------------------------ -*/ void ScrollLeft(void) { uint8_t xcol; /* Spaltenzähler */ uint16_t first; /* Zwischenspeicher der ersten Spalte */ first = leds[0]; /* Erste Spalte sichern */ for (xcol=0;xcol<WIDTH-1;xcol++) { leds[xcol]=leds[xcol+1]; /* Spalten nach links verschieben */ } leds[WIDTH-1] = first; /* Erste Spalte an letzte Spalte kopieren */ } /* ------------------------------------------------------------------------ - * Interrupt Routine * * Gibt nacheinander alle Spalten mit LED-Daten aus. * Dazu wird mittels der Schieberegister die aktuelle Spalte * ausgewählt und dann das Bitmuster derselben auf die Ports * gegeben. * Beim nächsten Interrupt ist dann die nächste Spalte dran. * ------------------------------------------------------------------------ -*/ // interrupt routine SIGNAL (SIG_OVERFLOW0) { uint16_t ledval; uint8_t portcout; uint8_t portdout; cli(); /* Interrupts verbieten */ /*-------------------------------------------------- * Aktuelle Spalte ermitteln *--------------------------------------------------*/ col++; if (col == 12) { col = 0; } /*-------------------------------------------------- * Ports initialisieren *--------------------------------------------------*/ PORTD = 0; PORTB = 0; PORTC = 0; /*--------------------------------------------------- * Eine einzelne 0 durch die Schiebergister schieben *---------------------------------------------------*/ if ( col == 0 ) { PORTB &= ~(1 << 4); /* Bei der ersten Spalte eine 0 ausgeben (PB4 = 0) */ /* Diese 0 geht auf die Reise durch die Schieberegister */ } else { PORTB |= (1 << 4); /* Danach Einsen hinterherschicken (PB4 = 1) */ } /*--------------------------------------------------- * Impulse für die Schieberegister generieren *---------------------------------------------------*/ PORTB |= (1 << 3); /* PB3 = 1 (cl) */ PORTB &= ~(1 << 3); /* PB3 = 0 (!cl) */ PORTB |= (1 << 2); /* PB2 = 1 (str) */ PORTB &= ~(1 << 2); /* PB2 = 0 (!str) */ /*--------------------------------------------------- * Daten der Spalte holen und auf die Ports verteilen *---------------------------------------------------*/ ledval = leds[col]; portdout = ledval & 0xff; /* low byte */ portcout = portdout & 0x0f; /* low nibble */ portdout = portdout & 0xf0; /* high nibble */ PORTD = portdout & 0xff; PORTC = portcout & 0xff; PORTB = (ledval >> 8) & 0x03; /* high byte */ sei(); /* Interrupts wieder erlauben */ } </code>
Ähhh... Lieber Moderator?! Kannst Du bitte den o.g. Post mit dem langen Code herausnehmen? Ich danke Dir sehr!
Ich habe zwei Platinen zu einer Laufschrift zusammengestellt. Dazu habe ich eine Taktleitung und eine Syncleitung gebraucht. Sync wartet einfach bis das erste Display voll geschrieben ist, gibt dann ein Signal aus wenn eine neue Spalte gebrauch wird. Sync taktet also mit der Anforderung das eine neue Spalte gebraucht wird. Die Taktfrequenz ist 12x N von der Syncfrequenz um das Displax direkt zu synchronisieren. Das ist besser wegen Syncproblemen. Ich habe N=7 so das ich 7 Graustufen habe. Ich verwende 7x12 Spalten intern und gebe je LED-Spalte 7 interne Spalten aus. Also wird alles dann schön weich bei dem laufen des Textes. Das war es mal ---- Jens
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.