Wenn wir einen Digitalport als Eingang verwenden wollen, müssen wir zunächst die Sonderfunktion wie ADC oder USART abschalten. Dazu muss das Function-Select-Register mit 0 initialisiert werden. Außerdem muss im Direction-Register festgelegt werden, dass der Digitalport als Eingang genutzt werden soll. Jeder Byteport verfügt über (bis zu) acht unabhängig voneinander ansprechbare Digitalpins. Die acht Bitstellen in den jeweiligen Registern (z.B. P1DIR oder P1SEL) sind dabei für den jeweiligen Pin 0 bis 7 vorgesehen. Beispiel 2.1 zeigt, wie wir den Byteport P1 als Eingang definieren können.
| Listing 2.1: | Initialisierung von P1 als digitalen Eingang |
Häufig verwendet man in der Mikrocontrollertechnik die hexadezimale Schreibweise zur Darstellung von Werten. Bei dieser Schreibweise stellt jede Ziffer ein so genanntes 4 Bit breites Nibble dar. Mit zwei Nibble können alle acht Pins adressiert werden. Sehr günstig ist dafür auch die Verwendung symbolischer Konstanten1 . Durch deren konsequente Nutzung wird der Code wesentlich besser lesbar und Fehler werden vermieden. Die Konstanten können dann mit einfacher boolscher Logik verknüpft werden. Mit der ”ODER”-Verknüpfung kann man ein Bit setzen, mit der ”UND-NICHT”-Verknüpfung ein Bit löschen.
| Listing 2.2: | Definition von Konstanten um selektiv Bits in Registern zu beeinflussen |
Um nun den Status eines Pins (in unserem Beispiel den Pin P1.2) auszulesen, müssen wir nach der Initialisierung auf das Input-Register zugreifen. Die Eingänge basieren auf Schmitt-Trigger-Bausteinen. Damit ist sichergestellt, dass selbst bei langsam wechselnden Eingangssignalen sauber zwischen dem eingeschalteten (1) und dem ausgeschalteten (0) Pegel unterschieden werden kann. Die Hysterese der Schmitt-Trigger-Bausteine sorgt schaltungstechnisch dafür, dass es zu keinen Schwingungen am Umschaltpunkt kommt. Eine Eingangsspannung oberhalb von 2V wird sicher als eine logische 1 erkannt, eine Spannung unterhalb von 0,9V sicher als eine logische 0. Diese Werte können sich für kleinere Betriebsspannungen noch verändern. Hier gibt das Datenblatt des jeweiligen Controllers genauen Aufschluss.
Man kann nur den kompletten Zustand eines Byteports einlesen und nicht jeden einzelnen Pin selbst. Um dennoch den Status eines einzelnen Pins auslesen zu können, kann man das Input-Register des Byteports entsprechend bitweise verknüpfen.
| Listing 2.3: | Auslesen des Status von Digitalport P1.2 |
Im Beispiel 2.3 wird geprüft, ob nur P1.2 logisch 1 ist. Alle anderen Pins müssen logisch 0 sein. Will man testen, ob P1.2 logisch 1 ist, unabhängig von den anderen Pins, müsste man auf P1.2 anstatt des ”==” -Operators eine AND-Verknüpfung (Achtung: &-Operator, nicht &&-Operator) anwenden. In jedem Fall ist zu beachten, dass die Zählung der Pins bei 0 beginnt. Für den Pin P1.0 muss man somit mit der hexadezimalen Zahl 0x01 verknüpfen. Für den Pin P3.6 dagegen würde man das Register P3IN mit der hexadezimalen Zahl 0x40 (dezimal = 64) verknüpfen. Wie gesagt, wäre das Verwenden der logischen Konstante BIT6 allemal einfacher zu verstehen.
Beim Anschluss von Tastern sollte man bestimmte Eigenschaften der digitalen I/O-Ports beachten. Wenn man mit digitalen Eingängen arbeitet, ist die Eingangsimpedanz der jeweiligen Pins sehr hochohmig. Ein strombegrenzender Vorwiderstand zum Sensor oder Taster ist daher nicht zwingend erforderlich, für die Entwicklungsphase aber dringend anzuraten. Schnell hat man aus Versehen den Pin als Ausgang statt als Eingang definiert. Der Widerstand vermeidet dann den elektrischen Kurzschluss und sichert das Überleben des Mikrocontrollers. Die digitalen Eingänge haben charakteristische Eingangspegel, die in Tabelle 2.2 zusammengefasst sind.
| Parameter | Minimal | Maximal |
| Obere Umschaltschwelle V IT+ | 1.5V | 1.9V |
| Untere Umschaltschwelle V IT- | 0.9V | 1.3V |
| Eingangsspannungshysterese V hys | 0.5V | 1V |
| Tabelle 2.2.: | Eingangspegel der digitalen Eingänge |
Um saubere und definierte Schaltzustände zu erhalten, verschaltet man die Eingänge meist mit so genannten Pull-Up- oder Pull-Down-Widerständen. Ein Pull-Up-Widerstand zieht den Pegel des Digitalports hoch (HIGH). Ein Pull-Down-Widerstand wird den Pegel des Digitalports dagegen runterziehen (LOW). Der Pegel ist dabei die am Port anliegende Spannung, die einem bestimmten logischen Zustand (gesetzt oder nicht gesetzt) des Digitalports entspricht.
| Bild 2.2.: | Anschluss von Tastern mit Pull-Up- und Pull-Down-Widerständen sowie einem ”Sicherheits-” Vorwiderstand |
Will man, dass der Eingang logisch HIGH ist, wenn man einen Taster drückt, würde man den Port
entsprechend Abbildung 2.2 (links) verschalten. Für einen Eingang, der beim Betätigen eines
angeschlossenen Tasters logisch LOW sein soll, bietet sich die Schaltung in Abbildung 2.2 (rechts)
an. Die Größe des ”Pull”-Widerstandes ist dabei nicht so entscheidend. Werte im Bereich von
10kΩ bis 1MΩ sind dafür üblich.
Die Dimensionierung des ”Sicherheitswiderstands” bemisst sich am Fehlerfall. Im schlimmsten Fehlerszenario schaltet der Port aktiv gegen Masse (Pull-Up-Konfiguration) oder Betriebsspannung (Pull-Down-Konfiguration), wenn der Schalter geschlossen ist. Das klingt auf den ersten Blick vielleicht relativ unwahrscheinlich, ist es aber nicht. Gerade bei der Entwicklung der Mikrocontroller-Software hat man schnell mal den falschen Port als Ausgang definiert und schon ist es passiert. Damit der Mikrocontroller überlebt, darf der Strom nicht größer als maximal erlaubt werden (z.B. IMax < 2mA). Damit erhalten wir bei 3.3V Versorgungsspannung einen minimalen ”Sicherheits-” Vorwiderstand von etwa 1.8kΩ.
Ein Problem von Schaltern und Tastern ist, dass sie als mechanische Bauteile die Eigenschaft haben zu prellen. Das bedeutet, dass sie bei Betätigung - also zum Beispiel beim Schließen eines Schalters - nicht unmittelbar Kontakt zum Eingangsport herstellen, sondern mehrfach schnell ein- und ausschalten. Dies wird zum Problem, wenn man in der Software nicht auf den Zustand eines Schaltelementes sondern auf den Zustandswechsel reagiert. Bei einer Taktung von 8MHz würde die While-Schleife aus Listing 2.3 in etwa einer Mikrosekunde durchlaufen. Wenn man an den Digitalport P1.2 einen Taster anschließt und die Tastendrücke nun in dieser Schleife zählt, so würde der Controller während eines Tastendrucks viele Male die Schleife durchlaufen und fälschlicherweise jedes Mal die Anzahl der Tastendrücke inkrementieren. Eine Lösungmöglichkeit ist das Entprellen von Eingängen. Prinzipiell kann man dies sowohl in Hardware als auch in Software erreichen.
Eine einfache Möglichkeit einen Eingang zu entprellen ist eine FOR-Schleife, die einige tausend Zyklen durchläuft und so eine künstliche Programmpause erzeugt. Beispiel 2.4 zeigt eine Software-Entprellung mit einer FOR-Schleife, die 1000-mal durchlaufen wird.
| Listing 2.4: | Programmausschnitt mit Software-Entprellung |
Ein Nachteil der Software-Entprellung ist, dass das Programm für eine kurze Zeit unterbrochen wird. Zeitkritische Anwendungen können dadurch beeinträchtigt werden. Im Gegensatz zur Entprellung per äußerer Beschaltung lässt sie sich jedoch auch noch nachträglich implementieren.
Wenn man den Programmfluss durch das Entprellen der Eingänge nicht unterbrechen will, bietet sich das Entprellen per äußerer Beschaltung an. Dazu kann man an den Eingang ein RC-Glied mit Tiefpassverhalten schalten, wie dies in Bild 2.3 zu sehen ist. Die RC-Zeitkonstante τ = R ⋅C sollte so gewählt werden, dass sie deutlich größer als die Prellzeit ist. Für die meisten handelsüblichen Schalter ist bei einem Vorwiderstand von 47kΩ eine Kapazität von 100nF ausreichend. Dies ergibt dann eine Zeitkonstante von etwa 5ms.