Timing-Berechnung des VGA-Signals mit MCU

Ich möchte ein VGA-Signal mit einem Mikrocontroller erzeugen. Aber es fällt mir schwer, online eine Lösung zu finden, wie man sie in Software generiert. Zum Beispiel erklärt normalerweise die gesamte Online-VGA-Signalerzeugung nur die Timing-Anforderungen für HSYNC und VSYNC zusammen mit dem Timing der hinteren und vorderen Veranda mit einigen festen Werten wie 640 x 480 bei 60 Hz oder 1024 x 786 bei 70 Hz usw. Aber was nicht angegeben ist, ist, wie sie und Pixel berechnet werden Uhr und andere Dinge. Wie berechnet man also das Timing für VSYNC und HSYNC zusammen mit der vorderen und hinteren Veranda für eine beliebige zufällige Auflösung bei einer zufälligen Bildwiederholfrequenz für z. B. 480 x 240 bei 60 Hz?

Danke für Antworten. Aschutosch

Antworten (3)

Es ist einfach genug, alles, was Sie brauchen, aus nur den grundlegenden bereitgestellten Informationen zu berechnen.

Die Website, die ich am häufigsten als Referenz verwende, ist beispielsweise diese: http://tinyvga.com/vga-timing/640x480@60Hz und sie enthält alles, was Sie für 640x480 @ 60Hz benötigen (sie gibt die gängigsten Auflösungen an, aber das ist die am einfachsten zu verarbeiten).

Es gibt alles in Pixeln und Zeilen an und bietet eine Pixeltaktfrequenz sowie Aktualisierungsfrequenzen. Alles, was Sie brauchen, ist der Pixeltakt und die Anzahl der Pixel für jedes Ding.

Er ergibt beispielsweise einen Pixeltakt von 25,175 MHz. Das ist für die meisten Mikrocontroller nicht einfach zu erzeugen, da es sowohl Hochfrequenz als auch Hochauflösung ist - im Allgemeinen können Sie eines dieser beiden haben - Hochfrequenz oder Hochauflösung. 25 MHz sind jedoch normalerweise einfach genug zu erzeugen und für die meisten Monitore "nah genug", um damit fertig zu werden.

Wir haben also einen Pixeltakt von 25 MHz. Wir haben auch eine "ganze Zeile" Größe von 800 Pixeln. Diese Größe umfasst die Veranden, die Synchronisation und den sichtbaren Bereich. Eine Zeile mit 800 Pixeln bei einem Takt von 25 MHz würde also mit (25.000.000/800) 31250 Hz oder einer Zeile alle 32 µs laufen.

Der horizontale Synchronisationsimpuls – 96 Pixel – wäre (96/25.000.000) = 3,84 µs lang.

Wir wissen, dass eine Zeile 32 µS benötigt, und es gibt 525 Zeilen in einem "ganzen Frame", also 0,000032 × 525 = 0,0168 s für einen Frame oder 59,524 Hz. Das ist ziemlich nah an den 60 Hz für die Spezifikation.

Wenn Sie also einen Pixeltakt und eine Reihe von Pixelperioden haben, können Sie alles berechnen. Natürlich kann man auch rückwärts gehen. Bei einer Bildrate und einer Auflösung können Sie Folgendes ausrechnen:

60 H z × 525 = 31500 H z

31500 H z × 800 P X = 25.2 M H z
Das zeigt, dass selbst die angegebenen Spezifikationen nicht 100 % genau sind, aber es gibt ein wenig Flexibilität bei den VGA-Timings, sodass Sie Ihre Uhr innerhalb gewisser Grenzen an Ihre Bedürfnisse anpassen können.

Und wo wir gerade dabei sind, das Generieren von VGA nur mit Software erfordert viel Verarbeitung und lässt Sie oft an CPU-Zyklen hungern, um irgendetwas zu tun. Einer der häufigsten "Tricks" zum Erzeugen eines VGA-Signals auf einer CPU ist die Verwendung von SPI zum Generieren des Pixeldatenstroms. Noch besser, wenn Sie DMA in Ihrem Mikrocontroller haben, um eine ganze Datenzeile auszugeben, ohne dass die CPU etwas tun muss. Die CPU ist dann nur noch dafür verantwortlich, die Sync-Impulse zu erzeugen und das DMA-System mit den richtigen Adressen zu laden – der Rest geschieht im Hintergrund. Damit bleibt Ihnen natürlich nur ein 1-Bit-Monochrom-Display. Wenn Sie zufällig eine SQI-Schnittstelle und genügend RAM haben, können Sie eine 4-Bit-Anzeige (16 Farben) leicht genug machen.

Das ist hilfreich!!! SO, nehmen wir zum Beispiel 640 x 480 in dem Link, den Sie geteilt haben, also sollte die vordere Veranda 1/40 der horizontalen Pixel betragen und so weiter. Kann ich also 12 Pixel für eine Breite von 480 horizontalen Pixeln verwenden, da es keine bestimmte Formel gibt?
480 ist keine geeignete Breite für eine erkannte Auflösung. Der Trick dabei ist, die Pixelgröße zu ändern. Behalten Sie (sagen wir) 640x480 als Ihre tatsächliche Auflösung bei, aber geben Sie die Pixel in Ihrem sichtbaren Bereich nicht mit der gleichen Geschwindigkeit aus. Obwohl der sichtbare Bereich die gleiche Zeit wie 640 Pixel benötigt, geben Sie tatsächlich 480 Pixel aus, die in der gleichen Zeit etwas langsamer sind (falls das Sinn macht).
okay, das ist logisch. Danke Majenko für die Info! :)

Obwohl die Formeln nicht bereitgestellt werden, enthält diese Seite einen Taschenrechner , mit dem Sie aus einer Liste entweder VGA oder SVGA (bis zu 1920 x 1080) auswählen können, und es werden etwa ein Dutzend verschiedene Parameter angezeigt. Sie können dann jeden dieser Parameter manuell ändern, und es werden Elemente wie Synchronisierungsfrequenzen, Impulslängen usw. neu berechnet.

Diese Seite ist eine andere, die nur Tabellen mit Parametern für verschiedene Auflösungen enthält, in vier Tabellen mit insgesamt über hundert verschiedenen Einträgen.

Dies ist eine knifflige Frage, da sie so eng mit der von Ihnen verwendeten MCU-Architektur und Bilderzeugungsschaltung gekoppelt ist. Ich habe es geschafft, indem ich angefangen habe, Makros zu definieren, mit denen ich verschiedene nützliche Dinge berechnen kann, wie Taktzyklen pro Zeile usw., und diese dann an die von mir verwendete Hardware angepasst habe.

Hier ist ein Ausschnitt aus Code, den ich für diesen Zweck geschrieben habe. Aller Wahrscheinlichkeit nach wird es für Sie als solches nicht nützlich sein, aber es könnte einen möglichen Lösungsansatz für das Problem aufzeigen.

/// Crystal frequency in MHZ (float, observe accuracy)
#define XTAL_MHZ 3.579545
/// Line length in microseconds (float, observe accuracy)
#define LINE_LENGTH_US 31.777557 
/// Frame length in lines (visible lines + nonvisible lines)
#define TOTAL_LINES 525
/// Number of visible lines in frame (excluding any border areas)
#define VISIBLE_LINES 480
/// Number of lines used for VSYNC
#define SYNC_LINES 2
/// Number of lines used after the VSYNC but before visible area
#define FRONT_PORCH_LINES 10

#define HSYNC_WIDTH_XTALCLKS 14
#define BACKPORCH_BORDER_XTALCLKS 14

#define FRONTPORCH_BORDER_XTALCLKS 12
/// Number of visible pixels (excluding any border areas)
#define VISIBLE_PIXELS 100
/// Width, in PLL clocks, of each pixel
#define PLLCLKS_PER_PIXEL 8
/// How many bits per pixel - this must match with the pattern generator microcode
#define BITS_PER_PIXEL 16

#define WORDS_PER_LINE ((VISIBLE_PIXELS * BITS_PER_PIXEL + 15) / 16)
#define FIRST_LINE (SYNC_LINES + FRONT_PORCH_LINES)
#define PLL_MHZ (XTAL_MHZ * 8.0)
#define PLLCLKS_PER_LINE ((u_int16)((LINE_LENGTH_US * PLL_MHZ)+0.5))
#define COLORCLKS_PER_LINE ((u_int16)((LINE_LENGTH_US * XTAL_MHZ)+0.5))
...and so on...