Tutorial · Einsteiger · 30 Min.

8051-Architektur: Pins, Speicherkarte und Register

Was im 8051 wirklich steckt: Harvard-Kern, vier Ports mit eigenem Charakter, 256 Byte RAM und ein Maschinenzyklus, den man mitzählen kann.

Einführung

Die meisten Mikrocontroller-Kurse beginnen mit dem 8051, und die meisten Studierenden begegnen ihm als Liste auswendig zu lernender Fakten: vier Ports, 128 Byte RAM, zwei Timer, sechs Interrupts. So auswendig gelernt ist er schnell vergessen. Versteht man ihn dagegen als Bündel bewusster Kompromisse aus dem Jahr 1980 – als RAM richtig Geld kostete und ein Chip in 40 Pins passen musste –, erklärt er fast alles, wie kleine Mikrocontroller bis heute funktionieren.

Dies ist der Architektur-Rundgang: was im Gehäuse steckt, wie der Speicher aufgeteilt ist und warum die Timing-Rechnung ungewöhnlich einfach ist. Die beiden Fortsetzungen behandeln die Ansteuerung der Pins und die PWM-Erzeugung per Timer.

„8051“ ist eine Familie, kein Chip

Intel führte den MCS-51 im Jahr 1980 ein und lizenzierte den Kern breit, daher kauft heute niemand mehr einen Intel 8051. Was man kauft, ist ein kompatibler Baustein – ganz überwiegend Atmels (heute Microchips) AT89S52, der Flash-Speicher hinzufügt, den man über vier Pins neu programmieren kann, statt des UV-löschbaren ROMs des Originals.

Die Unterschiede, die man kennen sollte:

8051 (Original) AT89S52 (dein Baustein)
Programmspeicher 4 KB ROM 8 KB Flash
Internes RAM 128 Byte 256 Byte
Timer 2 3
Interruptquellen 5 6
Programmierung Masken-ROM ab Werk Im System, über SPI-Pins

Alles andere – Befehlssatz, Ports, Registerlayout, Timing – ist identisch. Kursmaterial zum 8051 gilt unverändert für den Chip auf deinem Tisch.

Was im Gehäuse steckt

Ein 40-poliges DIP enthält einen kompletten Computer: eine 8-Bit-CPU, Programm-Flash, Daten-RAM, drei Timer/Zähler, eine Vollduplex-Serienschnittstelle, eine Interruptsteuerung und vier 8-Bit-I/O-Ports. Es gibt kein Betriebssystem und nichts läuft außer deinem Code.

Pinbelegung des 8051 im 40-poligen DIP-Gehäuse, vertikal gezeichnet mit der Pin-1-Kerbe oben. Linke Spalte mit Pins 1 bis 20: Port-1-Pins P1.0 bis P1.7 mit ihren T2-, T2EX-, MOSI-, MISO- und SCK-Sonderfunktionen, dann RST, dann Port-3-Pins P3.0 bis P3.7, beschriftet mit RXD, TXD, INT0, INT1, T0, T1, WR und RD, dann XTAL2, XTAL1 und GND. Rechte Spalte mit Pins 40 bis 21: VCC, Port-0-Pins P0.0 bis P0.7 zugleich als AD0 bis AD7, dann EA, ALE und PSEN, dann Port-2-Pins P2.7 bis P2.0 zugleich als Adressleitungen A15 bis A8. Farbcodierung trennt I/O-Ports, Port-3-Sonderfunktionen, Takt- und Steuerpins sowie Versorgung.
32 der 40 Pins sind I/O. Port 0 ist relativ zu den anderen rückwärts nummeriert, und unter den Alternativbeschriftungen von Port 3 leben Serienschnittstelle, externe Interrupts und Timer-Eingänge. SVG herunterladen

Vier Pins sind überhaupt kein I/O, und alle vier müssen stimmen, bevor irgendetwas läuft: XTAL1 und XTAL2 für den Quarz, RST für das Reset-Netzwerk und EA zur Wahl von internem oder externem Programmspeicher. Ist EA falsch, tut der Chip nichts – lautlos.

Die Minimalschaltung, die ein 8051 zum Laufen braucht. Ein AT89S52-Baustein zeigt sechs Pins: VCC an Pin 40 an der 5-Volt-Schiene und GND an Pin 20 an Masse; EA an Pin 31 an der 5-Volt-Schiene in Rot, kommentiert mit EA auf High legen, sonst läuft der Chip nicht; XTAL2 an Pin 18 und XTAL1 an Pin 19 über einen 11,0592-MHz-Quarz verbunden, mit je einem 33-Pikofarad-Kondensator von jedem Quarzbein nach Masse; und RST an Pin 9 über einen 10-Mikrofarad-Kondensator nach oben an die 5-Volt-Schiene und einen 10-Kiloohm-Widerstand nach unten an Masse, kommentiert mit Reset ist Active-High.
Vier Verbindungen und eine Handvoll passiver Bauteile. Beachte das Reset-Netzwerk: Der Kondensator geht an die Versorgung, nicht an Masse, weil RST Active-High ist. SVG herunterladen

Harvard: Code und Daten sind verschiedene Welten

Der 8051 hält Programmspeicher und Datenspeicher in getrennten Adressräumen. Eine Adresse 0x0030 bedeutet für einen Befehlszugriff etwas anderes als für einen Datenzugriff – es sind verschiedene Speicher, erreicht über verschiedene Befehle.

Darum zwingen C-Compiler für den 8051 zum Nachdenken über Speicherklassen, die andere Plattformen verbergen. Ein String-Literal, das du nie änderst, gehört in den code-Speicher, wo Kilobytes übrig sind. Lege es versehentlich in data ab, frisst es die 256 Byte, die du für alles andere brauchtest:

// In code (flash) — costs nothing from your 256 bytes of RAM.
const char code banner[] = "Line follower v1";

// In RAM — 17 of your 256 bytes, gone, for a string that never changes.
const char banner_bad[] = "Line follower v1";

Auf einem Arduino existiert genau dafür PROGMEM. Auf dem 8051 ist das keine Optimierung, sondern der Unterschied zwischen einem Programm, das passt, und einem, das nicht passt.

Die interne RAM-Karte

Die 256 Byte internes RAM sind kein flacher Notizzettel. Sie sind in Bereiche mit unterschiedlichen Fähigkeiten aufgeteilt, und zu wissen, welcher welcher ist, ist der größte Teil der Speicherkarte.

Karte des internen 8051-Datenspeichers als gestapelte Blöcke von Adresse 00h unten bis FFh oben. Von unten: vier 8-Byte-Registerbänke bei 00h bis 07h, 08h bis 0Fh, 10h bis 17h und 18h bis 1Fh; ein 16-Byte-bitadressierbarer Bereich bei 20h bis 2Fh mit 128 einzeln adressierbaren Bits; 80 Byte Arbeits-RAM und Stack von 30h bis 7Fh; und bei 80h bis FFh ein Block, der sowohl die Spezialfunktionsregister, erreicht über direkte Adressierung, als auch die oberen 128 Byte RAM enthält, erreicht nur über indirekte Adressierung. Ein Pfeil markiert, dass der Stackpointer auf 07h zurückgesetzt wird, sodass der Stack bei 08h auf Registerbank 1 beginnt, und ein zweiter Pfeil markiert den Bereich 80h bis FFh als zwei Speicher im selben Adressbereich.
Vier Bereiche mit vier verschiedenen Aufgaben. Die beiden markierten Fakten beißen: Der Stack landet auf Registerbank 1, und die obere Hälfte des Adressbereichs sind zwei getrennte Speicher. SVG herunterladen

00h–1Fh – vier Registerbänke. R0 bis R7 sind keine festen Adressen, sondern ein Fenster auf eine von vier 8-Byte-Bänken, gewählt über zwei Bits (RS0 und RS1) im Programmstatuswort. Das Umschalten der Bank ist ein Zwei-Bit-Schreibzugriff und damit ein sehr billiger Weg, einem Interrupt eigene Register zu geben, statt acht davon zu sichern und zurückzuholen.

20h–2Fh – bitadressierbar. Diese 16 Byte sind zusätzlich als 128 einzelne Bits adressierbar, 00h bis 7Fh. Der 8051 hat echte Einzelbit-Befehle – SETB, CLR, JB, JNB –, sodass ein Flag hier ein Bit und einen Befehl kostet statt eines Bytes und einer Maske. Darum bieten 8051-C-Compiler einen bit-Typ, den es sonst nirgends gibt.

30h–7Fh – Arbeitsbereich und Stack. Achtzig Byte für deine Variablen und deinen Aufruf-Stack, und genau diese Ressource geht tatsächlich aus.

80h–FFh – zwei Speicher, ein Adressbereich. Direkte Adressierung erreicht hier die Spezialfunktionsregister; indirekte Adressierung (über R0 oder R1) erreicht die oberen 128 Byte RAM. Gleiche Nummern, verschiedene Speicher, gewählt über die Befehlsform. Beim ursprünglichen 128-Byte-8051 existiert das obere RAM schlicht nicht.

Spezialfunktionsregister sind nur Speicher

Jede Peripherie des 8051 wird gesteuert, indem man Bytes an Adressen im direkten Bereich 80h–FFh schreibt. Es gibt keine API – es gibt ein Register, und das Setzen eines Bits darin ändert, was das Silizium tut.

Register Adresse Was es steuert
P0 P1 P2 P3 80h, 90h, A0h, B0h Die vier I/O-Ports
TMOD 89h Timer-0- und -1-Betriebsart
TCON 88h Timer-Startbits und Überlaufflags
TH0 TL0 TH1 TL1 8Ch, 8Ah, 8Dh, 8Bh Timer-Zählregister
SCON SBUF 98h, 99h Serienschnittstellen-Steuerung und Daten
IE IP A8h, B8h Interruptfreigabe und -priorität
PSW D0h Flags und die Registerbank-Auswahlbits
SP 81h Stackpointer

P1 = 0x0F; in C zu schreiben ist ein Speicherzugriff auf Adresse 90h, und acht Pins ändern ihren Zustand. Diese Direktheit ist der ganze Reiz des Chips als Lehrbaustein.

Timing zum Mitzählen

Ein Maschinenzyklus sind zwölf Oszillatorperioden beim klassischen 8051-Kern, und die meisten Befehle brauchen einen oder zwei Maschinenzyklen. Dieses feste Verhältnis erlaubt, die Ausführungszeit exakt zu berechnen statt sie zu messen:

machine cycle = 12 / f_osc

at 11.0592 MHz : 12 / 11 059 200 = 1.085 µs
at 12 MHz      : 12 / 12 000 000 = 1.000 µs

Eine Schleife aus drei Einzyklus-Befehlen bei 11,0592 MHz dauert jedes Mal 3,26 µs – ohne Cache, ohne Pipeline und ohne Interrupt-Jitter außer dem, den du selbst freigibst. Kaum ein moderner Prozessor erlaubt solches Schlussfolgern, und darum überlebt der 8051 in zeitkritischer Peripherie.

Warum der Quarz 11,0592 MHz hat

Diese Zahl wirkt willkürlich und ist es nicht. Die Serienschnittstelle leitet ihre Baudrate durch Teilung des Maschinenzyklustakts ab, und 11,0592 MHz lässt sich exakt auf Standard-Baudraten teilen:

baud = f_osc / (12 × 32 × (256 − TH1))

11.0592 MHz, TH1 = 253 :  11 059 200 / (12 × 32 × 3) = 9600.0   ✓ exact
12 MHz,      TH1 = 253 :  12 000 000 / (12 × 32 × 3) = 10416.7  ✗ 8.5% off

Ein UART verträgt wenige Prozent Fehler; 8,5 % verstümmeln jeden Rahmen. Wenn dein 8051-Board Müll über die Serienschnittstelle druckt, schau erst auf den Quarz, dann auf deinen Code.

Was der 8051 nicht hat

Zwei Lücken prägen jedes 8051-Projekt, und keine ist aus einer Funktionsliste ersichtlich:

  • Kein Analog-Digital-Wandler. Für ein Potenziometer, einen Thermistor oder einen analogen Liniensensor braucht es einen externen ADC-Baustein wie den ADC0804. Es gibt kein analogRead(), nach dem man greifen könnte.
  • Keine PWM-Hardware. Nichts auf dem Chip erzeugt ein Tastverhältnis-Signal. Eine LED zu dimmen oder eine Motordrehzahl zu setzen heißt, PWM selbst aus einem Timer-Interrupt zu bauen – und dafür CPU-Zeit zu zahlen.

Ein Arduino Uno hat beides eingebaut. Das ist der ehrliche Vergleich: Der 8051 ist kein schlechterer Arduino, sondern die Schicht darunter – mit entfernten Annehmlichkeiten, damit man sieht, was sie geleistet haben.

Wenn es schiefgeht

  • Das Board ist tot und nichts wird warm. Prüfe, ob EA (Pin 31) auf +5 V liegt. Schwebend oder auf Masse holt der Chip Code aus nicht vorhandenem externem Speicher und führt nichts aus – ganz ohne Symptom.
  • Es startet ständig neu oder gar nicht. Reset beim 8051 ist Active-High. Die Einschalt-Schaltung ist ein 10-µF-Kondensator von +5 V nach RST und ein 10-kΩ-Widerstand von RST nach Masse. Wie ein Active-Low-Reset verdrahtet hält sie den Chip in dauerhaftem Reset.
  • Serielle Ausgabe ist Müll. Fast immer der Quarz. Ein 12-MHz-Baustein erreicht keine Standard-Baudraten.
  • Variablen überschreiben einander ohne Grund. Wahrscheinlich sind die 80 Byte bei 30h–7Fh aufgebraucht oder der Stack ist in deine Variablen hineingewachsen. Prüfe die Speicherkarte des Compilers.
  • Register ändern sich unerwartet im Interrupt. Der Stackpointer startet bei 07h, also beginnt der Stack bei 08h – und das ist Registerbank 1. Verschiebe SP entweder im Startcode oder lasse Bank 1 in Ruhe.

Den Graphen erkunden

Teil dieser Bauprojekte

Projekte und Lernpfade, die dieses Tutorial enthalten.

Weiterführende Literatur

Quellen