Projekte

So zeigen Sie ein Bild auf einem LCD mit einem EFM8-Mikrocontroller an

Bildübertragung vom PC zum TV - PC SOS TV Episode 11 2012[HD] (Dezember 2018).

Anonim

So zeigen Sie ein Bild auf einem LCD mit einem EFM8-Mikrocontroller an


Erfahren Sie, wie Sie mit der USB-Funktion des EFM8 ein Bild von Ihrem PC auf ein LCD übertragen.

Empfohlene Stufe

Mittlere

Vorherige Artikel in dieser Serie

  • Die EFM8-Serie von Silicon Laboratories: Eine leistungsstarke neue Embedded-Entwicklungsplattform
  • LCD über SPI steuern: Eine Einführung in die Projektentwicklung mit einem EFM8 Microcontroller
  • Anzeigen von Zeichen auf einem LCD mit einem EFM8-Mikrocontroller
  • Kommunikation mit einem EFM8 Microcontroller über USB

Benötigte Hardware / Software

  • SLSTK2000A EFM8-Evaluierungsboard
  • Simplicity Studio integrierte Entwicklungsumgebung
  • Scilab

Projektübersicht

In früheren Projekten untersuchten wir die Implementierung der SPI-Funktionalität des EFM8, die Kommunikation mit einem LCD-Modul, das Formatieren und Drucken von 10x8 Pixel großen Zeichen sowie das Herstellen einer USB-Verbindung zwischen dem EFM8 und SciLab mithilfe der VCPXpress-Bibliothek. Das aktuelle Projekt bringt diese Fähigkeiten zusammen, um ein 128-mal-128-Pixel-Bild auf dem LCD effizient und bequem anzuzeigen. Das Ziel ist, mit einer Standard-Graustufen-BMP-Bilddatei zu beginnen und Scilab zu verwenden, um sie zu verarbeiten und dann über USB auf den EFM8-Mikrocontroller zu übertragen, so dass wir sie auf einem 128-mal-128-Pixel-LCD anzeigen können. Dieses Projekt verarbeitet nur ein einziges Bild, aber die hier vorgestellten Techniken könnten leicht angepasst werden, um eine einfache Animation anzuzeigen, die aus einer Reihe ähnlicher Bilder besteht.

Der Prozess beginnt mit dem Erstellen des Bildes mit Paint.NET oder einer anderen Bildbearbeitungsanwendung. Dieses Bild wird in Scilab geladen, in ein mit dem LCD kompatibles Format umgewandelt, in eine Matrix von Pixeldaten umgewandelt und über 64-Byte-USB-Pakete an das EFM8 übertragen. Eine aktualisierte SPI-Zustandsmaschine wird dann verwendet, um diese Pixeldaten, vier Zeilen gleichzeitig, zu dem LCD-Modul zu übertragen.

Port I / O

Die Port-E / A-Konfiguration ist identisch mit der im vorherigen Artikel verwendeten Konfiguration.

Die SPI-Signale werden auf die entsprechenden Port-Pins abgebildet, mit Ausnahme des Chip-Select-Signals, das wir manuell über P0.1 ansteuern. Wir müssen die Port-Pins für die USB-Datenleitungen nicht direkt konfigurieren; Die Initialisierung aller USB-Peripheriegeräte erfolgt über die VCPXpress-Bibliothek.

Peripheriegeräte und Interrupts

Das Setup für Peripherie und Interrupt ist identisch mit dem im vorherigen Artikel: SPI ist für die Kommunikation mit dem LCD-Modul konfiguriert, und Timer4 wird für kurze Verzögerungen verwendet. Wir verwenden Timer2 nicht in diesem Projekt, da wir keine Bildrate benötigen. Stattdessen wird das LCD sequentiell aktualisiert, wenn Pixeldatenpakete von dem PC empfangen werden.

Firmware

Die VCP-Konfiguration für dieses Projekt ist identisch mit der im vorherigen Projekt verwendeten Konfiguration. Es gibt jedoch einige zusätzliche USB-Funktionen: Bisher hat der EFM8 nur Daten von Scilab empfangen, während jetzt auch der EFM8 Daten überträgt.

 void USBTxByte(unsigned char BytetoSend) { Block_Write(&BytetoSend, 1, &USBBytesTransmitted); } 

Wie der Name der obigen Funktion Block_Write () andeutet, kann die VCPXpress-Bibliothek ein Array von Bytes mit einem Funktionsaufruf übertragen. In diesem Projekt werden USB-Übertragungen vom EFM8 jedoch nur zur Ablaufsteuerung verwendet: Der EFM8 sendet ein Byte, um Scilab mitzuteilen, dass es Zeit ist, weitere Daten zu senden. Die USBTxByte () - Funktion ist also eine einfache Möglichkeit, Block_Write () zu verwenden, um ein einzelnes Byte zu übertragen.

Empfangene USB-Pakete werden mit dem folgenden Code behandelt:

 if (API_InterruptCode & RX_COMPLETE) // USB read complete { if(USBBytesReceived == 1 & USBRxPacket(0) == NEW_IMAGE_FLAG) { CLEAR_LCD = TRUE; NextLinetoWrite = 0; //return the new image flag byte to the PC for flow control USBTxByte(NEW_IMAGE_FLAG); //continue with the next USB read procedure Block_Read(USBRxPacket, USB_PACKET_SIZE, &USBBytesReceived); } else if(USBBytesReceived == USB_PACKET_SIZE) { /*this flag tells the while loop in ImagetoLCD_main.c to process a received USB pixel data packet*/ USB_PACKET_RECEIVED = TRUE; //continue with the next USB read procedure Block_Read(USBRxPacket, USB_PACKET_SIZE, &USBBytesReceived); } } 

Wenn das Scilab-Skript die Bilddatei in LCD-Pixeldaten konvertiert hat, sendet es ein Ein-Byte-Paket mit einem in ImagetoLCD_Defs.h als NEW_IMAGE_FLAG definierten Wert. Wenn somit die empfangene Paketlänge eins ist und das einzelne empfangene Byte einen Wert von NEW_IMAGE_FLAG hat, weiß der Mikrocontroller, dass ein neues Bild auf dem Weg ist. Es löscht das LCD, überträgt NEW_IMAGE_FLAG an den PC und lädt Null in NextLinetoWrite, eine Variable, die die Adresse der ersten Zeile enthält, die aktualisiert werden soll, wenn der Mikrocontroller das nächste Pixeldatenpaket empfängt. Wenn die empfangene Paketlänge 64 Byte anstelle eines Bytes beträgt, bringt das Paket tatsächliche Pixeldaten mit. In diesem Fall setzen wir einfach das Flag USB_PACKET_RECEIVED auf True; Das Flusskontrollbyte wird übertragen, nachdem das LCD-Update abgeschlossen ist.

Wenn die Endlosschleife in ImagetoLCD_main.c erkennt, dass USB_PACKET_RECEIVED auf "true" gesetzt wurde, ruft sie ProcessUSBRxPacket () auf:

 void ProcessUSBRxPacket() { unsigned char n = 0, row, column; //copy the received pixel data to the LCD display data array for(row = 0; row < LINES_PER_PACKET; row++) { for(column = 0; column < NUM_LINE_DATA_BYTES; column++) { LCDDisplayData(row)(column) = USBRxPacket(n); n++; } } //wait until the SPI state variable indicates that the bus is available for a new transfer while(LCDTxState != IDLE); UpdateLCDLines(); } 

Hier übertragen wir die Pixeldaten in das entsprechende zweidimensionale Array. In diesem Projekt ist LCDDisplayData () () 4 Zeilen mal 16 Spalten: Wir benötigen noch 16 Spalten-Bytes, um die 128 Bits horizontaler Daten zu speichern, aber wir benötigen nur 4 Zeilen, da Pixeldaten vom PC in 64-Byte-Paketen übertragen werden. und 64 Bytes geteilt durch 16 Bytes pro Zeile entsprechen 4 Zeilen. Nach dem Aktualisieren des Arrays wartet das Programm, bis die LCD-Kommunikationsschnittstelle im Leerlauf ist, und ruft dann UpdateLCDLines () auf.

Dieses Projekt erfordert einige Änderungen an der Zustandsmaschine, die SPI-Übertragungen an das LCD steuert. Zuvor hatten wir die Funktion UpdateAllLCDLines (), die (wie Sie aus dem Namen erraten können) einen Prozess einleitet, der alle LCD-Zeilen in einer SPI-Übertragung aktualisiert. Aber wir aktualisieren jetzt nur vier Zeilen während einer SPI-Übertragung, und zwei zusätzliche Aufgaben werden am Ende der Prozedur ausgeführt:

Code herunterladen

Scilab

Das Scilab-Skript beginnt mit einem Bildverarbeitungsabschnitt:

Das Eingabebild muss eine Graustufen-128-mal-128-Pixel-BMP-Datei sein. Die Funktion SegmentByThreshold () konvertiert das Bild von Graustufen in Schwarz-Weiß, da bei unserem LCD die Pixel entweder aktiviert oder deaktiviert sind - kein Grau erlaubt. Eine Reihe von bitset () - Operationen konvertiert diese Bilddaten in Pixeldaten, die an das EFM8 gesendet und direkt an das LCD übertragen werden können. Beachten Sie, dass hochentwickelte computergestützte Anwendungen wie Scilab nicht genau für die Art von umständlichen bitweisen Operationen optimiert sind, die wir hier verwenden. Mit anderen Worten, der Doppel-For-Loop-Block in dem obigen Code braucht eine lange Zeit, um ausgeführt zu werden (z. B. ungefähr 23 Sekunden mit einem 2, 5-GHz-Prozessor, der Windows 8.1 ausführt). Wenn Sie diesen Code zum Anzeigen einer Animationssequenz anpassen möchten, müssen Sie daher alle Bilder in das LCD-Pixelformat konvertieren, bevor Sie mit dem Senden von Daten an den EFM8 beginnen.

Der andere Hauptabschnitt im Scilab-Skript ist die for-Schleife, die die Pixeldaten über die VCP-Verbindung an den EFM8 sendet:

Vier Zeilen von Pixeldaten werden in ein eindimensionales Array umgewandelt und als einzelnes 64-Byte-Paket unter Verwendung der Funktion slSendArray () übertragen. Das Skript liest dann das einzelne Bestätigungsbyte von dem EFM8, bevor es die nächsten vier Zeilen von Pixeldaten sendet. Wichtiger Hinweis : Die Aufrufe von slReadByte () in diesem Skript haben für den zweiten Parameter "1", dh response = slReadByte (EFM8Port, 1 ). Diese "1" zeigt an, dass die Funktion blockiert, was bedeutet, dass Scilab nichts unternimmt, bis mindestens ein Byte ankommt. Der Vorteil hierbei ist, dass das Skript so schnell wie möglich ausgeführt wird, da die Ausführung fortgesetzt wird, sobald das EFM8 das Bestätigungsbyte sendet. Das Problem ist jedoch, dass, wenn etwas schief geht und das Byte nie kommt, Scilab im Koma liegt, bis Sie das Programm schließen und es wieder öffnen. Daher ist es besser, während der Debugging-Phase die Funktion sleep () zu verwenden, um dem EFM8 Zeit zum Antworten zu geben und dann das Byte ohne Blockierung zu lesen, z. B. slReadByte (EFM8Port, 0 ).

Das Scilab-Skript ruft auch tic () und toc () auf, um die Länge der Zeit zu messen und anzuzeigen, die benötigt wird, um ein Bild zu übertragen und anzuzeigen. Mit der gleichen oben erwähnten 2, 5-GHz-Windows-Maschine dauert der Vorgang nur etwa 50 ms, was bedeutet, dass dieses System eine Animationsbildrate von 10 Bildern pro Sekunde komfortabel aufrechterhalten kann.

Code herunterladen

Gib diesem Projekt einen Versuch für dich selbst! Holen Sie sich die Stückliste.