Forum: Mikrocontroller und Digitale Elektronik "Big C" Pong und IC2 Bus. Wie?


von de8msh (Gast)


Lesenswert?

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.

von de8msh (Gast)


Lesenswert?

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>

von de8msh (Gast)


Lesenswert?

Ähhh... Lieber Moderator?! Kannst Du bitte den o.g. Post mit dem langen 
Code herausnehmen? Ich danke Dir sehr!

von Jens_Gr (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.