Hallo
Inzwischen kann ich das Teil erfolgreich flashen:
Bild hier
http://www.youtube.com/watch?v=MRRoa1hpnMQ
http://www.youtube.com/watch?v=JpfsYIkHjlw
Da wird sich meine Angetraute sicher sehr freuen, wenn ich ihr fünf so Dinger an den Christbaum hänge ;)
Dieses Beispielprogramm von der elo-Webseite habe ich ausgewählt, weil es zeigt, wie einfach die Daten an die LCD-Matrix ausgegeben werden. Und weil es einen brauchbaren Font mitbringt:
(Code von http://www.elo-web.de/elo/mikrocontr...ng/laufschrift)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 <util/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[] = " Frohes Fest und guten Rutsch :)\ ~"; /* 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 */ }
Gruß
mic
[Edit]
Bild hier
http://www.youtube.com/watch?v=tsTk4Un89uA
Neuer Bildspeicher mit nur 15 Bytes und set()/unset()-Funktionen. Echt ein nettes Spielzeug:
Code:#define F_CPU 8000000UL #include <inttypes.h> #include <avr/interrupt.h> #include <util/delay.h> uint8_t bildspeicher[15]; volatile uint8_t col = 0; uint8_t x, y; void set(uint8_t zeile, uint8_t spalte) { uint8_t temp; if(zeile < 8) bildspeicher[spalte] |= (1 << zeile); else { if(spalte<4) temp = 12; else if(spalte<8) temp = 13; else temp = 14; if(zeile & 1) bildspeicher[temp] |= (1<<((spalte%4)*2+1)); // Zeile 10 else bildspeicher[temp] |= (1<<(spalte%4)*2); // Zeile 9 } } void unset(uint8_t zeile, uint8_t spalte) { uint8_t temp; if(zeile < 8) bildspeicher[spalte] &= ~(1 << zeile); else { if(spalte<4) temp = 12; else if(spalte<8) temp = 13; else temp = 14; if(zeile & 1) bildspeicher[temp] &= ~(1<<((spalte%4)*2+1)); // Zeile 10 else bildspeicher[temp] &= ~(1<<(spalte%4)*2); // Zeile 9 } } int main(void) { cli(); DDRC = 0x0f; DDRB = 0xff; DDRD = 0xff; /*--------------------------------------------------------------------------- * 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 while(1) { for(x=0; x<15; x++) bildspeicher[x] = 0b10101010; _delay_ms(500); for(x=0; x<15; x++) bildspeicher[x] = 255; // alle LEDs an _delay_ms(1000); for(x=0; x<15; x++) bildspeicher[x] = 0; // alle LEDs aus _delay_ms(500); for(x=0; x<12; x++) for(y=0; y<10; y++) { set(y, x); _delay_ms(25); } _delay_ms(1000); for(y=10; y; y--) for(x=12; x; x--) { unset(y-1, x-1); _delay_ms(25); } _delay_ms(1000); } return (0); } /* ------------------------------------------------------------------------- * 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 = bildspeicher[col]; portdout = ledval & 0xff; /* low byte */ portcout = portdout & 0x0f; /* low nibble */ portdout = portdout & 0xf0; /* high nibble */ PORTD = portdout & 0xff; PORTC = portcout & 0xff; if(col<4) ledval=bildspeicher[12]; else if(col<8) ledval=bildspeicher[13]; else ledval=bildspeicher[14]; PORTB = (ledval >> (col%4)*2) & 0x03; /* high byte */ sei(); /* Interrupts wieder erlauben */ }







Zitieren


Lesezeichen