MCU Reverse Engineering

Mikrocontroller-Entsperrung - MikaTech

Unsere Werte und Ziele

Über MikaTech

Die Zeit verging schnell, von dem Tag, an dem wir 1998 unser erstes 8051-MCU-Reverse-Engineering-Projekt durchführten, bis zu dem Tag, an dem wir 2012 unser millionenschweres Reverse-Engineering-Labor einrichteten, vergingen 14 Jahre. Jetzt starten wir unser neues Geschäft mit der Entwicklung eingebetteter visueller Systeme und hoffen, weitere 10 Jahre dienen zu können.

Unterschrift Peter Lee Mitgründer & CEO

Architektur und Programmierung von 8051-MCUs für Reverse Engineering 3

Kapitel 5: Assemblersprache

Einleitung

Hardware-orientierte Ingenieure mussten Kompromisse eingehen, um in der eingebetteten Entwicklung wettbewerbsfähig zu bleiben. Anders als gewöhnliche elektronische Schaltungen, die nur Verdrahtung und Stromversorgung benötigen, erfordern Mikrocontroller zusätzlich eine individuelle Programmierung, um definierte Aufgaben auszuführen. Glücklicherweise haben sich Mikrocontroller-Architekturen nicht so weit entwickelt, dass sie verschiedene Hochsprachen erfordern; fast alle Mikrocontroller-Familien verstehen nativ nur Maschinensprache. Diese Standardisierung bringt große Vorteile. Der Nachteil ist, dass Maschinensprache, die nur aus binären Nullen und Einsen besteht, für menschliche Entwickler unverständlich ist und nur von spezialisierten Hardware-Design-Experten entschlüsselt werden kann. Um die Kommunikationslücke zwischen Mikrocontroller-Hardware und menschlichen Programmierern zu schließen, wurde die Assemblersprache – die erste menschenlesbare Low-Level-Programmiersprache – geschaffen.

Assembler löste das Problem, sich die rohen Binäroperationscodes für Hardwarebefehle merken zu müssen, führte jedoch eine neue Hürde ein, die den Arbeitsablauf für Entwickler und Mikrocontroller-Hardware erschwerte. Dieses neue Hindernis wurde mit zwei Schlüsselwerkzeugen überwunden: einer PC-basierten Assembler-Software und einem speziellen Hardware-Programmiergerät, dem Chip-Programmer.

Die Assembler-Software akzeptiert menschenlesbare Assembler-Mnemoniken und übersetzt sie zuverlässig in eine ausführbare Binärdatei. Die Kompilierungsphase, die Assembler-Quellcode in Maschinencode umwandelt, ist entscheidend, da die resultierende HEX-Datei ein Strom binärer Werte ist, den nur die Mikrocontroller-Hardware interpretieren kann. Roher Assembler-Quellcode kann nicht direkt auf einem Mikrocontroller ausgeführt werden, es sei denn, diese kompilierte HEX-Datei wird in den Programmspeicher des Geräts geschrieben. Hier kommt die letzte Komponente des Entwicklungsworkflows ins Spiel, der Chip-Programmer. Es handelt sich um ein kompaktes Hardware-Gerät, das über einen Standard-Kommunikationsport mit einem Desktop-PC verbunden wird und eine Fassung zum Einsetzen des Ziel-Mikrocontroller-Chips für das Firmware-Flashen bietet.

5.1 Elemente der Assemblersprache

Die Assemblersprache folgt strukturellen Regeln, die natürlichen Sprachen ähneln, mit reservierten Wörtern, strengen Formatierungsregeln und standardisierter Syntax. Die vier grundlegenden Bausteine des Assembler-Quellcodes sind unten aufgeführt:

  • Labels (Marken)
  • Befehls-Mnemoniken
  • Assembler-Direktiven
  • Kommentarzeilen
Elemente des Assemblers

Syntax der Assemblersprache

Beim Schreiben von Assembler-Quellcode müssen strenge Formatierungsregeln (gemeinsam als Syntax bezeichnet) befolgt werden, um eine fehlerfreie Kompilierung in ausführbaren HEX-Maschinencode zu gewährleisten. Die obligatorischen Syntaxregeln beschränken sich auf die folgenden Anforderungen:

  • Eine einzelne Zeile Assembler-Quellcode darf maximal 255 ASCII-Zeichen enthalten;
  • Jede kompilierbare Zeile muss mit einem Label, einem Befehls-Mnemonik oder einer Assembler-Direktive beginnen;
  • Der gesamte Text nach einem Semikolon ";" in einer Zeile wird als menschenlesbarer Kommentar behandelt und vom Assembler während der Kompilierung vollständig ignoriert;
  • Alle verschiedenen Komponenten in einer Zeile (Labels, Befehle, Operanden, Direktiven) müssen durch mindestens ein Leerzeichen getrennt sein. Die TAB-Taste wird häufig anstelle von einzelnen Leerzeichen verwendet, um Labels, Mnemoniken und Direktiven in vertikalen Spalten auszurichten und die Lesbarkeit des Codes zu verbessern.

Numerische Literale

Abgesehen vom veralteten Oktalsystem unterstützt die Assemblersprache numerische Werte in drei verschiedenen Basisformaten:

Dezimalzahlen

Wenn kein Basissuffix angegeben ist, interpretiert der Assembler alle numerischen Literale als Dezimalwerte. Die Dezimalschreibweise verwendet die Ziffern 0 bis 9. Da der Mikrocontrollerspeicher maximal zwei Bytes für die allgemeine numerische Speicherung zuweist, ist der größte darstellbare Dezimalwert im Assembler-Code 65535. Der Buchstabe "D" kann angehängt werden, um einen Wert explizit als dezimal zu kennzeichnen, z. B.: 1234D.

Hexadezimale Zahlen

Die hexadezimale Schreibweise ist das am häufigsten verwendete Format für die eingebettete Programmierung. Das hexadezimale System verwendet sechzehn eindeutige Symbole: die Ziffern 0–9 und die Buchstaben A–F. Der maximale zweibyte-hexadezimale Wert ist FFFF, was dem Dezimalwert 65535 entspricht. Um hexadezimale Literale von Dezimalwerten zu unterscheiden, wird der Buchstabe "h" (groß oder klein) an die Zahl angehängt, z. B. 54h.

Binäre Zahlen

Binäre Literale werden häufig verwendet, wenn einzelne Bit-Zustände von CPU-Registern explizit definiert werden müssen, da jede binäre Ziffer direkt einer Hardware-Bit-Position entspricht. Die Binärschreibweise verwendet nur die Ziffern 0 und 1. Das maximale zweibyte-binäre Literal ist 1111111111111111. Der Buchstabe "b" (groß oder klein) wird hinzugefügt, um binäre Werte von anderen Zahlenformaten zu unterscheiden, z. B.: 01100101B.

Operatoren

Viele bedingte Assembler-Direktiven und Befehlsoperanden akzeptieren mathematische und logische Ausdrücke anstelle von festen statischen Werten. Ein Beispiel für einen bedingten Block wird unten gezeigt:

IF (VERSION>1)
   LCALL Table_2
   USING VERSION+1
ENDIF
   ...

Der Assembler kann während der Kompilierung konstante mathematische und logische Ausdrücke auswerten und die resultierenden berechneten Werte in den endgültigen Maschinencode einbetten. Die vollständige Liste der unterstützten Operatoren ist in der folgenden Tabelle aufgeführt:

Operatorsymbol Operationsbeschreibung Beispielausdruck Ausgewertetes Ergebnis
+ Addition 10+5 15
- Subtraktion 25-17 8
* Multiplikation 7*4 28
/ Ganzzahldivision (Rest wird abgeschnitten) 7/4 1
MOD Modulo (Divisionsrest) 7 MOD 4 3
SHR Bitweises Rechtsverschieben 1000B SHR 2 0010B
SHL Bitweises Linksverschieben 1010B SHL 2 101000B
NOT Bitweises logisches NICHT (Einerkomplement) NOT 1 1111111111111110B
AND Bitweises logisches UND 1101B AND 0101B 0101B
OR Bitweises logisches ODER 1101B OR 0101B 1101B
XOR Bitweises exklusives ODER 1101B XOR 0101B 1000B
LOW Extrahiert die unteren 8 Bits eines 16-Bit-Werts LOW(0AADDH) 0DDH
HIGH Extrahiert die oberen 8 Bits eines 16-Bit-Werts HIGH(0AADDH) 0AAH
EQ, = Gleichheitsvergleich 7 EQ 4 oder 7=4 0 (Falsch)
NE,<> Ungleichheitsvergleich 7 NE 4 oder 7<>4 0FFFFH (Wahr)
GT, > Größer-als-Vergleich 7 GT 4 oder 7>4 0FFFFH (Wahr)
GE, >= Größer oder gleich 7 GE 4 oder 7>=4 0FFFFH (Wahr)
LT, < Kleiner-als-Vergleich 7 LT 4 oder 7<4 0 (Falsch)
LE,<= Kleiner oder gleich 7 LE 4 oder 7<=4 0 (Falsch)

Benutzerdefinierte Symbole

Benutzerdefinierte symbolische Namen können CPU-Registern, konstanten Werten, Speicheradressen und Unterprogramm-Einstiegspunkten im Assembler-Code zugewiesen werden, was die Lesbarkeit und Wartbarkeit des Quellcodes erheblich verbessert. Wenn beispielsweise der GPIO-Pin P0.3 mit einem physischen Taster verbunden ist, der einen vollständigen Prozessstopp (STOP-Taste) auslöst, wird die Codelogik viel intuitiver, wenn die Bitadresse P0.3 mit dem beschreibenden Symbol "pushbutton_STOP" aliasiert wird. Ähnlich wie in anderen Programmiersprachen gelten strenge Benennungsregeln für gültige benutzerdefinierte Symbole:

  • Gültige Symbolzeichen sind Groß- und Kleinbuchstaben (A-Z, a-z), Dezimalziffern (0–9) und zwei Sonderzeichen: Unterstrich "_" und Fragezeichen "?". Die Assemblersprache ist für Symbolnamen nicht case-sensitiv.

Die beiden folgenden Symbole werden vom Assembler als identisch behandelt:

Serial_Port_Buffer
SERIAL_PORT_BUFFER
  • Um Mehrdeutigkeiten mit numerischen Literalen zu vermeiden, muss jedes gültige Symbol mit einem Buchstaben, einem Unterstrich oder einem Fragezeichen beginnen; Ziffern können nicht als erstes Zeichen verwendet werden.
  • Ein Symbolname darf bis zu 255 Zeichen enthalten, aber der Assembler wertet nur die ersten 32 Zeichen aus, um eindeutige Bezeichner zu unterscheiden. Das folgende Beispiel zeigt dieses Verhalten: Die ersten beiden Symbole werden als doppelte Definitionen markiert (Kompilierungsfehler), während das dritte und vierte als unterschiedliche Bezeichner erkannt werden:
START_ADDRESS_OF_TABLE_AND_CONSTANTS_1
START_ADDRESS_OF_TABLE_AND_CONSTANTS_2
TABLE_OF_CONSTANTS_1_START_ADDRESS
TABLE_OF_CONSTANTC_2_START_ADDRESS
  • Bestimmte reservierte Schlüsselwörter können nicht als benutzerdefinierte Symbolnamen verwendet werden, da sie vordefinierte Kernbefehls-Mnemoniken, Assembler-Direktiven oder eingebaute Hardware-Registerbezeichner sind. Ein Benutzer kann beispielsweise kein Symbol namens "A" oder "DPTR" definieren, da diese Namen nativen CPU-Registern entsprechen.

Die vollständige Liste der reservierten Schlüsselwörter, die nicht als benutzerdefinierte Symbole verwendet werden dürfen, ist in der folgenden Tabelle angegeben:

A AB ACALL ADD
ADDC AJMP AND ANL
AR0 AR1 AR2 AR3
AR4 AR5 AR6 AR7
BIT BSEG C CALL
CJNE CLR CODE CPL
CSEG DA DATA DB
DBIT DEC DIV DJNZ
DPTR DS DSEG DW
END EQ EQU GE
GT HIGH IDATA INC
ISEG JB JBC JC
JMP JNB JNC JNZ
JZ LCALL LE LJMP
LOW LT MOD MOV
MOVC MOVX MUL NE
NOP NOT OR ORG
ORL PC POP PUSH
R0 R1 R2 R3
R4 R5 R6 R7
RET RETI RL RLC
RR RRC SET SETB
SHL SHR SJMP SUBB
SWAP USING XCH XCHD
XDATA XOR XRL XSEG

Labels

Ein Label ist eine spezielle Art von Symbol, das einen menschenlesbaren Alias für eine physische Speicheradresse im Programm-ROM oder Daten-RAM darstellt. Labels werden immer am Anfang einer Quellcodezeile platziert. Sprung-, Verzweigungs- und Unterprogrammaufrufbefehle wären ohne Labels äußerst umständlich zu schreiben und zu warten. Der standardmäßige Verwendungsworkflow für Labels ist einfach:

  • Weisen Sie der ersten Zeile einer Unterroutine oder dem Ziel eines Sprungs ein beschreibendes Label zu;
  • Verweisen Sie direkt auf den Labelnamen in Sprung- und Unterprogrammaufrufbefehlen, anstatt rohe 16-Bit-Speicheradressen manuell einzugeben.

Während der Kompilierung löst der Assembler jedes Label automatisch in seine entsprechende absolute Speicheradresse auf und ersetzt den numerischen Wert im kompilierten Maschinencode.

Assembler-Direktiven

Im Gegensatz zu CPU-Befehls-Mnemoniken, die in ausführbaren Maschinencode kompiliert werden, der im Programmspeicher des Mikrocontrollers gespeichert wird, sind Assembler-Direktiven native Befehle, die nur von der Assembler-Software interpretiert werden und keine Auswirkung auf das Laufzeitverhalten der Mikrocontroller-Hardware haben. Einige Direktiven sind für jedes gültige Assembler-Projekt obligatorisch, während andere nur zur Vereinfachung der Entwicklung oder zur Beschleunigung der Kompilierung dienen.
Direktiven belegen die gleiche vertikale Spalte wie die Befehls-Mnemoniken im Quellcode, und eine einzelne Quellzeile darf nur eine Assembler-Direktive enthalten.

EQU-Direktive

Die EQU-Direktive bindet einen festen konstanten numerischen Wert an einen benutzerdefinierten Symbolnamen zur Wiederverwendung in der gesamten Quelldatei. Beispiel:

MAXIMUM EQU 99

Nach dieser Definition wird jedes Vorkommen des Symbols "MAXIMUM" im Quellcode während der Kompilierung durch den Literalwert 99 ersetzt. Jedes Symbol kann mit EQU nur einmal definiert werden, daher werden EQU-Deklarationen fast immer am Anfang der Assembler-Datei für die globale Konstantenkonfiguration platziert.

SET-Direktive

Die SET-Direktive ordnet ebenfalls einen numerischen Wert einem symbolischen Alias zu. Ihr Hauptunterschied zu EQU besteht darin, dass SET eine wiederholte Neudefinition desselben Symbols mehrmals in der gesamten Quelldatei erlaubt:

SPEED SET 45
SPEED SET 46
SPEED SET 57

BIT-Direktive

Die BIT-Direktive weist einem bestimmten bitadressierbaren Speicherplatz einen benutzerdefinierten Symbolnamen zu, wobei die Zielbitadresse im Bereich 0–255 liegen muss. Beispiele:

TRANSMIT BIT PSW.7 ;Alias "TRANSMIT" für Bit 7 des PSW-Statusregisters
OUTPUT BIT 6 ;Alias "OUTPUT" für Bitadresse 06h
RELAY BIT 81 ;Alias "RELAY" für Bitadresse 81h (entspricht Port 0 Pin 1)

CODE-Direktive

Die CODE-Direktive verknüpft ein benutzerdefiniertes Symbol mit einer festen Programmspeicheradresse. Da der maximale Adressraum des standardmäßigen 8051-Programmspeichers 64 KB beträgt, sind gültige Adressen von 0 bis 65535. Beispiel:

RESET CODE 0 ;Alias "RESET" für Programmspeicherstelle 00h
TABLE CODE 1024 ;Alias "TABLE" für Programmspeicheradresse 1024 dezimal (0400h)

DATA-Direktive

Die DATA-Direktive fügt einen symbolischen Alias an eine Adresse im direkt zugänglichen internen RAM des Mikrocontrollers an, mit gültigen Adresswerten von 0–255. Sie kann lesbare Namen für jedes standardmäßige SFR oder allgemeine RAM-Register neu zuweisen:

TEMP12 DATA 32 ;RAM-Adresse 32 als "TEMP12" benennen
STATUS_R DATA 0D0h ;PSW-SFR in "STATUS_R" umbenennen

IDATA-Direktive

Die IDATA-Direktive erstellt symbolische Aliase für RAM-Stellen, die über indirekte Adressierung durch die Zeigerregister R0 oder R1 angesprochen werden:

TEMP22 IDATA 32 ;Alias für die RAM-Stelle, auf die das Register an Adresse 32 zeigt, als "TEMP22"
TEMP33 IDATA T_ADR ;Alias für die RAM-Stelle, auf die das Register T_ADR zeigt, als "TEMP33"

XDATA-Direktive

Die XDATA-Direktive weist symbolische Namen für Speicherstellen im externen Daten-RAM zu, das volle 16-Bit-Adressierung bis 65535 unterstützt. Beispiel:

TABLE_1 XDATA 2048 ;Alias für externe RAM-Adresse 2048 dezimal als "TABLE_1"

ORG-Direktive

Die ORG-Direktive legt den Start-Speicheroffset für allen nachfolgenden kompilierten Code oder Daten-Definitionen im aktiven Segment fest. Beispiel:

BEGINNING ORG 100
          ...
          ...
          ORG 1000h
TABLE     ...
          ...

Dieser Codeausschnitt platziert das Hauptprogramm ab Speicheroffset 100 dezimal, während der Tabellendatenblock an der Adresse 1000 hex verankert wird.

USING-Direktive

Die USING-Direktive wählt aus, welche der vier CPU-Registerbänke (R0–R7) für die nachfolgende Codelogik verwendet wird:

USING 0 ;Registerbank 0 wählen (R0-R7 auf RAM-Adressen 0–7 gemappt)
USING 1 ;Registerbank 1 wählen (R0-R7 auf RAM-Adressen 8–15 gemappt)
USING 2 ;Registerbank 2 wählen (R0-R7 auf RAM-Adressen 16–23 gemappt)
USING 3 ;Registerbank 3 wählen (R0-R7 auf RAM-Adressen 24–31 gemappt)

END-Direktive

Die END-Direktive markiert das absolute Ende der Assembler-Quelldatei. Der Assembler beendet sofort die gesamte Kompilierungsverarbeitung, wenn er dieses Token findet. Beispiel:

...
END ;Ende des gesamten Assembler-Quellprogramms

Segmentauswahl-Direktiven

Fünf dedizierte Direktiven steuern die Auswahl zwischen den fünf verschiedenen Speichersegmenttypen, die auf standardmäßigen 8051-Mikrocontrollern verfügbar sind:

CSEG ;Aktiviert das Programmcodesegment für ausführbare Befehle
BSEG ;Aktiviert das bitadressierbare interne RAM-Segment
DSEG ;Aktiviert das direkt adressierbare allgemeine interne RAM-Segment
ISEG ;Aktiviert das indirekt adressierbare interne RAM-Segment (über R0/R1-Zeiger)
XSEG ;Aktiviert das externe Daten-RAM-Segment

Das CSEG-Codesegment ist standardmäßig aktiviert, wenn der Assembler initialisiert wird, und bleibt aktiv, bis eine alternative Segment-Direktive deklariert wird. Jedes Speichersegment führt seinen eigenen unabhängigen Adresszähler, der jedes Mal auf Null zurückgesetzt wird, wenn der Assembler die Kompilierung neu startet. Der Startoffset des Adresszählers eines Segments kann manuell durch Anhängen eines AT-Spezifizierers gefolgt von einem numerischen Wert, einem arithmetischen Ausdruck oder einem vordefinierten Symbol gesetzt werden. Beispiel:

DSEG       ;Wechsel zum direkt adressierten internen RAM-Segment
BSEG AT 32 ;Bitadressierbares RAM mit Segmentzähler-Offset ab Bit 32 wählen

Das Dollar-Symbol "$" repräsentiert den aktuellen Wert des Adresszählers für das aktive Segment. Zwei praktische Anwendungsbeispiele sind unten angegeben:

Beispiel 1:

JNB FLAG,$ ;Endlosschleife, die diesen Sprungbefehl wiederholt, bis das FLAG-Bit gelöscht ist

Beispiel 2:

MESSAGE DB 'ALARM turn off engine'
LENGTH EQU $-MESSAGE-1

Diese beiden Zeilen berechnen die genaue Anzahl der Zeichen der ASCII-Zeichenkette "ALARM turn off engine", die an der mit MESSAGE bezeichneten Adresse gespeichert ist.

DS-Direktive

Die DS-Direktive reserviert einen zusammenhängenden Block von Byte-Speicherplatz im aktuell aktiven DSEG-, ISEG- oder XSEG-Datensegment. Zwei Anwendungsbeispiele werden unten gezeigt:

Beispiel 1:

DSEG     ;Direktzugriffs-RAM-Segment wählen
DS 32         ;Segmentadresszähler um 32 Bytes erhöhen
SP_BUFF DS 16 ;16-Byte zusammenhängenden Block für seriellen Empfangspuffer reservieren
IO_BUFF DS 8  ;8-Byte Block für allgemeinen E/A-Datenpuffer reservieren

Beispiel 2:

ORG 100       ;Startadressoffset auf 100 dezimal setzen
DS 8          ;8 leere aufeinanderfolgende Bytes reservieren
LAB ......... ;Programmlogik beginnt bei Speicheradresse 108

DBIT-Direktive

Die DBIT-Direktive weist einen Block zusammenhängender Bit-Speicher im aktiven BSEG-bitadressierbaren RAM-Segment zu, wobei die Zuordnungsgröße als Bitanzahl angegeben wird:

BSEG ;Bitadressierbares RAM-Segment aktivieren
IO_MAP DBIT 32 ;Die ersten 32 Bitpositionen für E/A-Statusflags reservieren

DB-Direktive

Die DB-Direktive speichert statische Bytewerte oder ASCII-Zeichenketten direkt im aktiven CSEG-Programmspeichersegment. Mehrere numerische Literale werden durch Kommas getrennt, und ASCII-Textzeichenketten müssen in einfache Anführungszeichen eingeschlossen werden. Diese Direktive darf nur verwendet werden, wenn das CSEG-Codesegment aktiv ist:

CSEG
DB 22,33,'Alarm',44

Wenn ein Label einer DB-Anweisung vorausgeht, zeigt die Adresse des Labels auf das erste definierte Datenelement (in diesem Beispiel den Wert 22).

DW-Direktive

Die DW-Direktive funktioniert ähnlich wie DB, speichert jedoch vollständige 16-Bit-Zweibyte-Wörter im Programmspeicher. Das höherwertige Byte jedes Wortwerts wird zuerst in den Speicher geschrieben, gefolgt vom niederwertigen Byte.

Bedingte Direktiven IF, ELSE, ENDIF

Diese drei Direktiven erstellen bedingte Kompilierungsblöcke im Assembler-Quellcode. Jeder bedingte Block beginnt mit einer IF-Anweisung und endet mit ENDIF, mit optionaler ELSE-Logik, die sich gegenseitig ausschließende Codepfade trennt. Der mathematische/logische Ausdruck in Klammern nach IF bestimmt, welche Quellcodeabschnitte in die endgültige Binärdatei kompiliert werden:

  • Wenn der bedingte Ausdruck wahr ist (Wert ungleich Null), werden alle Quellzeilen zwischen IF und der nächsten ELSE- oder ENDIF-Direktive in Maschinencode kompiliert;
  • Wenn der bedingte Ausdruck falsch ist (Wert Null), werden alle Zeilen zwischen IF und ELSE während der Kompilierung übersprungen, und die Assemblierung setzt die Verarbeitung der Zeilen nach ELSE oder ENDIF fort.

Beispiel 1:

IF (VERSION>3)
   LCALL Table_2
   LCALL Addition
ENDIF
   ...

Wenn der konstante VERSION-Wert größer als 3 ist (Bedingung wahr), werden die beiden Unterprogrammaufrufe an Table_2 und Addition in das endgültige Firmware-Image kompiliert. Wenn VERSION kleiner oder gleich 3 ist (Bedingung falsch), werden diese beiden Befehle während der Kompilierung vollständig verworfen.

Beispiel 2:

Wenn das Symbol Model gleich 1 ist, werden die beiden unmittelbar auf IF folgenden Befehle kompiliert, und der gesamte Code zwischen ELSE und ENDIF wird ignoriert. Wenn Model gleich 0 ist, werden die IF-Block-Befehle übersprungen, und nur der Code unter ELSE wird in Maschinencode assembliert.

IF (Model)
   MOV R0,#BUFFER
   MOV A,@R0
ELSE
   MOV R0,#EXT_BUFFER
   MOVX A,@R0
ENDIF
   ...

Assembler-Steuerdirektiven

Steuerdirektiven beginnen mit einem Dollarzeichen "$". Sie konfigurieren das Assembler-Verhalten während der Kompilierung, einschließlich der Einbindung externer Quelldateien, der Ausgabe-Pfade für HEX-Dateien und der Formatierungsregeln für die menschenlesbare Kompilierungsliste. Es gibt viele Steuerdirektiven, aber nur die am häufigsten verwendeten werden unten behandelt:

$INCLUDE-Direktive

Diese Direktive weist den Assembler an, während des Kompilierungsprozesses eine externe Assembler-Quelldatei zu laden und zu analysieren:

$INCLUDE(TABLE.ASM)

$MOD8253-Direktive

Die $MOD8253-Direktive referenziert eine vordefinierte Header-Datei, die alle Namen der Special Function Registers (SFR) und ihre entsprechenden Speicheradressen für die 8253-Mikrocontroller-Variante enthält. Mit dieser aktivierten Direktive können Entwickler Register mit ihren menschenlesbaren Namen anstelle von rohen numerischen Adressen referenzieren. Wenn diese Direktive weggelassen wird, muss jedes im Projekt verwendete SFR manuell mit seiner genauen Speicheradresse am Anfang der Quelldatei deklariert werden.

 

Kapitel 6 : Beispiele

Übersicht

Dieses Kapitel vermittelt grundlegendes Wissen über die Mikrocontroller-Hardware, das für die praktische Anwendung erforderlich ist. Die Leser werden in diesem Abschnitt keine übermäßig komplexe Programmlogik oder fortgeschrittene Schaltpläne mit hochmodernen optimierten Designs finden. Stattdessen zeigen die folgenden praktischen Beispiele, dass die eingebettete Programmierung weder eine exklusive Fähigkeit noch ein talentabhängiges Handwerk ist – es ist einfach der Prozess, modulare Funktionslogik über eine standardisierte Befehlssyntax zusammenzusetzen. Seien Sie versichert, dass Hardware-Design und iterative Entwicklung einem konsistenten Kernablauf folgen: „testen, anpassen, wiederholen“. Natürlich steigt die Projektkomplexität mit der Erfahrung; dieselbe puzzleartige Komponentenlogik gilt sowohl für Hobby-Prototypen als auch für industrielle professionelle Architekturentwicklung...

Während sich diese Einführungsdemos ausschließlich auf grundlegende Funktionsabläufe konzentrieren, birgt jede eingebettete Hardwareplattform eine oft unterschätzte zugrunde liegende Sicherheitsrisikoschicht, die in Anfänger-Tutorials selten behandelt wird. Der zentrale Mikrocontroller (MCU), der diese einfachen Steuerroutinen ausführt, kann später in kommerzielle Endprodukte integriert werden, wo der Schutz des ausführbaren Quellcodes vor unbefugtem Zugriff zu einer wichtigen Designpriorität wird. Viele unerfahrene Ingenieure glauben fälschlicherweise, dass der eingebaute Lockbit-Sicherungsmechanismus den externen Lesezugriff auf den internen Flash-Speicher vollständig blockieren kann, doch diese Annahme ist nicht universell zuverlässig. In realen Bedrohungsszenarien können böswillige Akteure Chip-Dekapsulationsabläufe einsetzen, um die bloßen Silizium-Die-Schichten freizulegen und eine direkte Mikrosondierung der sicherheitssteuernden Hardwaresicherungen durchzuführen. Sobald das Gehäuse entfernt ist, können Gegner einen vollständigen Speicherauszug aller Programmspeicherbereiche extrahieren und so eine vollständige Firmware-Extraktion ohne gültige Authentifizierungsnachweise durchführen. Das eingebaute EEPROM-Chipsatz, das üblicherweise Werkskalibrierungsparameter und kryptografische Sicherheitsschlüssel speichert, ist ähnlichen Schwachstellen gegenüber solchen physischen Hardware-Eindringangriffen ausgesetzt. Bestimmte Bedrohungsakteure nutzen Laborgeräte mit fokussiertem Ionenstrahl (FIB), um einzelne Sicherungsschaltkreise selektiv zu modifizieren und eine dauerhafte Entsperrung von als geschützt markierten Speicherzonen zu erzwingen. Andere Angreifer nutzen Seitenkanal-Analysemethoden, um vollständige Programmbinarys schrittweise auszulesen, ohne eine Hardware-Manipulationserkennung auszulösen. Im schlimmsten Exploit-Szenario ermöglicht ein vollständiger Auszug sowohl der Flash- als auch der EEPROM-Speicherpartitionen es Angreifern, identische Hardware-Repliken herzustellen, die voll funktionsfähige Geräteklone produzieren und den Wert des proprietären geistigen Eigentums vollständig untergraben. Aus diesem Grund müssen Entwickler bereits beim Erlernen der grundlegenden digitalen Ein-/Ausgangslogik und Timing-Steuerungsroutinen erkennen, dass dieselben Chip-Pins und Kernregister bei bösartigen Reverse-Engineering-Kampagnen ausgenutzt werden können. Die Wiederherstellung eines nicht funktionierenden eingebetteten Geräts erfordert gelegentlich die Umgehung von Sicherheitssperren durch Spannungsglitch-Injektion – eine legitime Hardware-Reparaturtechnik, die gleichzeitig einen Angriffspunkt schafft. Die Beherrschung der zugrunde liegenden Lockbit-Betriebslogik ist eine obligatorische Kompetenz sowohl für eingebettete Firmware-Entwickler als auch für dedizierte Hardwaresicherheitsanalysten. Eine große Anzahl kommerzieller eingebetteter Geräte hat aufgrund unsachgemäß konfigurierter Sicherungssicherungen vollständige Verletzungen des geistigen Eigentums erlitten, wodurch der ausführbare Code vollständig für den externen Abruf freigegeben wurde. Ein einfaches Auslesen der Chip-Konfigurationsspeicherbytes kann alle Sicherheitsrichtlinieneinstellungen offenlegen und Bedrohungsakteure direkt zum schwächsten Exploit-Vektor führen. Selbst die spätere einfache Watchdog-Timer-Demonstration kann zur Implementierung einer Hardware-Manipulationserkennungslogik umfunktioniert werden. In der realen Ingenieurspraxis müssen Entwickler ein Gleichgewicht zwischen Hardware-Funktionalität und Einbruchschutzmaßnahmen finden, um sicherzustellen, dass eine unbefugte Firmware-Extraktion technisch und finanziell undurchführbar bleibt. Die nachfolgenden praktischen Demos veranschaulichen elementare Hardware-Arbeitsabläufe, zeigen jedoch implizit, wie Kern-MCU-Peripheriegeräte wie Timer, Interrupt-Controller und serielle Kommunikationsschnittstellen zur Implementierung robuster Sicherheitshärtungs-Gegenmaßnahmen umfunktioniert werden können. Beispielsweise kann die Verwendung von Timermodulen zur Erzeugung zufälliger Timing-Offsets zeitbasierte Seitenkanalangriffe abmildern, die auf das Speicherauszug vertraulicher Geheimdaten abzielen. Darüber hinaus kann die UART-seriellen Übertragungslogik mit leichten Verschlüsselungsprotokollen umhüllt werden, um das Abhören von Rohdaten während unbefugter Leseversuche zu blockieren. LED-Multiplexing-Anzeigeschaltungen, obwohl scheinbar trivial, schaffen ein kritisches Bewusstsein für Timing-Empfindlichkeit – eine grundlegende Fähigkeit, die für die Implementierung sicherer authentifizierter Bootsequenzen erforderlich ist. Das EEPROM-Datenspeicherbeispiel behandelt direkt Workflows zur persistenten Datenwiederherstellung, ein technisches Konzept, das sich auf die sichere langfristige Aufbewahrung kryptografischer Schlüssel erstreckt. Letztendlich sollte jede Zeile eingebetteten Firmware-Codes unter der Annahme geschrieben werden, dass feindliche Akteure irgendwann vollen physischen Zugriff auf die Zielhardware erlangen könnten. Der Sicherheitssperrmechanismus dient lediglich als primäre Verteidigungsbarriere; ein umfassender Hardware-Schutz beruht auf mehrschichtigen Sicherheitsvorkehrungen, die eine Chip-Dekapsulation und Silizium-Sondierung für Angreifer wirtschaftlich undurchführbar machen. Dieses Kapitel schafft ein grundlegendes Sicherheitsbewusstsein, ohne tief in spezialisierte Reverse-Engineering-Exploit-Taktiken einzusteigen. Mit diesem doppelten Fokus auf funktionale Betriebsabläufe und eingebettete Sicherheit wenden wir uns nun der Betrachtung grundlegender Mikrocontroller-Verdrahtungsschemata und unterstützender Peripherie-Hardwarekomponenten zu.

6.1 Grundlegende Hardware-Verdrahtung

Grundlegendes Verdrahtungsschema - Stromversorgungsschaltung

Wie im obigen Schema dargestellt, müssen drei obligatorische Signaldomänen korrekt verdrahtet werden, um einen stabilen Mikrocontroller-Betrieb zu gewährleisten:

  • Geregelte Stromversorgungsschiene;
  • Hardware-Reset-Signal-Eingang; und
  • Externes Referenz-Taktoszillatorsignal.

Dies sind extrem minimale Schaltungstopologien, aber die Hardware-Komplexität steigt drastisch für Geräte, die zur Steuerung teurer Industriemaschinen oder zur Aufrechterhaltung sicherheitskritischer Arbeitsabläufe eingesetzt werden. Dennoch reicht dieses vereinfachte Schaltungslayout für einführende Lernzwecke aus...

Geregelte Stromversorgungsschaltung

Obwohl diese Mikrocontroller-Variante mehrere Eingangsspannungspegel unterstützt, gibt es keinen praktischen Grund, unnötige Fehlerrisiken durch das Testen marginaler Spannungsbedingungen einzuführen. Eine 5V DC-Versorgung bleibt der am weitesten verbreitete Industriestandard. Das gezeigte Schaltbild implementiert den kostengünstigen Dreipol-Positiv-Spannungsregler LM7805, der eine konstante stabile Ausgangsspannung und ausreichende 1A-Spitzenstromkapazität liefert, um den Mikrocontroller-Kern sowie alle angeschlossenen Hilfsperipheriegeräte zu versorgen.

Hardware-Reset-Signal-Schaltung

Für eine zuverlässige Mikrocontroller-Initialisierung muss ein logisch niedriges (0V) Signal am RS-Reset-Pin anliegen. Der den RS-Reset-Pin mit der VCC-Versorgungsschiene verbindende Taster ist nicht zwingend erforderlich, wird jedoch auf fast allen Prototypenplatinen verbaut. Dieser Taster ermöglicht eine kontrollierte erzwungene Reinitialisierung, falls die Firmware-Ausführung in einen instabilen Fehlerzustand gerät. Das Anlegen von 5V an diesen Pin löst einen vollständigen Chip-Reset aus und startet die Programmausführung von der Firmware-Eintrittsvektoradresse neu.

Taktoszillatorschaltung

Obwohl der Mikrocontroller einen internen RC-Oszillator integriert, erfordert ein stabiler deterministischer Betrieb einen externen Quarzkristall mit zwei passenden Lastkondensatoren, um die Kernbetriebsfrequenz festzulegen, die direkt den Befehlsausführungsdurchsatz des Chips definiert.

Taktoszillatorschaltungsschema

Diese Kristalloszillator-Topologie ist natürlich nicht universell anwendbar, und es existieren mehrere alternative Taktgenerierungslösungen. Eine alternative Konfiguration bezieht ein Taktreferenzsignal von einem dedizierten externen Oszillatormodul, das über einen invertierenden Logikpuffer geleitet wird, wie im linken Diagramm dargestellt.

6.2 Hilfsperipheriekomponenten

Trotz der Tatsache, dass es sich um hochmoderne kompakte Rechenhardware handelt, erfüllt ein eigenständiger Mikrocontroller ohne angeschlossene Hilfsperipherie keinen praktischen Zweck. Vereinfacht gesagt, haben Spannungspegeländerungen an den Ein-/Ausgangspins des Chips keine funktionale Bedeutung, es sei denn, sie werden zur Steuerung definierter Operationen genutzt: Ein-/Ausschalten von Lasten, Datenverschiebung, visuelle Statusanzeige und mehr.

Schalter und Taster

Keine Peripheriekomponente ist einfacher als mechanische Schalter und Taster; sie bieten die einfachste Methode zur Erkennung von Spannungszustandsübergängen an Mikrocontroller-Eingangspins.

Mechanische Schalter und Taster

Die praktische Umsetzung bringt unvorhergesehene Komplexität mit sich, die auf das Prellen der mechanischen Kontakte zurückzuführen ist, ein weit verbreiteter Fehler aller mechanischen Schalthardware. Wenn metallische Kontaktflächen aufeinandertreffen, erzeugen der physikalische Impuls und die Materialelastizität schnelle, wiederholte elektrische Impulse anstelle eines sauberen einzelnen Spannungsübergangs zwischen 0V und der vollen Versorgungsschiene. Dieses oszillierende Verhalten resultiert aus geringfügigen Oberflächenunebenheiten, angesammelter Staubverschmutzung und mechanischen Vibrationen. Die Prellzeit – gemessen in Mikrosekunden oder Millisekunden – bleibt für die menschliche Wahrnehmung unbemerkt, wird jedoch von der Hochgeschwindigkeits-Digital-Logik des Mikrocontrollers zuverlässig als mehrere diskrete Eingangsereignisse registriert. Wenn ein rohes Tastersignal direkt in eine impulszählende Firmware-Routine eingespeist wird, treten ohne Signalaufbereitung nahezu 100 % Zählfehler auf.

RC-Entprellfilter

Die kostengünstigste Strategie zur Minderung des Kontaktprellens ist eine passive RC-Tiefpassfilterschaltung, die schnelle Spannungstransienten unterdrückt. Da die Prellzeitcharakteristiken je nach Schaltermodell variieren, gibt es keine streng standardisierten Widerstands- und Kondensatorwerte, aber die im Diagramm dargestellten Komponentenwerte liefern für die meisten Anwendungsfälle konsistente Leistung.

Anwendungen, die absolute Eingangssignalstabilität erfordern, benötigen robustere Hardware-Gegenmaßnahmen. Eine RS-Flipflop-Schaltung ändert den logischen Ausgangszustand nur einmal beim ersten Kontaktübergang und ignoriert nachfolgende Prellimpulse vollständig. Obwohl diese Hardware-Lösung einen teureren SPDT-Schalter erfordert, eliminiert sie Prellartefakte vollständig und ermöglicht die Erkennung extrem kurzer Eingangsimpulse, die passive RC-Filter maskieren würden, da im Signalpfad keine Ladungsspeicherkondensatoren verwendet werden.

RS-Flipflop-Hardware-Entprellschaltung

Neben Hardware-Filtertopologien existiert auch eine einfache Software-Entprellimplementierung. Wenn die Firmware einen Zustandswechsel an einem Eingangspin erkennt, überprüft sie den logischen Pegel des Pins nach einer festen Verzögerungszeit erneut. Ein konsistenter Zustandslesebestätigt eine absichtliche Schalterbetätigung und nicht ein vorübergehendes Prellrauschen. Dieser Softwareansatz verursacht keine zusätzlichen Komponentenkosten, unterdrückt elektromagnetische Störeffekte und arbeitet zuverlässig mit verschlissenen mechanischen Kontakten geringer Qualität. Die Hauptbeschränkung entspricht der von RC-Filtern: Eingangsimpulse, die kürzer als die programmierte Verzögerungszeit sind, können von der Firmware-Logik nicht erfasst werden.

Optokoppler-Isolationsmodule

Optokoppler-Isolationsschaltungen

Optokoppler sind Industriestandard-Isolationsbauteile, die zur galvanischen Trennung von Mikrocontroller-Schaltkreisen von gefährlichen hochstrom- oder hochspannungsexternen elektrischen Umgebungen verwendet werden. Typische Optokoppler-Gehäuse integrieren eine, zwei oder vier LED-Lichtquellen auf der Eingangsseite, gepaart mit einer gleichen Anzahl lichtempfindlicher Halbleiterbauelemente auf der Ausgangsstufe: Fototransistoren, Fotothyristoren oder Fototriacs. Die Kernfunktionalität beruht auf einem nichtleitenden optischen Übertragungskanal, der digitale Signale zwischen isolierten Schaltungsdomänen überträgt und dabei eine vollständige elektrische Trennung aufrechterhält. Diese Isolationsleistung ist nur wirksam, wenn die LED-Eingangsseite und die Fotodetektor-Ausgangsseite mit unabhängigen Versorgungsspannungen versorgt werden. Diese Trennung schützt den Mikrocontroller und die empfindliche Präzisionsperipherie vollständig vor zerstörerischen Hochspannungstransienten und elektromagnetischen Störungen, zwei Hauptursachen für dauerhafte Hardwareschäden und instabiles Betriebsverhalten in eingebetteten Systemen. Optokoppler mit Fototransistorausgang sind die am weitesten verbreitete Variante. Bei Optokopplern mit freiliegendem Basisanschluss (Pin 6) kann die Basis offen gelassen werden. Ein optionales Widerstand-Kondensator-Netzwerk, dargestellt durch gepunktete Verdrahtung im Schema, dämpft hochfrequente Störungen, indem es extrem kurze transiente Impulssignale filtert.

Elektromechanische Relais

Relais-Ansteuerschaltungsschema

Ein Relais ist ein elektrisch betätigter mechanischer Schalter, der von einer sekundären Low-Power-Logikschaltung gesteuert wird. Relais werden mit den Ausgangspins des Mikrocontrollers verbunden, um Hochleistungslasten wie Gleichstrommotoren, Transformatoren, Heizelemente, Glühlampen und Antennenarrays zu schalten. Diese Hochleistungslasten werden fast immer physisch von den empfindlichen Niederspannungs-Logikkomponenten der Hauptplatine getrennt. Es gibt verschiedene Relais-Bauformen, aber alle arbeiten nach denselben elektromagnetischen Betätigungsprinzipien: Das Bestromen einer internen Kupferspule erzeugt ein Magnetfeld, das einen oder mehrere Sätze leitender Kontaktpaare mechanisch umschaltet. Wie Optokoppler bieten Relais eine vollständige galvanische Trennung ohne direkten elektrischen Leitungspfad zwischen Eingangssteuerlogik und Ausgangslastkreisen. Die meisten Standardrelais benötigen eine erhöhte Spannung und Stromstärke, um die Spule zu erregen, obwohl Miniatur-Signalrelais direkt von der geringen Stromquellenkapazität der Mikrocontroller-Ausgangspins angesteuert werden können.

Das dargestellte Schema zielt auf die 8051-Mikrocontroller-Architektur ab. Ein Darlington-Transistorpaar verstärkt den Ansteuerstrom, um die Relaisspule zu erregen – eine obligatorische Lösung für logisch-hohe Ausgangszustände, bei denen der Mikrocontroller-Pin als hochohmiger Eingang mit minimaler Stromquellenkapazität arbeitet, was gegen die Standard-Designrichtlinien für Treiberschaltungen verstößt, aber für die spezifischen elektrischen Eigenschaften dieser Architektur erforderlich ist.

Grundlegendes Verdrahtungsdiagramm für den Relaisantrieb mit Mikrocontroller

Eine antiparallele Freilaufdiode wird parallel zur Relaisspule geschaltet, um zerstörerische hochspannungsinduktive Spannungsspitzen zu unterdrücken, die beim abrupten Abschalten des Spulenstroms entstehen. Diese Klemmdiode absorbiert die induktive Spannungsspitze und schützt die umgebenden Halbleiterbauteile vor Durchbruchschäden.

Leuchtdioden (LEDs)

Leuchtdioden dienen als visuelle Statusanzeigekomponenten in elektronischen Systemen und werden in verschiedenen physikalischen Formfaktoren, Emissionsfarben und Gehäusegrößen hergestellt. Ihre extrem niedrigen Stückkosten, der geringe Stromverbrauch und die vereinfachte Ansteuerung haben herkömmliche Glühlampen in fast allen modernen Anwendungen verdrängt. Das elektrische Verhalten entspricht dem von Standard-PN-Übergangsdioden, mit der besonderen Eigenschaft der sichtbaren Lichtemission, wenn ein Durchlassstrom durch den Halbleiterübergang fließt.

Schaltschema der Leuchtdiode (LED)

Die Strombegrenzung ist eine kritische Designanforderung; ein unregulierter Durchlassstrom wird den LED-Übergang dauerhaft zerstören. Ein serieller Strombegrenzungswiderstand muss in jede LED-Treiberschaltung eingefügt werden. Die Berechnung des erforderlichen Widerstandswerts hängt von der Durchlassspannung der LED ab, einem Parameter, der durch das Halbleitermaterial und die gewünschte Emissionswellenlänge/Farbe bestimmt wird. Die standardmäßigen elektrischen Spezifikationen für häufig verwendete LED-Varianten sind in der folgenden Tabelle aufgeführt. Es gibt drei Hauptklassifikationen von LEDs: Standard-LEDs erreichen ihre volle Nennhelligkeit bei einem Durchlassstrom von 20 mA; Low-Current-LEDs liefern bei einem Zehntel dieses Stroms die gleiche Leuchtstärke; Super-Bright-LEDs erzeugen unter gleichen Ansteuerbedingungen eine deutlich höhere Lichtausbeute als Standard-LEDs.

Emissionsfarbe Typ Nennstrom Id (mA) Maximalstrom If (mA) Durchlassspannung Ud (V)
Infrarot - 30 50 1.4
Rot Standard 20 30 1.7
Rot Super Hell 20 30 1.85
Rot Niedrigstrom 2 30 1.7
Orange - 10 30 2.0
Grün Niedrigstrom 2 20 2.1
Gelb - 20 30 2.1
Blau - 20 30 4.5
Weiß - 25 35 4.4
Niedrigstrom-LED-Ansteuerung

Die 8051-Mikrocontroller-Familie liefert nur begrenzten Senken-/Quellenstrom auf den Allzweck-E/A-Pins, wobei die Pins bei Ansteuerung auf 0V logisch als Senkenstrom betrieben werden. Aus diesem Grund werden Niedrigstrom-LEDs mit ihren Kathoden direkt an die Mikrocontroller-Ausgangspins angeschlossen, wie im rechten Schaltbild dargestellt.

Segment-LED-Anzeigemodule

Ein Segment-LED-Anzeigemodul integriert mehrere diskrete LED-Dioden in einem einzigen Kunststoffgehäuse. Es gibt zahlreiche Anzeigevarianten, die Dutzende einzelner LED-Segmente zur Darstellung alphanumerischer Symbole und Ziffern enthalten.

Physisches Layout einer 7-Segment-LED-Anzeige

Die 7-Segment-Anzeige ist die am weitesten verbreitete Variante, die aus acht unabhängigen LED-Elementen besteht: sieben rechteckigen Leuchtelementen zur Darstellung von Ziffern und einem achten Segment für den Dezimalpunkt. Zur Vereinfachung der Leiterplattenverdrahtung sind alle Anoden oder Kathoden der Segmente mit einer gemeinsamen Klemme verbunden, wodurch zwei Haupttopologien entstehen: gemeinkathoden- und gemeinanoden-Varianten. Die Segmente werden mit den Buchstaben A bis G sowie dp für den Dezimalpunkt bezeichnet, entsprechend der Beschriftung im linken Diagramm. Jedes LED-Segment benötigt seinen eigenen Serienwiderstand zur Strombegrenzung bei der Hardware-Verdrahtung, da jedes Segment als unabhängiges Leuchtelement arbeitet.

Die direkte Verdrahtung mehrstelliger LED-Anzeigen mit dem Mikrocontroller verbraucht große Mengen der begrenzten E/A-Pin-Ressourcen, eine kritische Hardware-Einschränkung, insbesondere wenn mehrstellige numerische Anzeigen erforderlich sind. Die Ressourcenbeschränkung wird sofort deutlich, wenn man eine zweistellige sechsstellige numerische Anzeige realisieren will, die theoretisch 96 dedizierte Ausgangspins erfordern würde, wenn sie ohne Multiplexing verdrahtet wird. Die Standard-Industrielösung für diese Hardware-Einschränkung ist das Anzeige-Multiplexing, das auf einer optischen Persistenz-vision-Illusion basiert, die den Prinzipien der Filmprojektion entspricht. Es wird nur ein einzelnes Ziffernsegment-Bank zu einem bestimmten Taktzyklus mit Strom versorgt, doch das schnelle sequenzielle Umschalten zwischen den Ziffernpositionen erzeugt die visuelle Wahrnehmung, dass alle Ziffern gleichzeitig leuchten.

Verdrahtungsdiagramm einer gemultiplexten 7-Segment-Anzeige

Die Funktionslogik des obigen Schemas ist wie folgt: Zunächst wird ein Byte-Datenwert entsprechend der Einerstelle an einem Mikrocontroller-Port angelegt, während gleichzeitig der Transistor T1 aktiviert wird, um die Einer-Anzeigebank zu aktivieren. Nach einer kurzen festen Verzögerung wird T1 deaktiviert, der Zehner-Bytewert wird an das Portregister gesendet, und T2 aktiviert die Zehner-Anzeigebank. Diese sequenzielle Aktivierungssequenz wird kontinuierlich mit hoher Bildwiederholrate über alle Ziffernpositionen und ihre entsprechenden Treibertransistoren zyklisch wiederholt.

Die grundlegende Natur des Mikrocontrollers als binäres Rechengerät, das ausschließlich die Logikpegel 0 und 1 interpretiert, wird bei der Zifferndarstellung vollständig deutlich. Der MCU hat kein inhärentes Verständnis für Dezimalstellenwerte (Einer, Zehner, Hunderter) oder übliche menschenlesbare Ziffernformen. Alle anzuzeigenden Werte müssen wie folgt standardisiert vorverarbeitet werden:

Zunächst wird ein mehrstelliger ganzzahliger Wert mithilfe dedizierter Firmware-Routinen in isolierte Einer-, Zehner- und Hunderterstellen zerlegt. Jeder extrahierte einzelne Ziffernwert wird in separaten 8-Bit-Registerbytes gespeichert. Die Zifferndarstellung erfolgt durch eine Bitmasken-Übersetzungslogik, die rohe binäre Zahlenwerte über eine einfache Unterroutine in eindeutige Segment-Aktivierungsbitmuster umwandelt. Als veranschaulichendes Beispiel wird der rohe Binärwert 0000 1000 (entsprechend der Dezimalziffer 8) in ein Segmentmasken-Bitmuster übersetzt, das alle sieben Hauptanzeigesegmente aktiviert, während das Dezimalpunktsegment aus bleibt. Wenn die Mikrocontroller-Portverdrahtung Bit 0 auf Segment A, Bit 1 auf Segment B, Bit 2 auf Segment C usw. abbildet, ergibt sich die standardisierte Bitmasken-Nachschlagetabelle für jede Dezimalziffer wie unten gezeigt.

Referenztabelle für 7-Segment-Anzeige-Bitmasken
Anzuzeigende Ziffer Segment-Bit-Zuordnung
dp a b c d e f g
0 1 0 0 0 0 0 0 1
1 1 0 0 1 1 1 1 1
2 1 0 0 1 0 0 1 0
3 1 0 0 0 0 1 1 0
4 1 1 0 0 1 1 0 0
5 1 0 1 0 0 1 0 0
6 1 0 1 0 0 0 0 0
7 1 0 0 0 1 1 1 1
8 1 0 0 0 0 0 0 0
9 1 0 0 0 0 1 0 0

Über die Dezimalziffern 0 bis 9 hinaus können einige Buchstaben des lateinischen Alphabets durch angepasste Bitmasken dargestellt werden: Großbuchstaben A, C, E, J, F, U, H, L; Kleinbuchstaben b, c, d, o, r, t.
Bei gemeinkathoden-Anzeigen müssen alle logischen 1- und 0-Werte in der Nachschlagetabelle invertiert werden, und es sind NPN-Bipolartransistoren als Zifferntreiber erforderlich.

Flüssigkristallanzeigen (LCD)

Spezielle LCD-Module sind für die direkte Anbindung an Mikrocontroller ausgelegt und können nicht von generischen Standard-Logikschaltungen angesteuert werden. Diese Module zeigen anpassbare Textzeichenfolgen auf einer kompakten Flüssigkristalltafel an.

HD44780-Zeichen-LCD-Modul-Hardware

Die in diesem Material analysierte Modulvariante ist aufgrund ihrer niedrigen Stückkosten und ihres umfassenden Funktionsumfangs weit verbreitet und basiert auf dem integrierten Controller-Chip HD44780 von Hitachi. Dieses Standardpanel unterstützt zwei unabhängige Anzeigezeilen mit sechzehn Zeichenpositionen pro Zeile und stellt vollständige lateinische Zeichensätze, griechische Buchstaben, Satzzeichen, mathematische Operatoren und zusätzliche Glyphen dar. Benutzerdefinierte 5×8-Pixel-Grafiksymbole können ebenfalls gespeichert und angezeigt werden. Weitere native Funktionen umfassen automatisches Links-/Rechtstext-Scrolling, konfigurierbare sichtbare Cursorindikatoren und integrierte LED-Hintergrundbeleuchtung.

LCD-Externe Pinbelegung

Eine Reihe von Stiftleisten verläuft entlang einer Kante der LCD-Leiterplatte, um die Verdrahtung mit dem Mikrocontroller zu erleichtern. Das Basismodul umfasst vierzehn nummerierte Signalpins; Varianten mit integrierter Hintergrundbeleuchtung fügen zwei zusätzliche Stromversorgungspins hinzu, insgesamt sechzehn. Die vollständigen Pin-Funktionsspezifikationen sind in der folgenden Tabelle aufgeführt:

Signalzweck Pin-Nr. Bezeichnung Logikpegel Funktionsbeschreibung
Masse 1 Vss - 0V Systemmasse
Hauptstromversorgung 2 Vdd - +5V Logikversorgung
Kontrasteinstellung 3 Vee - Spannungsbereich 0V bis Vdd für LCD-Kontrastabgleich
Steuersignale 4 RS 0
1
D0–D7 als Controller-Befehle interpretiert
D0–D7 als Anzeigedatenbytes interpretiert
5 R/W 0
1
Schreibvorgang: MCU sendet Daten an LCD-Modul
Lesevorgang: LCD-Modul sendet Status/Daten an MCU
6 E 0
1
Fallende Flanke 1→0
LCD-Registerzugriff deaktiviert
Bereitschaftszustand
Übernahme von Befehlen/Daten in den LCD-Controller
Daten-/Befehlsbus 7 D0 0/1 Bit 0 (LSB)
8 D1 0/1 Bit 1
9 D2 0/1 Bit 2
10 D3 0/1 Bit 3
11 D4 0/1 Bit 4
12 D5 0/1 Bit 5
13 D6 0/1 Bit 6
14 D7 0/1 Bit 7 (MSB)

LCD-Panel-Pixel-Layout

LCD-Zeichen-Punktmatrix-Pixel-Layout

Das LCD-Anzeigepanel besteht aus zwei unabhängigen Zeichenzeilen mit jeweils sechzehn Zeichenpositionen. Jede Zeichenzelle ist als 5×8- oder optional 5×11-Punktmatrix-Pixelraster implementiert; dieses Referenzmaterial konzentriert sich ausschließlich auf die Industriestandard-5×8-Zeichenmatrix-Variante.

Der Anzeigekontrast hängt von der Versorgungsspannung und der Ein-/Zweizeilen-Konfiguration ab. Aus diesem Grund wird ein variables Spannungssignal zwischen 0V und Vdd an den Kontrastabgleich-Pin Vee angelegt, typischerweise über einen Trimmer-Potentiometer gesteuert. Viele LCD-Module integrieren farbige LED-Hintergrundbeleuchtung (blaue oder grüne Emission). Bei Verwendung der Hintergrundbeleuchtung muss ein Serienwiderstand zur Strombegrenzung in Reihe mit einem der Hintergrundbeleuchtungs-Strompins geschaltet werden, entsprechend den gleichen Designregeln wie bei diskreten LED-Komponenten.

Verdrahtungsdiagramm der LCD-Hintergrundbeleuchtung

Wenn nach dem Einschalten keine Textzeichen angezeigt werden oder alle Glyphen schwach erscheinen, besteht der erste Fehlerbehebungsschritt darin, den Kontrast-Einstellpotentiometer zu kalibrieren, um die richtige Spannungseinstellung zu überprüfen. Dieselbe Fehlerbehebungsprozedur gilt, wenn der Anzeigemodus (Ein-/Zweizeilen-Darstellung) während des Betriebs neu konfiguriert wird.

Interne Speicherpartition des LCD

Der LCD-Controller integriert drei verschiedene dedizierte Speicherpartitionen:

  • DDRAM: Display Data Random Access Memory;
  • CGRAM: Character Generator Random Access Memory; und
  • CGROM: Character Generator Read-Only Memory.

DDRAM-Anzeigedaten-RAM-Partition

Der DDRAM-Speicher enthält die ASCII-Zeichenbytewerte, die für die Bildschirmdarstellung vorgesehen sind, mit einer Kapazität von insgesamt achtzig Zeichenbytes. Einzelne Speicheradressen entsprechen direkt den diskreten Zeichenzellenpositionen auf dem physischen LCD-Panel.

LCD-DDRAM-Adresszuordnungs-Layout

Die Kernbetriebslogik ist einfach: Konfigurieren Sie den LCD-Controller so, dass er Speicheradressen automatisch erhöht (Textverschiebung nach rechts), und legen Sie dann die Startadresse für die Zieltextzeichenfolge fest (z. B. hexadezimale Adresse 00).

Nach Abschluss dieses Konfigurationsschritts werden alle über den D0–D7-Datenbus gesendeten Zeichenbytes sequenziell von links nach rechts in der üblichen Lesereihenfolge dargestellt. Bei einer auf 00 hex gesetzten Basisadresse beginnt die Textdarstellung in der linken Zeichenzelle der oberen Anzeigezeile. Wenn mehr als sechzehn Zeichenbytes gesendet werden, verbleiben alle überschüssigen Daten im DRAM-Speicher, aber nur die ersten sechzehn Positionen bleiben auf dem Bildschirm sichtbar. Ein spezieller Anzeige-Verschiebebefehl muss ausgegeben werden, um versteckte Zeichendaten in das sichtbare Panel-Fenster zu scrollen. Funktional betrachtet fungiert das LCD-Panel als festes Viewport, das horizontal über den stationären DRAM-Speicherinhalt gleitet und so den visuellen Effekt eines über den Bildschirm laufenden Textes erzeugt.

Wenn der Cursorindikator aktiviert ist, wird er an der aktuell aktiven DRAM-Adressposition angezeigt. Nach dem Schreiben eines Zeichenbytes an die aktive Adresse erhöht der Controller automatisch die Zieladresse auf die nächste Zeichenzellenposition.
Als flüchtiger Speicher werden alle DRAM-Daten beim Ausschalten der Stromversorgung dauerhaft gelöscht.

CGROM-Zeichengenerator-ROM-Partition

Das CGROM-Lesespeicherbank enthält die werkseitig geladene Standard-Glyphen-Nachschlagetabelle mit allen vom LCD-Panel nativ unterstützten Zeichensymbolen, wobei jede eindeutige Glyphe einer festen statischen Speicheradresse zugeordnet ist.

LCD-CGROM-ASCII-Zeichentabellen-Layout

Die CGROM-Speicheradressenoffsets entsprechen direkt den standardmäßigen ASCII-Codierungswerten. Wenn die aktive Firmware einen Befehl zum Senden des Zeichens 'P' an den LCD-Datenbus ausführt, wird der binäre Bytewert 0101 0000 auf den D0–D7-Datenleitungen angelegt. Dieser Binärwert entspricht der ASCII-Codierung für Großbuchstaben 'P', den der LCD-Controller verwendet, um die CGROM-Speicherbank zu indizieren und die entsprechende Glyphe an der Adresse 0101 0000 darzustellen. Diese Zuordnungsregel gilt universell für lateinische Groß- und Kleinbuchstaben, jedoch nicht direkt für Dezimalziffern.

Wie im vorhergehenden Zeichentabellendiagramm ersichtlich, sind alle Adressoffsets der Dezimalziffern um einen Basisoffsetwert von 48 relativ zu ihrem numerischen Wert nach oben verschoben: Ziffer 0 entspricht Adresse 48, Ziffer 1 Adresse 49, Ziffer 2 Adresse 50 usw. Daher muss die Firmware-Logik vor der Übertragung über den LCD-Datenbus die dezimale Konstante 48 zu jedem numerischen Ziffernbyte addieren, um eine korrekte Glyphendarstellung zu gewährleisten.

Von den frühen Computerarchitekturen bis zur modernen eingebetteten Hardware interpretieren digitale Verarbeitungssysteme nur binäre Zahlenwerte und können keine menschenlesbaren alphabetischen Zeichen nativ erkennen. Alle Daten, die zwischen einem Mikrocontroller und externer Peripheriehardware ausgetauscht werden, liegen im Binärformat vor, auch wenn sie von menschlichen Bedienern visuell als Textzeichen interpretiert werden; eine Standardtastatur ist ein anschauliches Beispiel dafür. Jedes druckbare Zeichen entspricht einem eindeutigen festen Binärbitmuster. Die ASCII-Codierung ist ein standardisierter Zeichensatz, der auf dem lateinischen Alphabet basiert und eine direkte Eins-zu-eins-Korrelation zwischen druckbaren grafischen Symbolen und ihren entsprechenden binären numerischen Darstellungen definiert.

CGRAM-Benutzerdefinierte-Zeichen-RAM-Partition

Zusätzlich zu den werkseitig vordefinierten CGROM-Glyphen unterstützt der LCD-Controller die Darstellung vollständig benutzerdefinierter grafischer Symbole in der 5×8-Pixel-Zeichenmatrix über eine dedizierte 64-Byte-flüchtige CGRAM-Speicherpartition.

Die CGRAM-Speicherregister sind 8 Bit breit, aber nur die fünf niederwertigsten Bitpositionen werden für die Pixelmusterspeicherung verwendet. Ein logisch hohes Bit (1) in jedem Register entspricht einem leuchtenden Pixelpunkt, während acht aufeinanderfolgende Register-Speicherstellen das vollständige Pixelmuster für eine einzelne benutzerdefinierte Zeichenglyphe speichern. Das folgende Diagramm verdeutlicht dieses Speicherzuordnungsprinzip:

LCD-CGRAM-Benutzerdefinierter-Zeichen-Speicher-Layout

Benutzerdefinierte Glyphenmuster werden typischerweise beim Firmware-Start initialisiert, indem sequenziell logische 0- und 1-Bitmuster in die CGRAM-Speicherregister geschrieben werden, um die gewünschte Pixelgrafik zu erstellen. Um eine vorkonfigurierte benutzerdefinierte Glyphe auf dem Bildschirm darzustellen, muss die Firmware lediglich den entsprechenden CGRAM-Basisadresswert an den LCD-Controller senden. Beachten Sie, dass die erste Spalte der CGROM-Zeichentabelle nicht auf statische CGROM-Adressen verweist, sondern auf benutzerdefinierte CGRAM-Glyphenindizes. In der Beispiellogik dieses Referenzmaterials bewirkt das Senden des Indexwerts 0 die Anzeige der ersten benutzerdefinierten Glyphe, Indexwert 1 die zweite usw.

Grundlegender Befehlssatz des LCD-Controllers

Alle über den D0–D7-Datenbus an das LCD-Modul gesendeten Bytes werden entweder als Controller-Befehlsopcodes oder als Anzeigezeichen-Datenbytes interpretiert, was vollständig vom logischen Zustand des RS-Registerauswahlpins bestimmt wird:

RS = 1 — Die Datenbusbits D0–D7 repräsentieren ASCII-Zeichenbytewerte, die für die Bildschirmdarstellung bestimmt sind. Der LCD-Controller indiziert die CGROM-Glyphenkarte mit diesem Bytewert und stellt das entsprechende Symbol an der aktiven DDRAM-Adressposition dar. Die Ziel-DDRAM-Adresse wird entweder vor der Übertragung des Zeichenbytes vorkonfiguriert oder nach jedem abgeschlossenen Zeichenschreibvorgang automatisch erhöht.

RS = 0 — Die Datenbusbits D0–D7 repräsentieren standardisierte Controller-Befehlsopcodes, die die globalen Anzeigebetriebsmodi konfigurieren. Eine vollständige Tabelle aller erkannten LCD-Befehlsopcodes ist unten aufgeführt:

Befehlsname RS RW D7 D6 D5 D4 D3 D2 D1 D0 Ausführungszeit
Gesamten Anzeigepuffer löschen 0 0 0 0 0 0 0 0 0 1 1,64ms
Cursor auf Startposition zurücksetzen 0 0 0 0 0 0 0 0 1 egal 1,64ms
Eingabemodus-Parameter konfigurieren 0 0 0 0 0 0 0 1 I/D S 40μs
Anzeige- & Cursor-Steuerung 0 0 0 0 0 0 1 D U B 40μs
Cursor/Display-Verschiebebefehl 0 0 0 0 0 1 D/C R/L egal egal 40μs
Hardware-Schnittstellenfunktion festlegen 0 0 0 0 1 DL N F egal egal 40μs
CGRAM-Basisadresse schreiben 0 0 0 1 6-Bit-CGRAM-Adressoffset 40μs
DDRAM-Basisadresse schreiben 0 0 1 7-Bit-DDRAM-Adressoffset 40μs
Busy-Flag (BF) & aktuelle DDRAM-Adresse lesen 0 1 BF 7-Bit-aktive DDRAM-Adresse N/A
Datenbyte in CGRAM/DDRAM schreiben 1 0 D7 D6 D5 D4 D3 D2 D1 D0 40μs
Datenbyte aus CGRAM/DDRAM lesen 1 1 D7 D6 D5 D4 D3 D2 D1 D0 40μs
I/D 1 = Automatische Adresserhöhung (+1)         R/L 1 = Anzeigeinhalt nach rechts verschieben
    0 = Automatische Adressverringerung (-1)             0 = Anzeigeinhalt nach links verschieben
    
S 1 = Globales Anzeige-Scrolling aktiviert          DL 1 = 8-Bit-Parallel-Datenbus-Schnittstelle
  0 = Globales Anzeige-Scrolling deaktiviert            0 = 4-Bit-geteilte Nibble-Datenbus-Schnittstelle
  
D 1 = LCD-Panel-Anzeige aktiv                      N 1 = Zweizeiliger Zeichenmodus
  0 = LCD-Panel-Anzeige deaktiviert                     0 = Einzeiliger Zeichenmodus
  
U 1 = Blinkcursorindikator aktiv                   F 1 = 5×10-Punkt-Zeichenformat
  0 = Statischer Cursorindikator deaktiviert            0 = 5×7-Punkt-Zeichenformat
 
B 1 = Cursor-Blinkanimation aktiviert             D/C 1 = Gesamten Anzeigepuffer verschieben
  0 = Cursor-Blinkanimation deaktiviert                0 = Nur Cursorposition verschieben

Erklärung des Busy-Flag-Statusbits

Relativ zur Hochgeschwindigkeits-Befehlsausführungspipeline des Mikrocontrollers arbeitet die LCD-Controller-Hardware mit wesentlich niedrigeren Verarbeitungsgeschwindigkeiten. Ein dediziertes Status-Flag-Signal wurde implementiert, um anzuzeigen, wann der Controller die Ausführung eines ausstehenden Befehls abgeschlossen hat und neue Eingangsdatenbytes akzeptiert. Dieses Busy-Flag-Signal ist über den D7-Datenbus-Pin lesbar. Wenn das BF-Bit auf logisch niedrig (BF=0) gelöscht wird, hat das LCD-Modul alle vorherigen Verarbeitungen abgeschlossen und ist bereit, neue Befehls- oder Zeichendatenbytes zu empfangen.

Hardware-Schnittstellen-Verdrahtungstopologien des LCD

Es gibt zwei verschiedene Verdrahtungsstandards für die Anbindung eines LCD-Moduls an einen Mikrocontroller: den 8-Bit-Vollbus-Modus und den 4-Bit-geteilten-Nibble-Bus-Modus. Der Zielbetriebsmodus wird während der Initialisierungsroutinen konfiguriert, die unmittelbar nach dem Power-On-Reset ausgeführt werden. Der 8-Bit-Modus überträgt vollständige 8-Bit-Datenbytes über den gesamten D0–D7-Datenbus gemäß der in den vorherigen Abschnitten behandelten Logik. Das Hauptentwurfsmotiv für den 4-Bit-Bus-Modus ist die Schonung der begrenzten allgemeinen E/A-Pins des Mikrocontrollers; nur die vier höherwertigen Datenleitungen D4–D7 werden für die Kommunikation verwendet, während D0–D3 unverbunden bleiben können. Jedes vollständige 8-Bit-Datenbyte wird in zwei aufeinanderfolgende Übertragungszyklen aufgeteilt: die vier höherwertigen Nibble-Bits werden zuerst über D4–D7 gesendet, gefolgt von den vier niederwertigen Nibble-Bits. Die Initialisierungssequenz konfiguriert den LCD-Controller so, dass er diese geteilten Nibble-Übertragungen korrekt analysiert und wieder zusammensetzt. Lesevorgänge vom LCD-Modul sind selten erforderlich, da der Datenfluss hauptsächlich unidirektional vom MCU zum LCD erfolgt. Dies ermöglicht eine gängige Pin-sparende Optimierung: die permanente Erdung des R/W-Lese-/Schreib-Steuerpins. Diese Hardware-Modifikation reduziert die Anzahl der benötigten E/A-Pins um eins, bringt jedoch einen funktionalen Nachteil mit sich: Das Busy-Flag-Statusregister kann nicht abgefragt werden, wodurch die Möglichkeit entfällt, Daten zu lesen, die in den internen Speicherpartitionen des LCD gespeichert sind.

4-Bit-LCD-Mikrocontroller-Verdrahtungsschema

Es gibt eine einfache Software-Umgehung, um die deaktivierte Busy-Flag-Abfrage auszugleichen. Nach dem Senden eines Befehls- oder Zeichenbytes an das LCD-Modul muss die Firmware eine feste Verzögerungszeit einfügen, um dem Controller ausreichend Verarbeitungszeit zu geben. Da der langsamste einzelne LCD-Befehlsvorgang maximal etwa 1,64 ms dauert, gewährleistet eine standardisierte Software-Verzögerung von 2 ms zuverlässig die vollständige Befehlsausführung vor nachfolgenden Übertragungszyklen.

LCD-Einschaltinitialisierungssequenz

Der LCD-Controller führt unmittelbar nach dem Anlegen der Versorgungsspannung automatisch eine interne Reset-Sequenz durch, die etwa 15 ms dauert. Nach dieser Initialisierungsverzögerung tritt das Modul in einen vordefinierten Standardbetriebskonfiguration ein, wie unten aufgeführt:

  1. Der gesamte Anzeigepufferspeicher wird auf leere Glyphen gelöscht
  2. Standard-Hardware-Schnittstellenkonfiguration
    • DL = 1: 8-Bit-Parallel-Datenbus-Kommunikation aktiviert
    • N = 0: Einzeiliger Textmodus aktiv
    • F = 0: 5×8-Punkt-Zeichenformat ausgewählt
  3. Standard-Anzeige- und Cursor-Zustände
    • D = 0: LCD-Panel-Ausgabe deaktiviert
    • U = 0: Sichtbarer Cursor deaktiviert
    • B = 0: Cursor-Blinkanimation deaktiviert
  4. Standard-Eingabemodus für Zeichen
    • I/D = 1: Automatische DDRAM-Adresserhöhung nach jedem Zeichenschreibvorgang
    • S = 0: Globales automatisches Text-Scrolling deaktiviert

Die automatische Power-On-Reset-Sequenz funktioniert unter idealen Stromversorgungsbedingungen in den meisten Prototyp-Designs zuverlässig, aber eine konsistente stabile Initialisierung kann nicht universell garantiert werden. Wenn die Versorgungsspannung nicht innerhalb eines 10-ms-Einschaltfensters den vollen Nennwert von 5V erreicht, gerät der LCD-Controller in einen undefinierten, unregelmäßigen Betriebszustand. Wenn die Stromversorgungsschaltung diese schnelle Spannungsanstiegsanforderung nicht erfüllen kann oder ein absolut konsistenter Hardware-Betrieb obligatorisch ist, muss eine manuelle Firmware-Initialisierungssequenz ausgeführt werden. Diese Initialisierungssequenz löst einen sekundären vollständigen internen Controller-Reset aus, um einen stabilen, vorhersagbaren Betrieb wiederherzustellen.

Das folgende Diagramm zeigt den standardisierten 8-Bit-Bus-Initialisierungsablauf:

8-Bit-LCD-Initialisierungsablauf

Es ist kein Fehler!
In diesem Algorithmus wird derselbe Wert dreimal hintereinander gesendet.

Die standardisierte 4-Bit-Bus-Initialisierungsprozedur ist im folgenden Diagramm dargestellt:

4-Bit-LCD-Initialisierungsablauf

6.3 Praktische Anwendungsbeispiele

Das folgende Schaltbild dient als gemeinsame Hardwareplattform für alle nachfolgenden Demoprogramme:

LED-Testschaltungsschema

Zusätzlich zu den für den Mikrocontroller-Betrieb notwendigen Komponenten wie Oszillator mit Kondensatoren und der einfachsten Reset-Schaltung gibt es mehrere LEDs und einen Taster. Diese dienen zur Anzeige des Programmablaufs.

Alle LEDs sind so gepolt, dass sie durch Anlegen eines logisch niedrigen (0) Pegels an den Mikrocontroller-Pin aktiviert werden.

LED-Blinken

Der Zweck dieses Beispiels ist nicht, die Funktionsweise von LEDs zu demonstrieren, sondern die Betriebsgeschwindigkeit des Mikrocontrollers. Um ein für den Menschen sichtbares Blinken zu ermöglichen, muss zwischen den Ein-/Aus-Zuständen der LEDs ausreichend Zeit vergehen. In diesem Beispiel wird die Zeitverzögerung durch eine Unterroutine namens Delay bereitgestellt. Es handelt sich um eine dreifache Schleife, in der das Programm etwa 0,5 Sekunden verweilt und dabei die Werte in den Registern R0, R1 oder R2 dekrementiert. Nach der Rückkehr aus der Unterroutine wird der Pin-Zustand invertiert und der gleiche Vorgang wiederholt...

;************************************************************************
;* PROGRAMMNAME : Delay.ASM
;* BESCHREIBUNG: Schaltet LED an Pin P1.0 ein/aus mit Software-Verzögerung
;************************************************************************
;GRUNDLEGENDE DIREKTIVEN
$MOD53
$TITLE(DELAY.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK

DSEG    AT    03FH

STACK_START:    DS    040H
;RESET-VEKTOREN

CSEG     AT    0

JMP      XRESET                  ;Reset-Vektor
ORG      100H
XRESET: MOV     SP,#STACK_START         ;Stack-Pointer definieren

MOV     P1,#0FFh                ;Alle Pins als Eingänge konfigurieren
LOOP:

CPL     P1.0                    ;Pin P1.0 Zustand invertieren

LCALL   Delay                   ;Zeitverzögerung

SJMP    LOOP
Delay:

MOV     R2,#20                  ;500 ms Verzögerung

F02:    MOV     R1,#50                  ;25 ms

F01:    MOV     R0,#230

DJNZ    R0,$

DJNZ    R1,F01

DJNZ    R2,F02
END                                     ;Programmende

Verwendung des Watchdog-Timers

Dieses Beispiel zeigt, wie der Watchdog-Timer nicht verwendet werden sollte. Der Watchdog-Timer ist richtig eingestellt (Zählzeit 1024 ms), aber der Befehl zu seiner Rücksetzung wurde absichtlich weggelassen, sodass dieser Timer immer "gewinnt". Infolgedessen wird der Mikrocontroller zurückgesetzt (Registerinhalte bleiben erhalten), das Programm startet von vorne und der Wert im Register R3 wird um 1 erhöht und dann auf Port P1 kopiert.

Die LEDs zeigen diese Zahl binär an...

;************************************************************************
;* PROGRAMMNAME : WatchDog.ASM
;* BESCHREIBUNG : Nach Watchdog-Reset wird der Wert in Register R3 inkrementiert und binär auf Port P1 angezeigt.
;************************************************************************
;GRUNDLEGENDE DIREKTIVEN

$MOD53

$TITLE(WATCHDOG.ASM)

$PAGEWIDTH(132)

$DEBUG

$OBJECT

$NOPAGING
WMCON     DATA    96H

WDTEN     EQU     00000001B        ; Watchdog-Timer aktiviert

PERIOD    EQU     11000000B        ; Watchdog-Periode auf 1024ms gesetzt
;RESET-VEKTOR

CSEG    AT      0

JMP     XRESET           ; Reset-Vektor
CSEG

ORG     100H
XRESET:   ORL     WMCON,#PERIOD    ; Watchdog-Periode definieren

ORL     WMCON,#WDTEN     ; Watchdog-Timer aktivieren
MOV     A,R3             ; R3 nach Port 1 verschieben

MOV     P1,A

INC     R3               ; Register R3 um 1 erhöhen
LAB:      SJMP    LAB              ; Auf Watchdog-Reset warten
END                      ; Programmende

Timer T0 im Modus 1

Dieses Programm verbringt die meiste Zeit in einer Endlosschleife und wartet darauf, dass Timer T0 einen vollen Zyklus zählt. Wenn dies geschieht, wird ein Interrupt ausgelöst, die Routine TIM0_ISR ausgeführt und eine logische Null (0) auf Port P1 um ein Bit nach rechts geschoben. Dies ist eine weitere Möglichkeit, die Betriebsgeschwindigkeit des Mikrocontrollers zu demonstrieren, da jede Verschiebung bedeutet, dass der Zähler T0 216 Impulse gezählt hat!

;************************************************************************
;* PROGRAMMNAME : Tim0Mod1.ASM
;* BESCHREIBUNG: Rotiert eine "0" auf Port 1 mittels Timer T0 im Modus 1
;************************************************************************
;GRUNDLEGENDE DIREKTIVEN

$MOD53

$TITLE(TIM0MOD1.ASM)

$PAGEWIDTH(132)

$DEBUG

$OBJECT

$NOPAGING
;VARIABLENDEKLARATION
;STACK
DSEG     AT     03FH
STACK_START:     DS     040H
;RESET-VEKTOREN

CSEG      AT 0

JMP       XRESET             ; Reset-Vektor
ORG       00BH

JMP       TIM0_ISR           ; Timer T0 Reset-Vektor


ORG       100H
XRESET: MOV      SP,#STACK_START    ; Stack-Pointer definieren

MOV       TMOD,#01H          ; Modus 1 gewählt

MOV       A,#0FFH

MOV       P1,#0FFH

SETB      TR0                ; Timer T0 gestartet

MOV       IE,#082H           ; Interrupt aktiviert

CLR       C
LOOP1: SJMP      LOOP1              ; Hier verweilen
TIM0_ISR:        RRC     A          ; Akkumulator A mit Übertragsflag rotieren

MOV     P1,A       ; Akkumulatorinhalt nach PORT1

RETI               ; Rückkehr aus Interrupt
END                          ; Programmende

Kapitel 6 : Praktische Beispiele

Einführung

Dieses Kapitel vermittelt grundlegendes Wissen über die Mikrocontroller-Hardware, das für den praktischen Einsatz erforderlich ist. Sie werden in diesem Abschnitt keine übermäßig komplexen fortgeschrittenen Programme oder ausgefeilten Schaltungsdesigns finden. Stattdessen beweisen die folgenden praktischen Beispiele, dass die eingebettete Programmierung weder ein exklusives Privileg noch eine talentabhängige Fähigkeit ist; es ist einfach der Prozess, modulare Funktionslogik über eine standardisierte Befehlssyntax zusammenzusetzen. Seien Sie versichert, dass Hardware-Design und iterative Entwicklung einem konsistenten Kernablauf folgen: „testen, anpassen, wiederholen“. Natürlich wächst die Projektkomplexität mit der Erfahrung, da dieselben grundlegenden Bausteine von Hobby-Einsteigern und professionellen Architekten zusammengesetzt werden können...

Während sich diese Einführungsdemos ausschließlich auf grundlegende Funktionsabläufe konzentrieren, birgt jedes eingebettete Hardwaresystem eine oft übersehene verborgene Sicherheitsrisikoschicht, die in Einführungsmaterialien selten behandelt wird. Der Mikrocontroller (MCU), der diese einfachen Steuerroutinen ausführt, kann später in kommerzielle Endprodukte integriert werden, wo der Schutz des ausführbaren Quellcodes vor unbefugtem Zugriff zu einer wichtigen Designpriorität wird. Viele unerfahrene Ingenieure glauben fälschlicherweise, dass der eingebaute Lockbit-Sicherungsmechanismus den externen Lesezugriff auf den internen Flash-Speicher vollständig blockieren kann, doch diese Annahme ist nicht universell zuverlässig. In realen Bedrohungsszenarien können böswillige Akteure Chip-Dekapsulationsabläufe einsetzen, um die bloßen Silizium-Die-Schichten freizulegen und eine direkte Mikrosondierung der sicherheitssteuernden Hardwaresicherungen durchzuführen. Sobald das Gehäuse entfernt ist, können Gegner einen vollständigen Speicherauszug aller Programmspeicherbereiche extrahieren und so eine vollständige Firmware-Extraktion ohne gültige Authentifizierungsnachweise durchführen. Das eingebaute EEPROM-Chipsatz, das üblicherweise Werkskalibrierungsparameter und kryptografische Sicherheitsschlüssel speichert, ist ähnlichen Schwachstellen gegenüber solchen physischen Hardware-Eindringangriffen ausgesetzt. Bestimmte Bedrohungsakteure nutzen Laborgeräte mit fokussiertem Ionenstrahl (FIB), um einzelne Sicherungsschaltkreise selektiv zu modifizieren und eine dauerhafte Entsperrung von als geschützt markierten Speicherzonen zu erzwingen. Andere Angreifer nutzen Seitenkanal-Analysemethoden, um vollständige Programmbinarys schrittweise auszulesen, ohne eine Hardware-Manipulationserkennung auszulösen. Im schlimmsten Exploit-Szenario ermöglicht ein vollständiger Auszug sowohl der Flash- als auch der EEPROM-Speicherpartitionen es Angreifern, identische Hardware-Repliken herzustellen, die voll funktionsfähige Geräteklone produzieren und den Wert des proprietären geistigen Eigentums vollständig untergraben. Aus diesem Grund müssen Entwickler bereits beim Erlernen der grundlegenden digitalen Ein-/Ausgangslogik und Timing-Steuerungsroutinen erkennen, dass dieselben Chip-Pins und Kernregister bei bösartigen Reverse-Engineering-Kampagnen ausgenutzt werden können. Die Wiederherstellung eines nicht funktionierenden eingebetteten Geräts erfordert gelegentlich die Umgehung von Sicherheitssperren durch Spannungsglitch-Injektion – eine legitime Hardware-Reparaturtechnik, die gleichzeitig einen Angriffspunkt schafft. Die Beherrschung der zugrunde liegenden Lockbit-Betriebslogik ist eine obligatorische Kompetenz sowohl für eingebettete Firmware-Entwickler als auch für dedizierte Hardwaresicherheitsanalysten. Eine große Anzahl kommerzieller eingebetteter Geräte hat aufgrund unsachgemäß konfigurierter Sicherungssicherungen vollständige Verletzungen des geistigen Eigentums erlitten, wodurch der ausführbare Code vollständig für den externen Abruf freigegeben wurde. Ein einfaches Auslesen der Chip-Konfigurationsspeicherbytes kann alle Sicherheitsrichtlinieneinstellungen offenlegen und Bedrohungsakteure direkt zum schwächsten Exploit-Vektor führen. Selbst die spätere einfache Watchdog-Timer-Demonstration kann zur Implementierung einer Hardware-Manipulationserkennungslogik umfunktioniert werden. In der realen Ingenieurspraxis müssen Entwickler ein Gleichgewicht zwischen Hardware-Funktionalität und Einbruchschutzmaßnahmen finden, um sicherzustellen, dass eine unbefugte Firmware-Extraktion technisch und finanziell undurchführbar bleibt. Die nachfolgenden praktischen Demos veranschaulichen elementare Hardware-Arbeitsabläufe, zeigen jedoch implizit, wie Kern-MCU-Peripheriegeräte wie Timer, Interrupt-Controller und serielle Kommunikationsschnittstellen zur Implementierung robuster Sicherheitshärtungs-Gegenmaßnahmen umfunktioniert werden können. Beispielsweise kann die Verwendung von Timermodulen zur Erzeugung zufälliger Timing-Offsets zeitbasierte Seitenkanalangriffe abmildern, die auf das Speicherauszug vertraulicher Geheimdaten abzielen. Darüber hinaus kann die UART-seriellen Übertragungslogik mit leichten Verschlüsselungsprotokollen umhüllt werden, um das Abhören von Rohdaten während unbefugter Leseversuche zu blockieren. LED-Multiplexing-Anzeigeschaltungen, obwohl scheinbar trivial, schaffen ein kritisches Bewusstsein für Timing-Empfindlichkeit – eine grundlegende Fähigkeit, die für die Implementierung sicherer authentifizierter Bootsequenzen erforderlich ist. Das EEPROM-Datenspeicherbeispiel behandelt direkt Workflows zur persistenten Datenwiederherstellung, ein technisches Konzept, das sich auf die sichere langfristige Aufbewahrung kryptografischer Schlüssel erstreckt. Letztendlich sollte jede Zeile eingebetteten Firmware-Codes unter der Annahme geschrieben werden, dass feindliche Akteure irgendwann vollen physischen Zugriff auf die Zielhardware erlangen könnten. Der Sicherheitssperrmechanismus dient lediglich als primäre Verteidigungsbarriere; ein umfassender Hardware-Schutz beruht auf mehrschichtigen Sicherheitsvorkehrungen, die eine Chip-Dekapsulation und Silizium-Sondierung für Angreifer wirtschaftlich undurchführbar machen. Dieses Kapitel schafft ein grundlegendes Sicherheitsbewusstsein, ohne tief in spezialisierte Reverse-Engineering-Exploit-Taktiken einzusteigen. Mit diesem doppelten Fokus auf funktionale Betriebsabläufe und eingebettete Sicherheit wenden wir uns nun der Betrachtung grundlegender Mikrocontroller-Verdrahtungsschemata und unterstützender Peripherie-Hardwarekomponenten zu.

6.1 Grundlegende Hardware-Verdrahtung

Grundlegende Verdrahtung - Stromversorgung

Wie im obigen Schema dargestellt, müssen drei obligatorische Signalbereiche korrekt verdrahtet werden, um einen stabilen Mikrocontroller-Betrieb zu gewährleisten:

  • Geregelte Stromversorgung;
  • Reset-Signal; und
  • Taktsignal.

Es handelt sich um sehr einfache Schaltungen, aber es muss nicht immer so sein. Wenn das Zielgerät zur Steuerung teurer Maschinen oder zur Aufrechterhaltung lebenswichtiger Funktionen eingesetzt wird, wird alles zunehmend komplexer. Für den Anfang reicht diese Lösung jedoch aus...

Stromversorgung

Obwohl dieser Mikrocontroller bei verschiedenen Versorgungsspannungen betrieben werden kann, warum das Murphysche Gesetz testen? Eine 5V-Gleichspannung wird am häufigsten verwendet. Die in der Abbildung gezeigte Schaltung verwendet den kostengünstigen integrierten Dreipol-Positivregler LM7805 und bietet eine hochwertige Spannungsstabilität und ausreichend Strom, um den Mikrocontroller und die Peripherieelektronik normal zu betreiben (ausreichend Strom bedeutet in diesem Fall 1A).

Reset-Signal

Damit der Mikrocontroller ordnungsgemäß arbeiten kann, muss am Reset-Pin RS eine logische 0 (0V) anliegen. Der Taster, der den Reset-Pin RS mit der Versorgungsspannung VCC verbindet, ist nicht erforderlich. Er wird jedoch fast immer bereitgestellt, da er es ermöglicht, den Mikrocontroller bei Problemen sicher in einen normalen Betriebszustand zurückzusetzen. Wenn 5V an diesen Pin angelegt werden, wird der Mikrocontroller zurückgesetzt und das Programm startet von vorne.

Taktsignal

Obwohl der Mikrocontroller einen eingebauten Oszillator hat, kann er nicht ohne zwei externe Kondensatoren und einen Quarzkristall arbeiten, die seinen Betrieb stabilisieren und seine Frequenz (Arbeitsgeschwindigkeit des Mikrocontrollers) bestimmen.

Taktsignal

Natürlich ist diese Lösung nicht immer anwendbar, daher gibt es immer alternative Lösungen. Eine davon besteht darin, das Taktsignal von einer speziellen Quelle über einen Inverter bereitzustellen. Siehe Abbildung links.

6.2 Zusätzliche Komponenten

Unabhängig davon, dass der Mikrocontroller ein Produkt moderner Technologie ist, ist er ohne Anschluss an zusätzliche Komponenten nutzlos. Vereinfacht gesagt bedeutet das Auftreten einer Spannung an seinen Pins nichts, wenn sie nicht zur Durchführung bestimmter Operationen (Ein-/Ausschalten, Verschieben, Anzeigen usw.) verwendet wird.

Schalter und Taster

Es gibt keine einfacheren Bauteile als Schalter und Taster. Dies ist die einfachste Methode, um das Auftreten einer Spannung am Mikrocontroller-Eingangspin zu erkennen.

Schalter und Taster

In der Praxis ist es jedoch nicht so einfach... Es geht um das Kontaktprellen – ein häufiges Problem bei mechanischen Schaltern. Wenn die Kontakte aufeinandertreffen, wirken ihr Impuls und ihre Elastizität zusammen und verursachen ein Prellen. Das Ergebnis ist ein schnell pulsierender elektrischer Strom anstelle eines sauberen Übergangs von Null auf Vollstrom. Dies geschieht hauptsächlich aufgrund von Vibrationen, leichten Unebenheiten und Schmutz zwischen den Kontakten. Dieser Effekt ist bei der alltäglichen Verwendung dieser Komponenten normalerweise nicht wahrnehmbar, da das Prellen zu schnell erfolgt. Mit anderen Worten, der gesamte Vorgang dauert nicht lange (einige Mikro- oder Millisekunden), aber er ist lang genug, um vom Mikrocontroller registriert zu werden. Wenn nur ein Taster als Impulszähler verwendet wird, treten in fast 100 % der Fälle Fehler auf!

RC-Entprellung

Die einfachste Lösung für dieses Problem ist der Anschluss einer einfachen RC-Schaltung, die schnelle Spannungsänderungen unterdrückt. Da die Prellperiode nicht definiert ist, sind die Werte der Komponenten nicht genau festgelegt. In den meisten Fällen wird empfohlen, die in der folgenden Abbildung gezeigten Werte zu verwenden.

Wenn absolute Stabilität erforderlich ist, sollten radikale Maßnahmen ergriffen werden. Der Ausgang der in der Abbildung gezeigten Schaltung (RS-Flipflop) ändert seinen logischen Zustand erst nach der Erkennung des ersten durch Kontaktprellen ausgelösten Impulses. Diese Lösung ist teuer (SPDT-Schalter), aber effizient, das Problem ist definitiv gelöst. Da kein Kondensator verwendet wird, können auf diese Weise auch sehr kurze Impulse erfasst werden.

Flipflop-Entprellung

Zusätzlich zu diesen Hardware-Lösungen gibt es auch eine einfache Software-Lösung. Wenn ein Programm den Zustand eines Eingangspins testet und eine Änderung erkennt, sollte die Prüfung nach einer bestimmten Verzögerung erneut durchgeführt werden. Wenn die Änderung bestätigt wird, bedeutet dies, dass ein Schalter oder Taster seine Position geändert hat. Die Vorteile einer solchen Lösung sind offensichtlich: Sie ist kostenlos, die Auswirkungen von Störungen werden beseitigt und sie kann auch bei Kontakten geringerer Qualität angewendet werden. Der Nachteil ist derselbe wie bei der Verwendung eines RC-Filters, d. h. Impulse, die kürzer als die Programmverzögerung sind, können nicht erfasst werden.

Optokoppler

Optokoppler

Ein Optokoppler ist ein Bauteil, das üblicherweise zur galvanischen Trennung der Mikrocontroller-Elektronik von gefährlichen Strömen oder Spannungen in seiner Umgebung verwendet wird. Optokoppler haben normalerweise eine, zwei oder vier Lichtquellen (LED-Dioden) auf ihrer Eingangsseite, während sich auf ihrer Ausgangsseite, den Dioden gegenüber, die gleiche Anzahl von lichtempfindlichen Elementen (Fototransistoren, Fotothyristoren oder Fototriacs) befindet. Der Punkt ist, dass ein Optokoppler einen kurzen optischen Übertragungsweg verwendet, um ein Signal zwischen den Schaltungselementen zu übertragen, während er sie elektrisch isoliert hält. Diese Isolierung macht nur Sinn, wenn Dioden und lichtempfindliche Elemente getrennt mit Strom versorgt werden. Auf diese Weise werden der Mikrocontroller und die teure Zusatzelektronik vollständig vor Hochspannung und Störungen geschützt, die in der Praxis die häufigste Ursache für die Zerstörung, Beschädigung oder instabile Funktion elektronischer Geräte sind. Die am häufigsten verwendeten Optokoppler sind solche mit Fototransistoren an ihren Ausgängen. Bei Verwendung eines Optokopplers mit interner Basis-Pin-6-Verbindung (es gibt auch Optokoppler ohne diese) kann die Basis offen gelassen werden. Eine optionale Verbindung, die die Auswirkungen von Störungen durch Unterdrückung sehr kurzer Impulse verringert, ist in der Abbildung durch die unterbrochene Linie dargestellt.

Relais

Relais

Ein Relais ist ein elektrischer Schalter, der unter der Steuerung eines anderen elektrischen Stromkreises öffnet und schließt. Er wird daher an die Ausgangspins des Mikrocontrollers angeschlossen und zum Ein- und Ausschalten von Hochleistungsgeräten wie Motoren, Transformatoren, Heizungen, Lampen, Antennensystemen usw. verwendet. Diese werden fast immer von den empfindlichen Komponenten der Platine entfernt platziert. Es gibt verschiedene Arten von Relais, aber alle arbeiten nach dem gleichen Prinzip. Wenn ein Strom durch die Spule fließt, wird das Relais von einem Elektromagneten betätigt, um einen oder mehrere Kontaktsätze zu öffnen oder zu schließen. Ähnlich wie bei Optokopplern gibt es keine galvanische Verbindung (elektrischer Kontakt) zwischen Eingangs- und Ausgangskreisen. Relais benötigen normalerweise sowohl eine höhere Spannung als auch einen höheren Strom, um zu funktionieren, aber es gibt auch Miniaturrelais, die mit einem niedrigen Strom direkt von einem Mikrocontroller-Pin aktiviert werden können.

Die Abbildung zeigt die für den 8051-Mikrocontroller spezifische Lösung. Hier wird ein Darlington-Transistor verwendet, um Relais aufgrund seiner hohen Stromverstärkung zu aktivieren. Dies entspricht nicht den "Regeln", ist jedoch erforderlich, wenn eine Aktivierung mit logisch 1 verwendet wird, da der Ausgangsstrom dann sehr niedrig ist (Pin verhält sich als Eingang).

Grundlegende Verdrahtung des Mikrocontrollers - Relais

Um das Auftreten einer durch plötzliches Abschalten des Spulenstroms verursachten hohen Selbstinduktionsspannung zu verhindern, wird eine antiparallele Diode parallel zur Spule geschaltet. Der Zweck dieser Diode besteht darin, die Spannungsspitze zu "begrenzen".

Leuchtdiode (LED)

Leuchtdioden sind Bauelemente zur optischen Signalgebung in der Elektronik. Sie werden in verschiedenen Formen, Farben und Größen hergestellt. Aufgrund ihres niedrigen Preises, ihres geringen Stromverbrauchs und ihrer einfachen Verwendung haben sie andere Lichtquellen, insbesondere Glühlampen, fast vollständig verdrängt. Sie verhalten sich ähnlich wie normale Dioden, mit dem Unterschied, dass sie Licht emittieren, wenn Strom durch sie fließt.

Leuchtdiode (LED)

Es ist wichtig, ihren Strom zu begrenzen, da sie sonst dauerhaft zerstört werden. Aus diesem Grund muss ein Widerstand in Reihe zu einer LED geschaltet werden. Um den Wert dieses Widerstands zu bestimmen, muss die Durchlassspannung der Diode bekannt sein, die davon abhängt, aus welchem Material die Diode besteht und welche Farbe sie hat. Typische Werte der am häufigsten verwendeten Dioden sind in der folgenden Tabelle aufgeführt. Wie zu sehen, gibt es drei Haupttypen von LEDs. Standard-LEDs erreichen ihre volle Helligkeit bei einem Strom von 20 mA. Niedrigstrom-Dioden erreichen ihre volle Helligkeit bei einem zehnmal niedrigeren Strom, während Super-Bright-Dioden ein intensiveres Licht als Standard-LEDs erzeugen.

Farbe Typ Typischer Strom Id (mA) Maximaler Strom If (mA) Durchlassspannung Ud (V)
Infrarot - 30 50 1.4
Rot Standard 20 30 1.7
Rot Super Hell 20 30 1.85
Rot Niedrigstrom 2 30 1.7
Orange - 10 30 2.0
Grün Niedrigstrom 2 20 2.1
Gelb - 20 30 2.1
Blau - 20 30 4.5
Weiß - 25 35 4.4
Niedrigstrom-LED

Da der 8051-Mikrocontroller nur einen geringen Ausgangsstrom liefern kann und seine Pins als Ausgänge konfiguriert sind, wenn die an ihnen anliegende Spannung 0V beträgt, erfolgt der direkte Anschluss an LEDs wie in der Abbildung rechts gezeigt (Niedrigstrom-LED, Kathode ist mit dem Ausgangspin verbunden).

LED-Anzeigen

Eine LED-Anzeige ist im Grunde nichts anderes als mehrere LEDs, die in einem Kunststoffgehäuse vergossen sind. Es gibt viele Arten von Anzeigen, die aus mehreren Dutzend eingebauten Dioden bestehen und verschiedene Symbole anzeigen können.

LED-Anzeigen

Am häufigsten wird die sogenannte 7-Segment-Anzeige verwendet. Sie besteht aus 8 LEDs, wobei 7 Segmente rechteckig für die Symbolanzeige angeordnet sind und ein zusätzliches Segment für die Anzeige des Dezimalpunkts vorhanden ist. Um die Verbindung zu vereinfachen, sind die Anoden und Kathoden aller Dioden mit dem gemeinsamen Pin verbunden, sodass es gemeinsame Anoden- und gemeinsame Kathodenanzeigen gibt. Die Segmente sind mit den Buchstaben A bis G sowie dp gekennzeichnet, wie in der Abbildung links gezeigt. Bei der Verbindung wird jede Diode separat behandelt, was bedeutet, dass jede ihren eigenen Strombegrenzungswiderstand benötigt.

Anzeigen, die mit dem Mikrocontroller verbunden sind, belegen normalerweise eine große Anzahl wertvoller E/A-Pins, was ein großes Problem darstellen kann, insbesondere wenn mehrstellige Zahlen angezeigt werden sollen. Das Problem ist mehr als offensichtlich, wenn beispielsweise zwei 6-stellige Zahlen angezeigt werden sollen (eine einfache Rechnung zeigt, dass in diesem Fall 96 Ausgangspins benötigt werden). Die Lösung für dieses Problem heißt MULTIPLEXING. Dabei wird eine optische Täuschung erzeugt, die auf dem gleichen Funktionsprinzip wie eine Filmkamera basiert. Es ist immer nur eine Ziffer aktiv, aber sie ändert ihren Zustand so schnell, dass der Eindruck entsteht, dass alle Ziffern einer Zahl gleichzeitig aktiv sind.

Grundlegende Verdrahtung des Mikrocontrollers - LED-Anzeigen

Hier ist eine Erklärung der obigen Abbildung. Zuerst wird ein Byte, das die Einer darstellt, an einen Mikrocontroller-Port angelegt und gleichzeitig ein Transistor T1 aktiviert. Nach einer Weile wird T1 ausgeschaltet, ein Byte, das die Zehner darstellt, wird an einen Port angelegt und ein Transistor T2 aktiviert. Dieser Vorgang wird für alle Ziffern und entsprechenden Transistoren zyklisch mit hoher Geschwindigkeit wiederholt.

Die Tatsache, dass der Mikrocontroller nur eine Art Miniaturcomputer ist, der nur die Sprache der Nullen und Einsen versteht, zeigt sich vollständig bei der Anzeige einer Ziffer. Der Mikrocontroller weiß nämlich nicht, was Einer, Zehner oder Hunderter sind, noch wie die zehn Ziffern aussehen, die wir gewohnt sind. Daher muss jede anzuzeigende Zahl wie folgt vorbereitet werden:

Zunächst muss eine mehrstellige Zahl in Einer, Zehner usw. in einer bestimmten Unterroutine zerlegt werden. Dann muss jede dieser Ziffern in speziellen Bytes gespeichert werden. Die Ziffern erhalten ein bekanntes Format durch eine "Maskierung". Mit anderen Worten, das Binärformat jeder Ziffer wird in einer einfachen Unterroutine durch eine andere Bitkombination ersetzt. Beispielsweise wird die Ziffer 8 (0000 1000) durch die Binärzahl 0111 111 ersetzt, um alle LEDs, die die Ziffer 8 anzeigen, zu aktivieren. Die einzige Diode, die in diesem Fall inaktiv bleibt, ist für den Dezimalpunkt reserviert. Wenn ein Mikrocontroller-Port so mit der Anzeige verbunden ist, dass Bit 0 das Segment "a" aktiviert, Bit 1 das Segment "b", Bit 2 das Segment "c" usw., dann zeigt die folgende Tabelle die "Maske" für jede Ziffer.

Maskierung von LED-Anzeigen
Anzuzeigende Ziffer Anzeigesegmente
dp a b c d e f g
0 1 0 0 0 0 0 0 1
1 1 0 0 1 1 1 1 1
2 1 0 0 1 0 0 1 0
3 1 0 0 0 0 1 1 0
4 1 1 0 0 1 1 0 0
5 1 0 1 0 0 1 0 0
6 1 0 1 0 0 0 0 0
7 1 0 0 0 1 1 1 1
8 1 0 0 0 0 0 0 0
9 1 0 0 0 0 1 0 0

Zusätzlich zu den Ziffern 0 bis 9 können durch entsprechende Maskierung auch einige Buchstaben des Alphabets - A, C, E, J, F, U, H, L, b, c, d, o, r, t - angezeigt werden.
Wenn gemeinsame Kathodenanzeigen verwendet werden, sollten alle Einsen in der Tabelle durch Nullen ersetzt werden und umgekehrt. Außerdem sollten NPN-Transistoren als Treiber verwendet werden.

Flüssigkristallanzeigen (LCD)

Ein LCD-Display ist speziell für den Einsatz mit Mikrocontrollern hergestellt, was bedeutet, dass es nicht von standardmäßigen IC-Schaltungen aktiviert werden kann. Es wird zur Anzeige verschiedener Nachrichten auf einem Miniatur-Flüssigkristalldisplay verwendet.

Flüssigkristallanzeigen (LCD)

Das hier beschriebene Modell wird aufgrund seines niedrigen Preises und seiner großen Fähigkeiten in der Praxis am häufigsten verwendet. Es basiert auf dem Mikrocontroller HD44780 (Hitachi) und kann Nachrichten in zwei Zeilen mit jeweils 16 Zeichen anzeigen. Es zeigt alle Buchstaben des Alphabets, griechische Buchstaben, Satzzeichen, mathematische Symbole usw. an. Darüber hinaus ist es möglich, benutzerdefinierte Symbole anzuzeigen. Weitere nützliche Funktionen sind automatische Nachrichtenverschiebung (links und rechts), Cursor-Anzeige, LED-Hintergrundbeleuchtung usw.

LCD-Pins

Entlang einer Seite einer kleinen Leiterplatte befinden sich Pins. Diese werden zum Anschluss an den Mikrocontroller verwendet. Es gibt insgesamt 14 Pins mit Nummern (16, wenn eine Hintergrundbeleuchtung vorhanden ist). Ihre Funktion ist in der folgenden Tabelle beschrieben:

Funktion Pin-Nr. Name Logikzustand Beschreibung
Masse 1 Vss - 0V
Stromversorgung 2 Vdd - +5V
Kontrast 3 Vee - 0 - Vdd
Betriebssteuerung 4 RS 0
1
D0-D7 werden als Befehle interpretiert
D0-D7 werden als Daten interpretiert
5 R/W 0
1
Daten schreiben (vom Controller zum LCD)
Daten lesen (vom LCD zum Controller)
6 E 0
1
Von 1 auf 0
Zugriff auf LCD deaktiviert
Normalbetrieb
Daten/Befehle werden an LCD übertragen
Daten / Befehle 7 D0 0/1 Bit 0 LSB
8 D1 0/1 Bit 1
9 D2 0/1 Bit 2
10 D3 0/1 Bit 3
11 D4 0/1 Bit 4
12 D5 0/1 Bit 5
13 D6 0/1 Bit 6
14 D7 0/1 Bit 7 MSB

LCD-Bildschirm

LCD-Bildschirmpixel

Ein LCD-Bildschirm besteht aus zwei Zeilen mit jeweils 16 Zeichen. Jedes Zeichen besteht aus einer 5x8- oder 5x11-Punktmatrix. Dieses Buch behandelt das am häufigsten verwendete Display, d. h. das 5x8-Zeichen-Display.

Der Displaykontrast hängt von der Versorgungsspannung und davon ab, ob Nachrichten in einer oder zwei Zeilen angezeigt werden. Aus diesem Grund wird am Pin Vee eine variable Spannung 0-Vdd angelegt. Normalerweise wird dazu ein Trimmer-Potentiometer verwendet. Einige LCD-Displays haben eine eingebaute Hintergrundbeleuchtung (blaue oder grüne LEDs). Wenn sie während des Betriebs verwendet wird, sollte ein Strombegrenzungswiderstand in Reihe mit einem der Pins für die Hintergrundbeleuchtung geschaltet werden (ähnlich wie bei LEDs).

LCD-Hintergrundbeleuchtung

Wenn keine Zeichen angezeigt werden oder alle schwach erscheinen, wenn das Display eingeschaltet ist, sollte als erstes der Potentiometer für die Kontrastregelung überprüft werden. Ist er richtig eingestellt? Gleiches gilt, wenn der Betriebsmodus geändert wurde (Schreiben in einer oder zwei Zeilen).

LCD-Speicher

Das LCD-Display enthält drei Speicherblöcke:

  • DDRAM Display Data RAM;
  • CGRAM Character Generator RAM; und
  • CGROM Character Generator ROM.

DDRAM-Speicher

Der DDRAM-Speicher wird zum Speichern der anzuzeigenden Zeichen verwendet. Die Größe dieses Speichers reicht für 80 Zeichen. Einige Speicherstellen sind direkt mit den Zeichen auf dem Display verbunden.

DDRAM-Speicher

Er funktioniert ganz einfach: Es reicht aus, das Display so zu konfigurieren, dass die Adressen automatisch erhöht werden (nach rechts verschieben) und die Startadresse für die anzuzeigende Nachricht festgelegt wird (z. B. 00 hex).

Danach werden alle über die Leitungen D0-D7 gesendeten Zeichen in dem gewohnten Nachrichtenformat von links nach rechts angezeigt. In diesem Fall beginnt die Anzeige im ersten Feld der ersten Zeile, da die Adresse 00 hex ist. Wenn mehr als 16 Zeichen gesendet werden, werden alle gespeichert, aber nur die ersten sechzehn Zeichen sind sichtbar. Um die restlichen anzuzeigen, muss ein Verschiebebefehl verwendet werden. Praktisch gesehen erscheint alles so, als ob das LCD-Display ein "Fenster" ist, das sich über Speicherstellen mit verschiedenen Zeichen von links nach rechts bewegt. So wird der Effekt einer "bewegten" Nachricht auf dem Bildschirm erzeugt.

Wenn der Cursor eingeschaltet ist, erscheint er an der Stelle, die gerade adressiert wird. Mit anderen Worten: Wenn ein Zeichen an der Cursorposition erscheint, bewegt es sich automatisch zur nächsten adressierten Stelle.
Da es sich um eine Art RAM-Speicher handelt, können Daten geschrieben und gelesen werden, aber ihr Inhalt geht beim Ausschalten der Stromversorgung unwiederbringlich verloren.

CGROM-Speicher

Der CGROM-Speicher enthält die Standard-Zeichentabelle mit allen Zeichen, die auf dem Bildschirm angezeigt werden können. Jedes Zeichen ist einem Speicherplatz zugeordnet.

CGROM-Speicher

Die Adressen der CGROM-Speicherplätze entsprechen den ASCII-Zeichen. Wenn das laufende Programm auf einen Befehl "sende Zeichen P an Port" stößt, erscheint der Binärwert 0101 0000 am Port. Dieser Wert ist das ASCII-Äquivalent für das Zeichen P. Er wird dann an das LCD geschrieben, was zur Anzeige des Symbols von der CGROM-Stelle 0101 0000 führt. Mit anderen Worten, das Zeichen "P" wird angezeigt. Dies gilt für alle Buchstaben des Alphabets (Groß- und Kleinbuchstaben), aber nicht für Zahlen.

Wie auf der vorherigen "Karte" zu sehen, sind die Adressen aller Ziffern um 48 gegenüber ihrem Wert nach oben verschoben (Ziffer 0 Adresse 48, Ziffer 1 Adresse 49, Ziffer 2 Adresse 50 usw.). Daher muss jede Ziffer vor dem Senden an das LCD um die Dezimalzahl 48 erhöht werden, um sie korrekt anzuzeigen.

Von ihrer Entstehung bis heute können Computer nur Zahlen erkennen, aber keine Buchstaben. Das bedeutet, dass alle Daten, die ein Computer mit einem Peripheriegerät austauscht, ein binäres Format haben, auch wenn sie vom Menschen als Buchstaben erkannt werden (die Tastatur ist ein hervorragendes Beispiel). Jedes Zeichen entspricht einer eindeutigen Kombination von Nullen und Einsen. ASCII ist eine Zeichencodierung, die auf dem englischen Alphabet basiert. Der ASCII-Code legt die Entsprechung zwischen standardmäßigen Zeichensymbolen und ihren numerischen Äquivalenten fest.

CGRAM-Speicher

Neben Standardzeichen kann das LCD-Display auch vom Benutzer selbst definierte Symbole anzeigen. Es kann jedes Symbol in der Größe von 5x8 Pixeln sein. Ein RAM-Speicher namens CGRAM in der Größe von 64 Bytes ermöglicht dies.

Die Speicherregister sind 8 Bit breit, aber nur die 5 unteren Bits werden verwendet. Eine logische Eins (1) in jedem Register stellt einen leuchtenden Punkt dar, während 8 zusammengehörige Stellen ein Zeichen darstellen. Dies wird am besten in der folgenden Abbildung veranschaulicht:

CGRAM-Speicher

Symbole werden normalerweise zu Beginn des Programms definiert, indem einfach Nullen und Einsen in die CGRAM-Register geschrieben werden, um die gewünschten Formen zu erzeugen. Um sie anzuzeigen, reicht es aus, ihre Adresse anzugeben. Beachten Sie die erste Spalte in der CGROM-Zeichentabelle. Sie enthält keine RAM-Speicheradressen, sondern die hier diskutierten Symbole. In diesem Beispiel bedeutet "Anzeige 0" - Anzeige "č", "Anzeige 1" - Anzeige "ž" usw.

LCD-Grundbefehle

Alle über die Ausgänge D0-D7 an das LCD übertragenen Daten werden als Befehl oder als Daten interpretiert, was vom logischen Zustand des Pins RS abhängt:

RS = 1 - Bits D0-D7 sind Adressen der anzuzeigenden Zeichen. Der LCD-Prozessor adressiert ein Zeichen aus der Zeichentabelle und zeigt es an. Die DDRAM-Adresse gibt die Stelle an, an der das Zeichen angezeigt werden soll. Diese Adresse wird vor der Übertragung des Zeichens definiert, oder die Adresse des zuvor übertragenen Zeichens wird automatisch erhöht.

RS = 0 - Bits D0-D7 sind Befehle, die den Anzeigemodus festlegen. Die vom LCD erkannten Befehle sind in der folgenden Tabelle aufgeführt:

Befehl RS RW D7 D6 D5 D4 D3 D2 D1 D0 Ausführungszeit
Display löschen 0 0 0 0 0 0 0 0 0 1 1.64mS
Cursor nach Hause 0 0 0 0 0 0 0 0 1 x 1.64mS
Eingabemodus festlegen 0 0 0 0 0 0 0 1 I/D S 40uS
Display Ein/Aus-Steuerung 0 0 0 0 0 0 1 D U B 40uS
Cursor/Display-Verschiebung 0 0 0 0 0 1 D/C R/L x x 40uS
Funktion festlegen 0 0 0 0 1 DL N F x x 40uS
CGRAM-Adresse festlegen 0 0 0 1 CGRAM-Adresse 40uS
DDRAM-Adresse festlegen 0 0 1 DDRAM-Adresse 40uS
"BUSY"-Flag (BF) lesen 0 1 BF DDRAM-Adresse -
In CGRAM oder DDRAM schreiben 1 0 D7 D6 D5 D4 D3 D2 D1 D0 40uS
Aus CGRAM oder DDRAM lesen 1 1 D7 D6 D5 D4 D3 D2 D1 D0 40uS
I/D 1 = Inkrement (um 1)         R/L 1 = Nach rechts verschieben
0 = Dekrement (um 1)             0 = Nach links verschieben
S 1 = Display-Verschiebung ein          DL 1 = 8-Bit-Schnittstelle

0 = Display-Verschiebung aus            0 = 4-Bit-Schnittstelle
D 1 = Display ein                N 1 = Anzeige in zwei Zeilen

0 = Display aus                 0 = Anzeige in einer Zeile
U 1 = Cursor ein                  F 1 = Zeichenformat 5x10 Punkte

0 = Cursor aus                  0 = Zeichenformat 5x7 Punkte
B 1 = Cursor blinken ein           D/C 1 = Display verschieben

0 = Cursor blinken aus              0 = Cursor verschieben

Was ist das Busy-Flag?

Im Vergleich zum Mikrocontroller ist das LCD ein extrem langsames Bauteil. Aus diesem Grund war es notwendig, ein Signal bereitzustellen, das nach der Befehlsausführung anzeigt, dass das Display bereit ist, neue Daten zu empfangen. Dieses Signal, das Busy-Flag genannt, kann von der Leitung D7 gelesen werden. Wenn das BF-Bit gelöscht ist (BF=0), ist das Display bereit, neue Daten zu empfangen.

LCD-Verbindung

Je nachdem, wie viele Leitungen für die Verbindung des LCD mit dem Mikrocontroller verwendet werden, gibt es 8-Bit- und 4-Bit-LCD-Modi. Der entsprechende Modus wird zu Beginn des Betriebs ausgewählt. Dieser Vorgang wird als "Initialisierung" bezeichnet. Der 8-Bit-LCD-Modus verwendet die Ausgänge D0-D7, um Daten wie auf der vorherigen Seite beschrieben zu übertragen. Der Hauptzweck des 4-Bit-LED-Modus besteht darin, wertvolle E/A-Pins des Mikrocontrollers zu sparen. Nur die 4 höherwertigen Bits (D4-D7) werden für die Kommunikation verwendet, andere können unverbunden bleiben. Jedes Datum wird in zwei Schritten an das LCD gesendet: zuerst werden die vier höherwertigen Bits gesendet (normalerweise über die Leitungen D4-D7), dann die vier niederwertigen Bits. Die Initialisierung ermöglicht es dem LCD, die empfangenen Bits richtig zu verknüpfen und zu interpretieren. Daten werden selten vom LCD gelesen (sie werden hauptsächlich vom Mikrocontroller zum LCD übertragen), sodass es oft möglich ist, einen zusätzlichen E/A-Pin zu sparen, indem der R/W-Pin einfach mit Masse verbunden wird. Diese Ersparnis hat ihren Preis. Nachrichten werden normal angezeigt, aber es wird nicht möglich sein, das Busy-Flag zu lesen, da auch das Display nicht gelesen werden kann.

LCD-Verbindung

Es gibt jedoch eine einfache Lösung. Nach dem Senden eines Zeichens oder Befehls ist es wichtig, dem LCD genügend Zeit für seine Arbeit zu geben. Da die Ausführung des langsamsten Befehls etwa 1,64 ms dauert, reicht es aus, etwa 2 ms für das LCD zu warten.

LCD-Initialisierung

Das LCD wird beim Einschalten automatisch gelöscht. Dies dauert etwa 15 ms. Danach ist das Display betriebsbereit. Der Betriebsmodus ist standardmäßig voreingestellt. Das bedeutet:

  1. Display ist gelöscht
  2. Modus
    • DL = 1 Kommunikation über 8-Bit-Schnittstelle
    • N = 0 Nachrichten werden in einer Zeile angezeigt
    • F = 0 Zeichenschrift 5 x 8 Punkte
  3. Display/Cursor ein/aus
    • D = 0 Display aus
    • U = 0 Cursor aus
    • B = 0 Cursor blinken aus
  4. Zeicheneingabe
    • ID = 1 Angezeigte Adressen werden automatisch um 1 erhöht
    • S = 0 Display-Verschiebung aus

Der automatische Reset funktioniert in den meisten Fällen problemlos. In den meisten Fällen, aber nicht immer! Wenn die Versorgungsspannung aus irgendeinem Grund nicht innerhalb von 10 ms den vollen Wert erreicht, beginnt das Display völlig unvorhersehbar zu arbeiten. Wenn die Spannungsversorgung diese Bedingung nicht erfüllen kann oder ein völlig sicherer Betrieb erforderlich ist, wird eine Initialisierung durchgeführt. Die Initialisierung bewirkt unter anderem einen neuen Reset, der das Display in die Lage versetzt, normal zu arbeiten.

Die folgende Abbildung zeigt die Vorgehensweise für die 8-Bit-Initialisierung:

8-Bit-Initialisierung

Es ist kein Fehler!
In diesem Algorithmus wird derselbe Wert dreimal hintereinander gesendet.

Bei der 4-Bit-Initialisierung lautet die Vorgehensweise wie folgt:

4-Bit-Initialisierung

6.3 Beispiele

Das folgende Schema wird in den folgenden Beispielen verwendet:

LED-Verbindungsschema

Neben den für den Betrieb des Mikrocontrollers notwendigen Komponenten wie Oszillator mit Kondensatoren und der einfachsten Reset-Schaltung sind auch mehrere LEDs und ein Taster vorhanden. Diese dienen zur Anzeige des Programmablaufs.

Alle LEDs sind so gepolt, dass sie durch Anlegen eines logisch niedrigen (0) Pegels an den Mikrocontroller-Pin aktiviert werden.

LED-Blinken

Der Zweck dieses Beispiels ist nicht, die Funktionsweise von LEDs zu demonstrieren, sondern die Betriebsgeschwindigkeit des Mikrocontrollers. Um ein sichtbares Blinken zu ermöglichen, muss zwischen den Ein-/Aus-Zuständen der LEDs ausreichend Zeit vergehen. In diesem Beispiel wird die Zeitverzögerung durch den Aufruf einer Unterroutine namens Delay bereitgestellt. Es handelt sich um eine dreifache Schleife, in der das Programm etwa 0,5 Sekunden verweilt und die Werte in den Registern R0, R1 oder R2 dekrementiert. Nach der Rückkehr aus der Unterroutine wird der Pin-Zustand invertiert und der Vorgang wiederholt...

;************************************************************************
;* PROGRAMMNAME : Delay.ASM
;* BESCHREIBUNG: Schaltet LED an Pin P1.0 ein/aus mit Software-Verzögerung
;************************************************************************
;GRUNDLEGENDE DIREKTIVEN
$MOD53
$TITLE(DELAY.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK

DSEG    AT    03FH

STACK_START:    DS    040H
;RESET-VEKTOREN

CSEG     AT    0

JMP      XRESET                  ;Reset-Vektor
ORG      100H
XRESET: MOV     SP,#STACK_START         ;Stack-Pointer definieren

MOV     P1,#0FFh                ;Alle Pins als Eingänge konfigurieren
LOOP:

CPL     P1.0                    ;Pin P1.0 Zustand invertieren

LCALL   Delay                   ;Zeitverzögerung

SJMP    LOOP
Delay:

MOV     R2,#20                  ;500 ms Verzögerung

F02:    MOV     R1,#50                  ;25 ms

F01:    MOV     R0,#230

DJNZ    R0,$

DJNZ    R1,F01

DJNZ    R2,F02
END                                     ;Programmende

Verwendung des Watchdog-Timers

Dieses Beispiel zeigt, wie der Watchdog-Timer nicht verwendet werden sollte. Der Watchdog-Timer ist richtig eingestellt (Zählzeit 1024 ms), aber der Befehl zu seiner Rücksetzung wurde absichtlich weggelassen, sodass dieser Timer immer "gewinnt". Infolgedessen wird der Mikrocontroller zurückgesetzt (Registerinhalte bleiben erhalten), das Programm startet von vorne und der Wert im Register R3 wird um 1 erhöht und dann auf Port P1 kopiert.

Die LEDs zeigen diese Zahl binär an...

;************************************************************************
;* PROGRAMMNAME : WatchDog.ASM
;* BESCHREIBUNG : Nach Watchdog-Reset wird der Wert in Register R3 inkrementiert und binär auf Port P1 angezeigt.
;************************************************************************
;GRUNDLEGENDE DIREKTIVEN

$MOD53

$TITLE(WATCHDOG.ASM)

$PAGEWIDTH(132)

$DEBUG

$OBJECT

$NOPAGING
WMCON     DATA    96H

WDTEN     EQU     00000001B        ; Watchdog-Timer aktiviert

PERIOD    EQU     11000000B        ; Watchdog-Periode auf 1024ms gesetzt
;RESET-VEKTOR

CSEG    AT      0

JMP     XRESET           ; Reset-Vektor
CSEG

ORG     100H
XRESET:   ORL     WMCON,#PERIOD    ; Watchdog-Periode definieren

ORL     WMCON,#WDTEN     ; Watchdog-Timer aktivieren
MOV     A,R3             ; R3 nach Port 1 verschieben

MOV     P1,A

INC     R3               ; Register R3 um 1 erhöhen
LAB:      SJMP    LAB              ; Auf Watchdog-Reset warten
END                      ; Programmende

Timer T0 im Modus 1

Dieses Programm verbringt die meiste Zeit in einer Endlosschleife und wartet darauf, dass Timer T0 einen vollen Zyklus zählt. Wenn dies geschieht, wird ein Interrupt ausgelöst, die Routine TIM0_ISR ausgeführt und eine logische Null (0) auf Port P1 um ein Bit nach rechts geschoben. Dies ist eine weitere Möglichkeit, die Betriebsgeschwindigkeit des Mikrocontrollers zu demonstrieren, da jede Verschiebung bedeutet, dass der Zähler T0 216 Impulse gezählt hat!

;************************************************************************
;* PROGRAMMNAME : Tim0Mod1.ASM
;* BESCHREIBUNG: Rotiert eine "0" auf Port 1 mittels Timer T0 im Modus 1
;************************************************************************
;GRUNDLEGENDE DIREKTIVEN

$MOD53

$TITLE(TIM0MOD1.ASM)

$PAGEWIDTH(132)

$DEBUG

$OBJECT

$NOPAGING
;VARIABLENDEKLARATION
;STACK
DSEG     AT     03FH
STACK_START:     DS     040H
;RESET-VEKTOREN

CSEG      AT 0

JMP       XRESET             ; Reset-Vektor
ORG       00BH

JMP       TIM0_ISR           ; Timer T0 Reset-Vektor


ORG       100H
XRESET: MOV      SP,#STACK_START    ; Stack-Pointer definieren

MOV       TMOD,#01H          ; Modus 1 gewählt

MOV       A,#0FFH

MOV       P1,#0FFH

SETB      TR0                ; Timer T0 gestartet

MOV       IE,#082H           ; Interrupt aktiviert

CLR       C
LOOP1: SJMP      LOOP1              ; Hier verweilen
TIM0_ISR:        RRC     A          ; Akkumulator A mit Übertragsflag rotieren

MOV     P1,A       ; Akkumulatorinhalt nach PORT1

RETI               ; Rückkehr aus Interrupt
END                          ; Programmende

Kapitel 6 : Praktische Beispiele

Einleitung

Dieses Kapitel vermittelt grundlegendes Wissen über die Mikrocontroller-Hardware, das für den praktischen Einsatz erforderlich ist. Sie werden in diesem Abschnitt keine übermäßig komplexen fortgeschrittenen Programme oder ausgefeilten Schaltungsdesigns finden. Stattdessen beweisen die folgenden praktischen Beispiele, dass die eingebettete Programmierung weder ein exklusives Privileg noch eine talentabhängige Fähigkeit ist; es ist einfach der Prozess, modulare Funktionslogik über eine standardisierte Befehlssyntax zusammenzusetzen. Seien Sie versichert, dass Hardware-Design und iterative Entwicklung einem konsistenten Kernablauf folgen: „testen, anpassen, wiederholen“. Natürlich wächst die Projektkomplexität mit der Erfahrung, da dieselben grundlegenden Bausteine von Hobby-Einsteigern und professionellen Architekten zusammengesetzt werden können...

6.1 Grundlegende Hardware-Verdrahtung

Grundlegende Verdrahtung - Stromversorgung

Wie im obigen Schema dargestellt, müssen drei obligatorische Signalbereiche korrekt verdrahtet werden, um einen stabilen Mikrocontroller-Betrieb zu gewährleisten:

  • Geregelte Stromversorgung;
  • Reset-Signal; und
  • Taktsignal.

Es handelt sich um sehr einfache Schaltungen, aber es muss nicht immer so sein. Wenn das Zielgerät zur Steuerung teurer Maschinen oder zur Aufrechterhaltung lebenswichtiger Funktionen eingesetzt wird, wird alles zunehmend komplexer. Für den Anfang reicht diese Lösung jedoch aus...

Stromversorgung

Obwohl dieser Mikrocontroller bei verschiedenen Versorgungsspannungen betrieben werden kann, warum das Murphysche Gesetz testen? Eine 5V-Gleichspannung wird am häufigsten verwendet. Die in der Abbildung gezeigte Schaltung verwendet den kostengünstigen integrierten Dreipol-Positivregler LM7805 und bietet eine hochwertige Spannungsstabilität und ausreichend Strom, um den Mikrocontroller und die Peripherieelektronik normal zu betreiben (ausreichend Strom bedeutet in diesem Fall 1A).

Reset-Signal

Damit der Mikrocontroller ordnungsgemäß arbeiten kann, muss am Reset-Pin RS eine logische 0 (0V) anliegen. Der Taster, der den Reset-Pin RS mit der Versorgungsspannung VCC verbindet, ist nicht erforderlich. Er wird jedoch fast immer bereitgestellt, da er es ermöglicht, den Mikrocontroller bei Problemen sicher in einen normalen Betriebszustand zurückzusetzen. Wenn 5V an diesen Pin angelegt werden, wird der Mikrocontroller zurückgesetzt und das Programm startet von vorne.

Taktsignal

Obwohl der Mikrocontroller einen eingebauten Oszillator hat, kann er nicht ohne zwei externe Kondensatoren und einen Quarzkristall arbeiten, die seinen Betrieb stabilisieren und seine Frequenz (Arbeitsgeschwindigkeit des Mikrocontrollers) bestimmen.

Taktsignal

Natürlich ist diese Lösung nicht immer anwendbar, daher gibt es immer alternative Lösungen. Eine davon besteht darin, das Taktsignal von einer speziellen Quelle über einen Inverter bereitzustellen. Siehe Abbildung links.

6.2 Zusätzliche Komponenten

Unabhängig davon, dass der Mikrocontroller ein Produkt moderner Technologie ist, ist er ohne Anschluss an zusätzliche Komponenten nutzlos. Vereinfacht gesagt bedeutet das Auftreten einer Spannung an seinen Pins nichts, wenn sie nicht zur Durchführung bestimmter Operationen (Ein-/Ausschalten, Verschieben, Anzeigen usw.) verwendet wird.

Schalter und Taster

Es gibt keine einfacheren Bauteile als Schalter und Taster. Dies ist die einfachste Methode, um das Auftreten einer Spannung am Mikrocontroller-Eingangspin zu erkennen.

Schalter und Taster

In der Praxis ist es jedoch nicht so einfach... Es geht um das Kontaktprellen – ein häufiges Problem bei mechanischen Schaltern. Wenn die Kontakte aufeinandertreffen, wirken ihr Impuls und ihre Elastizität zusammen und verursachen ein Prellen. Das Ergebnis ist ein schnell pulsierender elektrischer Strom anstelle eines sauberen Übergangs von Null auf Vollstrom. Dies geschieht hauptsächlich aufgrund von Vibrationen, leichten Unebenheiten und Schmutz zwischen den Kontakten. Dieser Effekt ist bei der alltäglichen Verwendung dieser Komponenten normalerweise nicht wahrnehmbar, da das Prellen zu schnell erfolgt. Mit anderen Worten, der gesamte Vorgang dauert nicht lange (einige Mikro- oder Millisekunden), aber er ist lang genug, um vom Mikrocontroller registriert zu werden. Wenn nur ein Taster als Impulszähler verwendet wird, treten in fast 100 % der Fälle Fehler auf!

RC-Entprellung

Die einfachste Lösung für dieses Problem ist der Anschluss einer einfachen RC-Schaltung, die schnelle Spannungsänderungen unterdrückt. Da die Prellperiode nicht definiert ist, sind die Werte der Komponenten nicht genau festgelegt. In den meisten Fällen wird empfohlen, die in der folgenden Abbildung gezeigten Werte zu verwenden.

Wenn absolute Stabilität erforderlich ist, sollten radikale Maßnahmen ergriffen werden. Der Ausgang der in der Abbildung gezeigten Schaltung (RS-Flipflop) ändert seinen logischen Zustand erst nach der Erkennung des ersten durch Kontaktprellen ausgelösten Impulses. Diese Lösung ist teuer (SPDT-Schalter), aber effizient, das Problem ist definitiv gelöst. Da kein Kondensator verwendet wird, können auf diese Weise auch sehr kurze Impulse erfasst werden.

Flipflop-Entprellung

Zusätzlich zu diesen Hardware-Lösungen gibt es auch eine einfache Software-Lösung. Wenn ein Programm den Zustand eines Eingangspins testet und eine Änderung erkennt, sollte die Prüfung nach einer bestimmten Verzögerung erneut durchgeführt werden. Wenn die Änderung bestätigt wird, bedeutet dies, dass ein Schalter oder Taster seine Position geändert hat. Die Vorteile einer solchen Lösung sind offensichtlich: Sie ist kostenlos, die Auswirkungen von Störungen werden beseitigt und sie kann auch bei Kontakten geringerer Qualität angewendet werden. Der Nachteil ist derselbe wie bei der Verwendung eines RC-Filters, d. h. Impulse, die kürzer als die Programmverzögerung sind, können nicht erfasst werden.

Optokoppler

Optokoppler

Ein Optokoppler ist ein Bauteil, das üblicherweise zur galvanischen Trennung der Mikrocontroller-Elektronik von gefährlichen Strömen oder Spannungen in seiner Umgebung verwendet wird. Optokoppler haben normalerweise eine, zwei oder vier Lichtquellen (LED-Dioden) auf ihrer Eingangsseite, während sich auf ihrer Ausgangsseite, den Dioden gegenüber, die gleiche Anzahl von lichtempfindlichen Elementen (Fototransistoren, Fotothyristoren oder Fototriacs) befindet. Der Punkt ist, dass ein Optokoppler einen kurzen optischen Übertragungsweg verwendet, um ein Signal zwischen den Schaltungselementen zu übertragen, während er sie elektrisch isoliert hält. Diese Isolierung macht nur Sinn, wenn Dioden und lichtempfindliche Elemente getrennt mit Strom versorgt werden. Auf diese Weise werden der Mikrocontroller und die teure Zusatzelektronik vollständig vor Hochspannung und Störungen geschützt, die in der Praxis die häufigste Ursache für die Zerstörung, Beschädigung oder instabile Funktion elektronischer Geräte sind. Die am häufigsten verwendeten Optokoppler sind solche mit Fototransistoren an ihren Ausgängen. Bei Verwendung eines Optokopplers mit interner Basis-Pin-6-Verbindung (es gibt auch Optokoppler ohne diese) kann die Basis offen gelassen werden. Eine optionale Verbindung, die die Auswirkungen von Störungen durch Unterdrückung sehr kurzer Impulse verringert, ist in der Abbildung durch die unterbrochene Linie dargestellt.

Relais

Relais

Ein Relais ist ein elektrischer Schalter, der unter der Steuerung eines anderen elektrischen Stromkreises öffnet und schließt. Er wird daher an die Ausgangspins des Mikrocontrollers angeschlossen und zum Ein- und Ausschalten von Hochleistungsgeräten wie Motoren, Transformatoren, Heizungen, Lampen, Antennensystemen usw. verwendet. Diese werden fast immer von den empfindlichen Komponenten der Platine entfernt platziert. Es gibt verschiedene Arten von Relais, aber alle arbeiten nach dem gleichen Prinzip. Wenn ein Strom durch die Spule fließt, wird das Relais von einem Elektromagneten betätigt, um einen oder mehrere Kontaktsätze zu öffnen oder zu schließen. Ähnlich wie bei Optokopplern gibt es keine galvanische Verbindung (elektrischer Kontakt) zwischen Eingangs- und Ausgangskreisen. Relais benötigen normalerweise sowohl eine höhere Spannung als auch einen höheren Strom, um zu funktionieren, aber es gibt auch Miniaturrelais, die mit einem niedrigen Strom direkt von einem Mikrocontroller-Pin aktiviert werden können.

Die Abbildung zeigt die für den 8051-Mikrocontroller spezifische Lösung. Hier wird ein Darlington-Transistor verwendet, um Relais aufgrund seiner hohen Stromverstärkung zu aktivieren. Dies entspricht nicht den "Regeln", ist jedoch erforderlich, wenn eine Aktivierung mit logisch 1 verwendet wird, da der Ausgangsstrom dann sehr niedrig ist (Pin verhält sich als Eingang).

Grundlegende Verdrahtung des Mikrocontrollers - Relais

Um das Auftreten einer durch plötzliches Abschalten des Spulenstroms verursachten hohen Selbstinduktionsspannung zu verhindern, wird eine antiparallele Diode parallel zur Spule geschaltet. Der Zweck dieser Diode besteht darin, die Spannungsspitze zu "begrenzen".

Leuchtdiode (LED)

Leuchtdioden sind Bauelemente zur optischen Signalgebung in der Elektronik. Sie werden in verschiedenen Formen, Farben und Größen hergestellt. Aufgrund ihres niedrigen Preises, ihres geringen Stromverbrauchs und ihrer einfachen Verwendung haben sie andere Lichtquellen, insbesondere Glühlampen, fast vollständig verdrängt. Sie verhalten sich ähnlich wie normale Dioden, mit dem Unterschied, dass sie Licht emittieren, wenn Strom durch sie fließt.

Leuchtdiode (LED)

Es ist wichtig, ihren Strom zu begrenzen, da sie sonst dauerhaft zerstört werden. Aus diesem Grund muss ein Widerstand in Reihe zu einer LED geschaltet werden. Um den Wert dieses Widerstands zu bestimmen, muss die Durchlassspannung der Diode bekannt sein, die davon abhängt, aus welchem Material die Diode besteht und welche Farbe sie hat. Typische Werte der am häufigsten verwendeten Dioden sind in der folgenden Tabelle aufgeführt. Wie zu sehen, gibt es drei Haupttypen von LEDs. Standard-LEDs erreichen ihre volle Helligkeit bei einem Strom von 20 mA. Niedrigstrom-Dioden erreichen ihre volle Helligkeit bei einem zehnmal niedrigeren Strom, während Super-Bright-Dioden ein intensiveres Licht als Standard-LEDs erzeugen.

Farbe Typ Typischer Strom Id (mA) Maximaler Strom If (mA) Durchlassspannung Ud (V)
Infrarot - 30 50 1.4
Rot Standard 20 30 1.7
Rot Super Hell 20 30 1.85
Rot Niedrigstrom 2 30 1.7
Orange - 10 30 2.0
Grün Niedrigstrom 2 20 2.1
Gelb - 20 30 2.1
Blau - 20 30 4.5
Weiß - 25 35 4.4
Niedrigstrom-LED

Da der 8051-Mikrocontroller nur einen geringen Ausgangsstrom liefern kann und seine Pins als Ausgänge konfiguriert sind, wenn die an ihnen anliegende Spannung 0V beträgt, erfolgt der direkte Anschluss an LEDs wie in der Abbildung rechts gezeigt (Niedrigstrom-LED, Kathode ist mit dem Ausgangspin verbunden).

LED-Anzeigen

Eine LED-Anzeige ist im Grunde nichts anderes als mehrere LEDs, die in einem Kunststoffgehäuse vergossen sind. Es gibt viele Arten von Anzeigen, die aus mehreren Dutzend eingebauten Dioden bestehen und verschiedene Symbole anzeigen können.

LED-Anzeigen

Am häufigsten wird die sogenannte 7-Segment-Anzeige verwendet. Sie besteht aus 8 LEDs, wobei 7 Segmente rechteckig für die Symbolanzeige angeordnet sind und ein zusätzliches Segment für die Anzeige des Dezimalpunkts vorhanden ist. Um die Verbindung zu vereinfachen, sind die Anoden und Kathoden aller Dioden mit dem gemeinsamen Pin verbunden, sodass es gemeinsame Anoden- und gemeinsame Kathodenanzeigen gibt. Die Segmente sind mit den Buchstaben A bis G sowie dp gekennzeichnet, wie in der Abbildung links gezeigt. Bei der Verbindung wird jede Diode separat behandelt, was bedeutet, dass jede ihren eigenen Strombegrenzungswiderstand benötigt.

Anzeigen, die mit dem Mikrocontroller verbunden sind, belegen normalerweise eine große Anzahl wertvoller E/A-Pins, was ein großes Problem darstellen kann, insbesondere wenn mehrstellige Zahlen angezeigt werden sollen. Das Problem ist mehr als offensichtlich, wenn beispielsweise zwei 6-stellige Zahlen angezeigt werden sollen (eine einfache Rechnung zeigt, dass in diesem Fall 96 Ausgangspins benötigt werden). Die Lösung für dieses Problem heißt MULTIPLEXING. Dabei wird eine optische Täuschung erzeugt, die auf dem gleichen Funktionsprinzip wie eine Filmkamera basiert. Es ist immer nur eine Ziffer aktiv, aber sie ändert ihren Zustand so schnell, dass der Eindruck entsteht, dass alle Ziffern einer Zahl gleichzeitig aktiv sind.

Grundlegende Verdrahtung des Mikrocontrollers - LED-Anzeigen

Hier ist eine Erklärung der obigen Abbildung. Zuerst wird ein Byte, das die Einer darstellt, an einen Mikrocontroller-Port angelegt und gleichzeitig ein Transistor T1 aktiviert. Nach einer Weile wird T1 ausgeschaltet, ein Byte, das die Zehner darstellt, wird an einen Port angelegt und ein Transistor T2 aktiviert. Dieser Vorgang wird für alle Ziffern und entsprechenden Transistoren zyklisch mit hoher Geschwindigkeit wiederholt.

Die Tatsache, dass der Mikrocontroller nur eine Art Miniaturcomputer ist, der nur die Sprache der Nullen und Einsen versteht, zeigt sich vollständig bei der Anzeige einer Ziffer. Der Mikrocontroller weiß nämlich nicht, was Einer, Zehner oder Hunderter sind, noch wie die zehn Ziffern aussehen, die wir gewohnt sind. Daher muss jede anzuzeigende Zahl wie folgt vorbereitet werden:

Zunächst muss eine mehrstellige Zahl in Einer, Zehner usw. in einer bestimmten Unterroutine zerlegt werden. Dann muss jede dieser Ziffern in speziellen Bytes gespeichert werden. Die Ziffern erhalten ein bekanntes Format durch eine "Maskierung". Mit anderen Worten, das Binärformat jeder Ziffer wird in einer einfachen Unterroutine durch eine andere Bitkombination ersetzt. Beispielsweise wird die Ziffer 8 (0000 1000) durch die Binärzahl 0111 111 ersetzt, um alle LEDs, die die Ziffer 8 anzeigen, zu aktivieren. Die einzige Diode, die in diesem Fall inaktiv bleibt, ist für den Dezimalpunkt reserviert. Wenn ein Mikrocontroller-Port so mit der Anzeige verbunden ist, dass Bit 0 das Segment "a" aktiviert, Bit 1 das Segment "b", Bit 2 das Segment "c" usw., dann zeigt die folgende Tabelle die "Maske" für jede Ziffer.

Maskierung von LED-Anzeigen
Anzuzeigende Ziffer Anzeigesegmente
dp a b c d e f g
0 1 0 0 0 0 0 0 1
1 1 0 0 1 1 1 1 1
2 1 0 0 1 0 0 1 0
3 1 0 0 0 0 1 1 0
4 1 1 0 0 1 1 0 0
5 1 0 1 0 0 1 0 0
6 1 0 1 0 0 0 0 0
7 1 0 0 0 1 1 1 1
8 1 0 0 0 0 0 0 0
9 1 0 0 0 0 1 0 0

Zusätzlich zu den Ziffern 0 bis 9 können durch entsprechende Maskierung auch einige Buchstaben des Alphabets - A, C, E, J, F, U, H, L, b, c, d, o, r, t - angezeigt werden.
Wenn gemeinsame Kathodenanzeigen verwendet werden, sollten alle Einsen in der Tabelle durch Nullen ersetzt werden und umgekehrt. Außerdem sollten NPN-Transistoren als Treiber verwendet werden.

Flüssigkristallanzeigen (LCD)

Ein LCD-Display ist speziell für den Einsatz mit Mikrocontrollern hergestellt, was bedeutet, dass es nicht von standardmäßigen IC-Schaltungen aktiviert werden kann. Es wird zur Anzeige verschiedener Nachrichten auf einem Miniatur-Flüssigkristalldisplay verwendet.

Flüssigkristallanzeigen (LCD)

Das hier beschriebene Modell wird aufgrund seines niedrigen Preises und seiner großen Fähigkeiten in der Praxis am häufigsten verwendet. Es basiert auf dem Mikrocontroller HD44780 (Hitachi) und kann Nachrichten in zwei Zeilen mit jeweils 16 Zeichen anzeigen. Es zeigt alle Buchstaben des Alphabets, griechische Buchstaben, Satzzeichen, mathematische Symbole usw. an. Darüber hinaus ist es möglich, benutzerdefinierte Symbole anzuzeigen. Weitere nützliche Funktionen sind automatische Nachrichtenverschiebung (links und rechts), Cursor-Anzeige, LED-Hintergrundbeleuchtung usw.

LCD-Pins

Entlang einer Seite einer kleinen Leiterplatte befinden sich Pins. Diese werden zum Anschluss an den Mikrocontroller verwendet. Es gibt insgesamt 14 Pins mit Nummern (16, wenn eine Hintergrundbeleuchtung vorhanden ist). Ihre Funktion ist in der folgenden Tabelle beschrieben:

Funktion Pin-Nr. Name Logikzustand Beschreibung
Masse 1 Vss - 0V
Stromversorgung 2 Vdd - +5V
Kontrast 3 Vee - 0 - Vdd
Betriebssteuerung 4 RS 0
1
D0-D7 werden als Befehle interpretiert
D0-D7 werden als Daten interpretiert
5 R/W 0
1
Daten schreiben (vom Controller zum LCD)
Daten lesen (vom LCD zum Controller)
6 E 0
1
Von 1 auf 0
Zugriff auf LCD deaktiviert
Normalbetrieb
Daten/Befehle werden an LCD übertragen
Daten / Befehle 7 D0 0/1 Bit 0 LSB
8 D1 0/1 Bit 1
9 D2 0/1 Bit 2
10 D3 0/1 Bit 3
11 D4 0/1 Bit 4
12 D5 0/1 Bit 5
13 D6 0/1 Bit 6
14 D7 0/1 Bit 7 MSB

LCD-Bildschirm

LCD-Bildschirmpixel

Ein LCD-Bildschirm besteht aus zwei Zeilen mit jeweils 16 Zeichen. Jedes Zeichen besteht aus einer 5x8- oder 5x11-Punktmatrix. Dieses Buch behandelt das am häufigsten verwendete Display, d. h. das 5x8-Zeichen-Display.

Der Displaykontrast hängt von der Versorgungsspannung und davon ab, ob Nachrichten in einer oder zwei Zeilen angezeigt werden. Aus diesem Grund wird am Pin Vee eine variable Spannung 0-Vdd angelegt. Normalerweise wird dazu ein Trimmer-Potentiometer verwendet. Einige LCD-Displays haben eine eingebaute Hintergrundbeleuchtung (blaue oder grüne LEDs). Wenn sie während des Betriebs verwendet wird, sollte ein Strombegrenzungswiderstand in Reihe mit einem der Pins für die Hintergrundbeleuchtung geschaltet werden (ähnlich wie bei LEDs).

LCD-Hintergrundbeleuchtung

Wenn keine Zeichen angezeigt werden oder alle schwach erscheinen, wenn das Display eingeschaltet ist, sollte als erstes der Potentiometer für die Kontrastregelung überprüft werden. Ist er richtig eingestellt? Gleiches gilt, wenn der Betriebsmodus geändert wurde (Schreiben in einer oder zwei Zeilen).

LCD-Speicher

Das LCD-Display enthält drei Speicherblöcke:

  • DDRAM Display Data RAM;
  • CGRAM Character Generator RAM; und
  • CGROM Character Generator ROM.

DDRAM-Speicher

Der DDRAM-Speicher wird zum Speichern der anzuzeigenden Zeichen verwendet. Die Größe dieses Speichers reicht für 80 Zeichen. Einige Speicherstellen sind direkt mit den Zeichen auf dem Display verbunden.

DDRAM-Speicher

Er funktioniert ganz einfach: Es reicht aus, das Display so zu konfigurieren, dass die Adressen automatisch erhöht werden (nach rechts verschieben) und die Startadresse für die anzuzeigende Nachricht festgelegt wird (z. B. 00 hex).

Danach werden alle über die Leitungen D0-D7 gesendeten Zeichen in dem gewohnten Nachrichtenformat von links nach rechts angezeigt. In diesem Fall beginnt die Anzeige im ersten Feld der ersten Zeile, da die Adresse 00 hex ist. Wenn mehr als 16 Zeichen gesendet werden, werden alle gespeichert, aber nur die ersten sechzehn Zeichen sind sichtbar. Um die restlichen anzuzeigen, muss ein Verschiebebefehl verwendet werden. Praktisch gesehen erscheint alles so, als ob das LCD-Display ein "Fenster" ist, das sich über Speicherstellen mit verschiedenen Zeichen von links nach rechts bewegt. So wird der Effekt einer "bewegten" Nachricht auf dem Bildschirm erzeugt.

Wenn der Cursor eingeschaltet ist, erscheint er an der Stelle, die gerade adressiert wird. Mit anderen Worten: Wenn ein Zeichen an der Cursorposition erscheint, bewegt es sich automatisch zur nächsten adressierten Stelle.
Da es sich um eine Art RAM-Speicher handelt, können Daten geschrieben und gelesen werden, aber ihr Inhalt geht beim Ausschalten der Stromversorgung unwiederbringlich verloren.

CGROM-Speicher

Der CGROM-Speicher enthält die Standard-Zeichentabelle mit allen Zeichen, die auf dem Bildschirm angezeigt werden können. Jedes Zeichen ist einem Speicherplatz zugeordnet.

CGROM-Speicher

Die Adressen der CGROM-Speicherplätze entsprechen den ASCII-Zeichen. Wenn das laufende Programm auf einen Befehl "sende Zeichen P an Port" stößt, erscheint der Binärwert 0101 0000 am Port. Dieser Wert ist das ASCII-Äquivalent für das Zeichen P. Er wird dann an das LCD geschrieben, was zur Anzeige des Symbols von der CGROM-Stelle 0101 0000 führt. Mit anderen Worten, das Zeichen "P" wird angezeigt. Dies gilt für alle Buchstaben des Alphabets (Groß- und Kleinbuchstaben), aber nicht für Zahlen.

Wie auf der vorherigen "Karte" zu sehen, sind die Adressen aller Ziffern um 48 gegenüber ihrem Wert nach oben verschoben (Ziffer 0 Adresse 48, Ziffer 1 Adresse 49, Ziffer 2 Adresse 50 usw.). Daher muss jede Ziffer vor dem Senden an das LCD um die Dezimalzahl 48 erhöht werden, um sie korrekt anzuzeigen.

Von ihrer Entstehung bis heute können Computer nur Zahlen erkennen, aber keine Buchstaben. Das bedeutet, dass alle Daten, die ein Computer mit einem Peripheriegerät austauscht, ein binäres Format haben, auch wenn sie vom Menschen als Buchstaben erkannt werden (die Tastatur ist ein hervorragendes Beispiel). Jedes Zeichen entspricht einer eindeutigen Kombination von Nullen und Einsen. ASCII ist eine Zeichencodierung, die auf dem englischen Alphabet basiert. Der ASCII-Code legt die Entsprechung zwischen standardmäßigen Zeichensymbolen und ihren numerischen Äquivalenten fest.

CGRAM-Speicher

Neben Standardzeichen kann das LCD-Display auch vom Benutzer selbst definierte Symbole anzeigen. Es kann jedes Symbol in der Größe von 5x8 Pixeln sein. Ein RAM-Speicher namens CGRAM in der Größe von 64 Bytes ermöglicht dies.

Die Speicherregister sind 8 Bit breit, aber nur die 5 unteren Bits werden verwendet. Eine logische Eins (1) in jedem Register stellt einen leuchtenden Punkt dar, während 8 zusammengehörige Stellen ein Zeichen darstellen. Dies wird am besten in der folgenden Abbildung veranschaulicht:

CGRAM-Speicher

Symbole werden normalerweise zu Beginn des Programms definiert, indem einfach Nullen und Einsen in die CGRAM-Register geschrieben werden, um die gewünschten Formen zu erzeugen. Um sie anzuzeigen, reicht es aus, ihre Adresse anzugeben. Beachten Sie die erste Spalte in der CGROM-Zeichentabelle. Sie enthält keine RAM-Speicheradressen, sondern die hier diskutierten Symbole. In diesem Beispiel bedeutet "Anzeige 0" - Anzeige "č", "Anzeige 1" - Anzeige "ž" usw.

LCD-Grundbefehle

Alle über die Ausgänge D0-D7 an das LCD übertragenen Daten werden als Befehl oder als Daten interpretiert, was vom logischen Zustand des Pins RS abhängt:

RS = 1 - Bits D0-D7 sind Adressen der anzuzeigenden Zeichen. Der LCD-Prozessor adressiert ein Zeichen aus der Zeichentabelle und zeigt es an. Die DDRAM-Adresse gibt die Stelle an, an der das Zeichen angezeigt werden soll. Diese Adresse wird vor der Übertragung des Zeichens definiert, oder die Adresse des zuvor übertragenen Zeichens wird automatisch erhöht.

RS = 0 - Bits D0-D7 sind Befehle, die den Anzeigemodus festlegen. Die vom LCD erkannten Befehle sind in der folgenden Tabelle aufgeführt:

Befehl RS RW D7 D6 D5 D4 D3 D2 D1 D0 Ausführungszeit
Display löschen 0 0 0 0 0 0 0 0 0 1 1.64mS
Cursor nach Hause 0 0 0 0 0 0 0 0 1 x 1.64mS
Eingabemodus festlegen 0 0 0 0 0 0 0 1 I/D S 40uS
Display Ein/Aus-Steuerung 0 0 0 0 0 0 1 D U B 40uS
Cursor/Display-Verschiebung 0 0 0 0 0 1 D/C R/L x x 40uS
Funktion festlegen 0 0 0 0 1 DL N F x x 40uS
CGRAM-Adresse festlegen 0 0 0 1 CGRAM-Adresse 40uS
DDRAM-Adresse festlegen 0 0 1 DDRAM-Adresse 40uS
"BUSY"-Flag (BF) lesen 0 1 BF DDRAM-Adresse -
In CGRAM oder DDRAM schreiben 1 0 D7 D6 D5 D4 D3 D2 D1 D0 40uS
Aus CGRAM oder DDRAM lesen 1 1 D7 D6 D5 D4 D3 D2 D1 D0 40uS
I/D 1 = Inkrement (um 1)         R/L 1 = Nach rechts verschieben
0 = Dekrement (um 1)             0 = Nach links verschieben
S 1 = Display-Verschiebung ein          DL 1 = 8-Bit-Schnittstelle

0 = Display-Verschiebung aus            0 = 4-Bit-Schnittstelle
D 1 = Display ein                N 1 = Anzeige in zwei Zeilen

0 = Display aus                 0 = Anzeige in einer Zeile
U 1 = Cursor ein                  F 1 = Zeichenformat 5x10 Punkte

0 = Cursor aus                  0 = Zeichenformat 5x7 Punkte
B 1 = Cursor blinken ein           D/C 1 = Display verschieben

0 = Cursor blinken aus              0 = Cursor verschieben

Was ist das Busy-Flag?

Im Vergleich zum Mikrocontroller ist das LCD ein extrem langsames Bauteil. Aus diesem Grund war es notwendig, ein Signal bereitzustellen, das nach der Befehlsausführung anzeigt, dass das Display bereit ist, neue Daten zu empfangen. Dieses Signal, das Busy-Flag genannt, kann von der Leitung D7 gelesen werden. Wenn das BF-Bit gelöscht ist (BF=0), ist das Display bereit, neue Daten zu empfangen.

LCD-Verbindung

Je nachdem, wie viele Leitungen für die Verbindung des LCD mit dem Mikrocontroller verwendet werden, gibt es 8-Bit- und 4-Bit-LCD-Modi. Der entsprechende Modus wird zu Beginn des Betriebs ausgewählt. Dieser Vorgang wird als "Initialisierung" bezeichnet. Der 8-Bit-LCD-Modus verwendet die Ausgänge D0-D7, um Daten wie auf der vorherigen Seite beschrieben zu übertragen. Der Hauptzweck des 4-Bit-LED-Modus besteht darin, wertvolle E/A-Pins des Mikrocontrollers zu sparen. Nur die 4 höherwertigen Bits (D4-D7) werden für die Kommunikation verwendet, andere können unverbunden bleiben. Jedes Datum wird in zwei Schritten an das LCD gesendet: zuerst werden die vier höherwertigen Bits gesendet (normalerweise über die Leitungen D4-D7), dann die vier niederwertigen Bits. Die Initialisierung ermöglicht es dem LCD, die empfangenen Bits richtig zu verknüpfen und zu interpretieren. Daten werden selten vom LCD gelesen (sie werden hauptsächlich vom Mikrocontroller zum LCD übertragen), sodass es oft möglich ist, einen zusätzlichen E/A-Pin zu sparen, indem der R/W-Pin einfach mit Masse verbunden wird. Diese Ersparnis hat ihren Preis. Nachrichten werden normal angezeigt, aber es wird nicht möglich sein, das Busy-Flag zu lesen, da auch das Display nicht gelesen werden kann.

LCD-Verbindung

Es gibt jedoch eine einfache Lösung. Nach dem Senden eines Zeichens oder Befehls ist es wichtig, dem LCD genügend Zeit für seine Arbeit zu geben. Da die Ausführung des langsamsten Befehls etwa 1,64 ms dauert, reicht es aus, etwa 2 ms für das LCD zu warten.

LCD-Initialisierung

Das LCD wird beim Einschalten automatisch gelöscht. Dies dauert etwa 15 ms. Danach ist das Display betriebsbereit. Der Betriebsmodus ist standardmäßig voreingestellt. Das bedeutet:

  1. Display ist gelöscht
  2. Modus
    • DL = 1 Kommunikation über 8-Bit-Schnittstelle
    • N = 0 Nachrichten werden in einer Zeile angezeigt
    • F = 0 Zeichenschrift 5 x 8 Punkte
  3. Display/Cursor ein/aus
    • D = 0 Display aus
    • U = 0 Cursor aus
    • B = 0 Cursor blinken aus
  4. Zeicheneingabe
    • ID = 1 Angezeigte Adressen werden automatisch um 1 erhöht
    • S = 0 Display-Verschiebung aus

Der automatische Reset funktioniert in den meisten Fällen problemlos. In den meisten Fällen, aber nicht immer! Wenn die Versorgungsspannung aus irgendeinem Grund nicht innerhalb von 10 ms den vollen Wert erreicht, beginnt das Display völlig unvorhersehbar zu arbeiten. Wenn die Spannungsversorgung diese Bedingung nicht erfüllen kann oder ein völlig sicherer Betrieb erforderlich ist, wird eine Initialisierung durchgeführt. Die Initialisierung bewirkt unter anderem einen neuen Reset, der das Display in die Lage versetzt, normal zu arbeiten.

Die folgende Abbildung zeigt die Vorgehensweise für die 8-Bit-Initialisierung:

8-Bit-Initialisierung

Es ist kein Fehler!
In diesem Algorithmus wird derselbe Wert dreimal hintereinander gesendet.

Bei der 4-Bit-Initialisierung lautet die Vorgehensweise wie folgt:

4-Bit-Initialisierung

6.3 Beispiele

Das folgende Schema wird in den folgenden Beispielen verwendet:

LED-Verbindungsschema

Neben den für den Betrieb des Mikrocontrollers notwendigen Komponenten wie Oszillator mit Kondensatoren und der einfachsten Reset-Schaltung sind auch mehrere LEDs und ein Taster vorhanden. Diese dienen zur Anzeige des Programmablaufs.

Alle LEDs sind so gepolt, dass sie durch Anlegen eines logisch niedrigen (0) Pegels an den Mikrocontroller-Pin aktiviert werden.

LED-Blinken

Der Zweck dieses Beispiels ist nicht, die Funktionsweise von LEDs zu demonstrieren, sondern die Betriebsgeschwindigkeit des Mikrocontrollers. Um ein sichtbares Blinken zu ermöglichen, muss zwischen den Ein-/Aus-Zuständen der LEDs ausreichend Zeit vergehen. In diesem Beispiel wird die Zeitverzögerung durch den Aufruf einer Unterroutine namens Delay bereitgestellt. Es handelt sich um eine dreifache Schleife, in der das Programm etwa 0,5 Sekunden verweilt und die Werte in den Registern R0, R1 oder R2 dekrementiert. Nach der Rückkehr aus der Unterroutine wird der Pin-Zustand invertiert und der Vorgang wiederholt...

;************************************************************************
;* PROGRAMMNAME : Delay.ASM
;* BESCHREIBUNG: Schaltet LED an Pin P1.0 ein/aus mit Software-Verzögerung
;************************************************************************
;GRUNDLEGENDE DIREKTIVEN
$MOD53
$TITLE(DELAY.ASM)
$PAGEWIDTH(132)
$DEBUG
$OBJECT
$NOPAGING
;STACK

DSEG    AT    03FH

STACK_START:    DS    040H
;RESET-VEKTOREN

CSEG     AT    0

JMP      XRESET                  ;Reset-Vektor
ORG      100H
XRESET: MOV     SP,#STACK_START         ;Stack-Pointer definieren

MOV     P1,#0FFh                ;Alle Pins als Eingänge konfigurieren
LOOP:

CPL     P1.0                    ;Pin P1.0 Zustand invertieren

LCALL   Delay                   ;Zeitverzögerung

SJMP    LOOP
Delay:

MOV     R2,#20                  ;500 ms Verzögerung

F02:    MOV     R1,#50                  ;25 ms

F01:    MOV     R0,#230

DJNZ    R0,$

DJNZ    R1,F01

DJNZ    R2,F02
END                                     ;Programmende

Verwendung des Watchdog-Timers

Dieses Beispiel zeigt, wie der Watchdog-Timer nicht verwendet werden sollte. Der Watchdog-Timer ist richtig eingestellt (Zählzeit 1024 ms), aber der Befehl zu seiner Rücksetzung wurde absichtlich weggelassen, sodass dieser Timer immer "gewinnt". Infolgedessen wird der Mikrocontroller zurückgesetzt (Registerinhalte bleiben erhalten), das Programm startet von vorne und der Wert im Register R3 wird um 1 erhöht und dann auf Port P1 kopiert.

Die LEDs zeigen diese Zahl binär an...

;************************************************************************
;* PROGRAMMNAME : WatchDog.ASM
;* BESCHREIBUNG : Nach Watchdog-Reset wird der Wert in Register R3 inkrementiert und binär auf Port P1 angezeigt.
;************************************************************************
;GRUNDLEGENDE DIREKTIVEN

$MOD53

$TITLE(WATCHDOG.ASM)

$PAGEWIDTH(132)

$DEBUG

$OBJECT

$NOPAGING
WMCON     DATA    96H

WDTEN     EQU     00000001B        ; Watchdog-Timer aktiviert

PERIOD    EQU     11000000B        ; Watchdog-Periode auf 1024ms gesetzt
;RESET-VEKTOR

CSEG    AT      0

JMP     XRESET           ; Reset-Vektor
CSEG

ORG     100H
XRESET:   ORL     WMCON,#PERIOD    ; Watchdog-Periode definieren

ORL     WMCON,#WDTEN     ; Watchdog-Timer aktivieren
MOV     A,R3             ; R3 nach Port 1 verschieben

MOV     P1,A

INC     R3               ; Register R3 um 1 erhöhen
LAB:      SJMP    LAB              ; Auf Watchdog-Reset warten
END                      ; Programmende

Timer T0 im Modus 1

Dieses Programm verbringt die meiste Zeit in einer Endlosschleife und wartet darauf, dass Timer T0 einen vollen Zyklus zählt. Wenn dies geschieht, wird ein Interrupt ausgelöst, die Routine TIM0_ISR ausgeführt und eine logische Null (0) auf Port P1 um ein Bit nach rechts geschoben. Dies ist eine weitere Möglichkeit, die Betriebsgeschwindigkeit des Mikrocontrollers zu demonstrieren, da jede Verschiebung bedeutet, dass der Zähler T0 216 Impulse gezählt hat!

;************************************************************************
;* PROGRAMMNAME : Tim0Mod1.ASM
;* BESCHREIBUNG: Rotiert eine "0" auf Port 1 mittels Timer T0 im Modus 1
;************************************************************************
;GRUNDLEGENDE DIREKTIVEN

$MOD53

$TITLE(TIM0MOD1.ASM)

$PAGEWIDTH(132)

$DEBUG

$OBJECT

$NOPAGING
;VARIABLENDEKLARATION
;STACK
DSEG     AT     03FH
STACK_START:     DS     040H
;RESET-VEKTOREN

CSEG      AT 0

JMP       XRESET             ; Reset-Vektor
ORG       00BH

JMP       TIM0_ISR           ; Timer T0 Reset-Vektor


ORG       100H
XRESET: MOV      SP,#STACK_START    ; Stack-Pointer definieren

MOV       TMOD,#01H          ; Modus 1 gewählt

MOV       A,#0FFH

MOV       P1,#0FFH

SETB      TR0                ; Timer T0 gestartet

MOV       IE,#082H           ; Interrupt aktiviert

CLR       C
LOOP1: SJMP      LOOP1              ; Hier verweilen
TIM0_ISR:        RRC     A          ; Akkumulator A mit Übertragsflag rotieren

MOV     P1,A       ; Akkumulatorinhalt nach PORT1

RETI               ; Rückkehr aus Interrupt
END                          ; Programmende
  • Mikatech SyncMOS 8051 MCU Reverse-Engineering-Liste:
  • F29Cxx-Serie Hack Mikrocontrollerschutz: F29C31004T F29C31004B F29C31400TF29LC51002F29LC51001F29LC51000 F29C51004T F29C51002T F29C51001T F29C51000T F29C51000B F29C51004T F29C51004B F29C51002T F29C51002B F29C51001T F29C51001BF29C61400T ...

    S29Cxx-Serie Hack Controller-Firmwareschutz: S29C31001B S29C31001T S29C31002B S29C31002T S29C31004B S29C31004T S29C51001B S29C51001T S29C51002B S29C51002T S29C51004B S29C51004T ...

    MSUxx-Serie Auslesen Mikrocontrollerschutz: MSU1958 MSU2952 MSU2964 MSU2958 ...

    SM29xx-Serie Hack Controller-Lockbitschutz: SM2951 SM2952 SM2954 SM2958 SM2964 SM2965 ...

    SM59xx-Serie Auslesen Mikrocontroller-Lockbitschutz: SM59064 SM59128C SM59128L SM5912C SM5912L SM5916C SM59164 SM5916L SM59264 SM5964 SM5964A SM5964AC SM5964AL SM5964C SM5964D0 SM5964D0A SM5964D1A SM59D02G2C SM59D02G2L SM59D03G2C SM59D03G2L SM59D04G2C SM59D04G2L SM59R08A2 ...

    SM59xx-Serie Hack Mikrocontrollerschutz: SM7908 SM79108 SM79164 SM79164L SM79164V SM7932 SM7964 ...

    SM59xx-Serie Hack Controller-Lockbitschutz: SM894051 SM8951 SM89516 SM89516A SM89516AL SM89516B SM89516BL SM89516L SM8951A SM8951AL SM8951B SM8951BL SM8951L SM8952 SM8952A SM8952AL SM8952B SM8952BL SM8952L SM8954 SM8954A SM8954AL SM8954B SM8954BL SM8954L SM8958 SM8958A SM8958AL SM8958B SM8958BL SM8958L SM89S16R1C SM89T04R1C SM89T04R1L SM89T08R1C SM89T08R1L SM89T16R1C SM89T16R1L ..

Allgemeine Fragen zur Mikrocontroller-Firmware-Extraktion


  • Ist es sicher, eine Zahlung an MikaTech zu senden?

    Wenn MikaTech ein schlechtes Unternehmen wäre, könnten Sie im Internet über die 28-jährige Geschichte hinweg tonnenweise schlechte Bewertungen über seinen Service finden

    Die Antwort lautet also JA! Wir sind gute Leute.

    Warum Mikatech wählen, bitte klicken Sie hier, um es herauszufinden


  • Kann Mikatech ICs knacken, die nicht auf dieser Site aufgeführt sind?

    Verschiedene Chip-Hersteller haben unterschiedliche Teilenummern, aber der innere Kern des Chips kann mit derselben Technologie hergestellt werden. Es wäre völlig unmöglich, alle Teilenummern aufzulisten, auf die unsere Technologie anwendbar ist, wie MYSON, STK, FEELING, ANALOG, FUJITSU, NOVATEK, LG/HYNDAI.

    Außerdem gewinnen wir durch den Fortschritt der Technologie täglich mehr Erfahrung und entwickeln neue Methoden für das Reverse Engineering für verschiedene integrierte Schaltungsteile. Die vollständige Liste der Teilenummern integrierter Schaltungen, die in unseren Leistungsbereich fallen, wird ständig größer. Bitte kontaktieren Sie uns, um dies herauszufinden.

  • Wird meine Privatsphäre geschützt?

    Mikatech Innovative Limited versteht die Bedeutung der Privatsphäre seiner Kunden. Sobald Sie Mikatech kontaktieren, werden Ihre persönlichen Informationen durch unsere Geschäftsordnung, die wir im Laufe unserer jahrelangen Praxis entwickelt haben, geschützt. Mikatech verwendet diese Informationen, um seinen Service für Sie zu personalisieren und wird diese Informationen niemals aus irgendeinem Grund an Dritte weitergeben.
    Bei jedem Projekt, das wir durchgeführt haben, löschen wir alle Daten, Materialien und Codes 60 Tage nach der Lieferung der Dateien. Dies schützt uns und schützt Ihre Privatsphäre.

  • Ist es legal, Dienstleistungen von Mikatech in Anspruch zu nehmen?

    Ja, es ist völlig legal.
    Mikatech erbringt seine Reverse-Engineering-Dienstleistungen nur zu Bildungszwecken. Die Nutzung der oben genannten Dienstleistungen kann in einigen Ländern oder Regionen illegal sein. Bitte überprüfen Sie Ihre lokalen Gesetze. Mikatech übernimmt keine Verantwortung im Zusammenhang mit der Nutzung der oben genannten Dienstleistungen, die als illegal angesehen werden könnte.


  • Ich habe Ihnen eine E-Mail geschickt, warum gibt es keine Antwort?

    • A. Unser Mail-Server ist vorübergehend ausgefallen, Ihre Nachricht wurde nicht in unser Postfach zugestellt, obwohl die Meldung "Erfolgreich gesendet" auf dem Bildschirm angezeigt wird. Bitte kontaktieren Sie uns erneut.
    • B. Unsere E-Mail wird von Ihrem Mail-Server als Junk-Mail erkannt, daher wurde unsere Antwort von Ihrem Mail-Server abgelehnt oder in Ihren Junk-Mail-Ordner umgeleitet. Bitte entfernen Sie unser Konto aus der Junk-Mail-Liste oder überprüfen Sie Ihren Junk-Mail-Ordner oder verwenden Sie ein anderes E-Mail-Konto wie Gmail, um uns zu kontaktieren.
    • C. Ihre E-Mail wird von unserem Mail-Server als Junk-Mail erkannt, daher wurde Ihre E-Mail in unseren Junk-Mail-Ordner verschoben. Bitte verwenden Sie ein anderes E-Mail-Konto, um uns erneut zu kontaktieren.

    Mikrocontroller-Hack-Zeit

    Jahre

    28 +
    Mikrocontroller-Hack-Länder

    Länder

    110 +
    Mikrocontroller-Angriffskunden

    Kunden

    5000 +
    Entsperrte Mikrocontroller-Projekte

    Projekte

    60000 +