Den Abschluss dieser Serie über Parallax Propeller 2 stellen die Smart-Pin-Funktionen dar, dank der sich die I/O-Pins universell und flexibel konfigurieren lassen. Außerdem werden die Pull-up- und Pull-down-Widerstände der I/O-Pins beleuchtet. Und es gibt noch mehr zu entdecken….

GPIOs der MCU Propeller 2

Da die Pins des Propeller 2 mehr als die üblichen Funktionen anderer MCUs haben, ist ein genauerer Blick darauf spannend. Als eine Art Referenz dient zunächst ein Blick auf die GPIO-Struktur des verbreiteten Mikrocontrollers ATmega328P. Im Vergleich zum Propeller 2 sieht man dann, welche Unterschiede es gibt und wie man sie nutzt. Damit sollte es dann sehr einfach sein, den Status einiger Taster abzufragen.

I/O-Pins anderer MCUs 

Wer mit dem ATmega328P vertraut ist weiß, dass es grundsätzlich vier I/O-Pin-Zustände gibt: Ein offener Eingang, ein Eingang mit Pull-up, ein Ausgang mit Low-Pegel und ein Ausgang mit High-Pegel. Nur wenige Pins des ATmega328P haben Analog-Funktionen – sie werden hier nicht behandelt. Das Datenblatt in Bild 1 zeigt, wie ein I/O-Pin grundsätzlich aufgebaut ist.
 
ATmega328 I/O block.
Bild 1: Datenblatt-Ausschnitt mit dem I/O-Blocks des ATmega328.

Im Folgenden werden die interessanten Aspekte in den Bildern rot bezeichnet. Wesentlich ist hier eine Ansteuerung für einen Pull-up-Widerstand (20 bis 50 kΩ), bestehend aus einem FET und dem Widerstand sowie einer Steuerlogik für den FET (wie der Ausschnitt in Bild 2 zeigt).

Output path for ATmega328.
Bild 2: Ausgangspfad des ATmega328.

Unten in Bild 1 ist ein sogenanntes Transmission Gate (Bild 3), das als digital gesteuerter Schalter fungiert und analoge Spannungen durchlässt.

Transmission Gate.
Bild 3: Transmission Gate.

Interessant ist das SLEEP-Signal, welches das Transmission Gate deaktiviert und gleichzeitig dessen Ausgang mit einem extra FET auf Masse legt. Der Grund ist der Schmitt-Trigger am Ausgang des Transmission Gates. Er kann eine analoge Spannung in einen binären Wert umwandeln. In der Mitte von Bild 4 befindet sich die Ausgangsstufe mit „enable“.

ATmega328 FET for pull-up.
Bild 4: Ein FET aktiviert den Pull-up-Widerstand.

Wenn „enable“ nicht gegeben ist, wird die Ausgangsstufe abgeschaltet, ansonsten gibt sie je nach anliegendem Eingang ein Low oder High aus. Das war viel Text für eine I/O-Funktion, aber dies dient dem Verständnis der Grundlagen. Nun zum Pull-up: Man kann nur global alle Pins auf einmal in den Ruhezustand versetzen (so wie andere Teile des ATmega328). Bleibt ein Pin unbenutzt lassen, wird sein Eingang floaten. Das bedeutet, dass er zufälliges Rauschen aufnimmt, das der Schmitt-Trigger in binäre Pegelfolgen umwandelt. Daher wird der Schmitt-Trigger samt interne Logik schnell zwischen Low und High wechseln – relevant, da jeder Pegelwechsel etwas Energie benötigt. Das ist nicht wünschenswert und verschwendet Energie. Besonders bei Batteriebetrieb sollte man das vermeiden. Abhilfe ist einfach: Per Pull-up wird der (ansonsten hochohmige) Eingang auf VCC (= High) gelegt und das zufällige Schalten verhindert. Eine lange aber notwendige Herleitung zum Umgang mit einem simplen I/O-Pin. Ab jetzt geht es um die I/O-Implementierung des Propeller 2.

Smart Pins beim Propeller 2

Wie schon erwähnt, gibt es keine simplen I/O-Pins beim Propeller 2. Schon bei den grundlegenden I/O-Funktionen zeigt das vorläufige Datenblatt des Propeller 2, dass selbst für die einfache I/O-Konfiguration mehr als vier Auswahlmöglichkeiten existieren. Alle Pins können als digitaler oder analoger Eingang- oder Ausgang agieren.
Los geht es mit der digitalen Eingang. Beim ATmega328 war alles sehr einfach: Ein Transmission Gate und ein Schmitt-Trigger zum Auslesen des Signals war alles. Beim Propeller 2 gibt es mehr Logik bei den Pins. Bild 5 zeigt den digitalen Eingangspfad, bzw. die Pfade, die für einen einzelnen Pin existieren.

Input paths for Propeller 2 I/O pin.
Bild 5: Eingangspfade der I/O-Pins beim Propeller 2.

Etwas seltsam ist, ist, dass es jeweils gleich zwei Eingangsselektoren gibt. Damit lässt sich für jeden Eingang der aktuelle Pin und bis zu drei Pins daneben auswählen. Die Signale der Selektoren können optional auch noch invertiert werden, was zu einem A- oder B-Term führt. Die resultierenden A- und B-Signale werden dann in einen Block eingespeist, der logische Operationen oder Filterungen durchführen kann. Das Resultat dieser Operationen wird schließlich dem System als IN-Signal präsentiert. Das macht die I/Os etwas komplizierter, aber auch vielseitiger als bei einem ATmega328P. Beim digitalen Ausgang sind die Dinge einfach: Es gibt nur einen Low- und einen High-Ausgang – auf den ersten Blick nichts Ausgefallenes.
 
Nun zum Pull-up-Widerstand: Sie ahnen es bereits: Der Propeller 2 hat mehr als nur einen. Es ist sowohl ein Pull-up als auch ein Pull-down möglich und das unterschiedlich „stark“:

  • 1,5 kΩ
  • 15 kΩ
  • 150 kΩ
  • 19 Ω
  • 1 mA
  • 100 µA
  • 10 µA
  • Floating 

Da einstellbar ist, ob man einen Pull-up- oder Pull-down-Widerstand oder gar Stromquellen haben will, sind die Pins sehr flexibel an verschiedenen Bedingungen Bus-Typen anpassbar.
 
Pull-Ups oder Pull-Downs werden nicht wie beim ATmega328 mit einem separaten FET ein- oder ausgeschaltet, sondern diese Widerstände wirken als „drive strength“ so, als ob sie zwischen der Treiberstufe und dem Pin-Ausgang lägen. Für die Verwendung als Pull-Up oder Pull-Down schaltet man den Pin als Ausgang mit dem entsprechendem Widerstand und verwendet Low oder High für Pull-Up oder Pull-Down. Die Low-Level-Beschreibung eines Pins von Bild 6 zeigt, dass noch etwas mehr dahinter steckt.

Low level description for Propeller 2 pin.
Bild 6: Low-Level-Pin-Beschreibung beim Propeller 2.

Jeder einzelne Pin kann auch in analog verwendet werden. Deshalb gibt es dafür jeweils einen DAC und einen ADC. Die Dokumentation ist leider noch nicht ganz vollständig, so dass einige Bereiche für bestimmte I/O-Konfigurationen fehlen. Dies gilt besonders für Low-Level-Konfigurationen. Bei Vorserien-Silizium ist dies jedoch zu erwarten. Bild 7 gibt einen Überblick über das Smart-Pin-Konfigurationsregister. Genug der Theorie für den Moment…

Smart pin configuration register.
Bild 7: Smart-Pin-Konfigurationsregister.

Praktische Anwendung

Für einen ersten Praxistest dienen vier Taster. Auf diese Weise kann man eine LED mit einem Tastendruck zum Leuchten bringen. Hierzu wird der bestehende SPIN2-Code erweitert und dabei all die netten Fähigkeiten eingesetzt, mit denen ein I/O-Pin für eine LED angesteuert und die prints()-Funktion zum Schreiben von Strings auf einen UART genutzt werden können. Das einfache Ziel ist: Der Zustand eines Pins wird abgefragt und entsprechend eine LED gesteuert – das Ganze viermal für vier LEDs und vier Taster. Zusätzlich wird ein String ausgegeben, wenn ein Taster gedrückt oder losgelassen wird.

Zur Konfiguration der Eingänge: Da die Hardware-Taster keine eigenen Pull-up- oder Pull-down-Widerstände haben, werden die Chip-internen genutzt. Aus Bild 7 und Bild 8 wird den Wert für das Config-Register berechnet.

Propeller 2 pin modes overview.
Bild 8: Übersicht über die Pin-Modi des Propeller 2.

Mit Blick auf Bild 5 kommt am Ende der Logikpegel heraus, der vom Pin geboten wird. Folglich werden die Eingänge A und B gleich konfiguriert, nicht invertiert und der Ausgang A verzichtet auf jegliche Logik oder Filterung. Laut Propeller 2-Datenblatt errechnet sich dies zu 0000 0000 000 000 010 010 00 00000 in Binär ( 0x900 in Hex), wenn man einen 15-kΩ-Pull-up wählt.
 
Für den Code bedeutet dies, dass vier Eingänge und vier Ausgänge verwendet werden, indem die kleine Zusatzplatine (Bild 9) an das Propeller-2-Evaluation-Board angeschlossen wird.

Propeller 2 with attached buttons.
Bild 9: Propeller 2 mit angeschlossenen Tastern.

Listing 1 enthält den modifizierten SPIN2-Code zum Einrichten der vier Eingangspins mit Pull-ups samt Ausgangskonfiguration der Pins für die LEDs.

Listing 1

Die zuletzt eingelesenen Pin-Pegel landen in vier globalen Variablen und werden zudem als serielle Nachricht zu senden, wenn sich ein Pin geändert hat. Hierzu wird der schon vorhandene Code um zwei Funktionen zur Initialisierung der LEDs und zur Initialisierung der Eingänge erweitert. Listing 2 zeigt vier deklarierte Bytes, die den Zustand der vier an angeschlossenen Taster speichern.

Listing 2

Außerdem sieht man, dass sich der Code mit den beiden Initialisierungsfunktionen geändert hat (Listing 3).

Lisitng 3

Die Magie für die aktiven Pull-ups der Eingänge ist in den Bits von Listing 4 versteckt.

Lisitng 4

Die Ein- und Ausgänge werden so konfiguriert, dass sie mit einem Widerstand von 15 kΩ angesteuert werden. In der letzten Zeile werden die vier Eingangspins so konfiguriert, dass sie als Ausgang mit Low-Pegel dienen.
 
Nachdem der Initialisierung wird die Funktion read_switch() wiederholt aufgerufen. Der Code von Listing 5 verwendet nach dem Einlesen der Pin-Zustände in die Variablen a bis d einige IF- und IF-ELSE-Konstrukte.

Listing 5

Als erstes wird geschaut, ob sich ein Pin geändert hat, indem der gespeicherte Zustand mit dem neuen, gerade gelesenen verglichen wird. Bei einem Unterschied hat sich der Zustand am Pin-Eingang geändert. Jetzt lässt sich überprüfen und entscheiden, ob entsprechende Taster gedrückt oder losgelassen wurde. Abhängig vom aktuellen Zustand des Pins gibt die Funktion prints() die Meldung „Switch pressed“ oder „Switch released“ aus. IListing 5 zeigt, wie read_switch() aufgebaut ist und funktioniert: Mit einfachen IF-THEN-ELSE-Pfaden für jeden verwendeten Taster. Dort kann man auch sehen, dass der Zustand der LEDs entsprechend dem neu erkannten Zustand geändert wird.
 
Das war genug zum Thema Smart Pins. Dieser kleine Einblick in deren Konfiguration und Anwendung bildet fürs Erste auch das Ende der Serie. Da bei mir ein Propeller 2 auf dem Tisch liegt, wird es nicht das letzte Mal sein, dass ich darüber schreibe oder ein kurzes Video mache. Da sich Software und IDE weiterentwickeln, möchte ich ihr noch etwas Zeit zum Reifen geben. In der Zwischenzeit können Sie auf den in dieser Serie entwickelten Code in unserem GitHub-Repository zugreifen.

Erste Einsichten

Nachdem meiner Beschäftigung mit dem Propeller 2 kann ich sagen, dass es sich um eine leistungsfähige MCU handelt, die definitiv mehr Aufmerksamkeit für ihre Details benötigt als z.B. ein Raspberry Pi Pico. Die Verwendung von SPIN2 und Assembler ist etwas Besonderes und macht die Wiederverwendung von bestehendem C-Code unmöglich. Propeller 2 wird wohl nicht meine MCU der Wahl für Mainstream-Projekte, aber es gibt definitiv einige Nischen, für die dieser Chip wie gemacht erscheint.