DIGITALE EINGÄNGE
Ein Mikrocontroller ohne Kontakt zur Aussenwelt macht keinen Sinn.
Deswegen besitzt ein Mikrocontroller sogenannte Ports.
Ein Port ist in seiner Gesamtheit eine Menge, in der sich die entsprechenden Controller-Pins befinden, die internen Register, die für diese Pins zuständig sind, und die Elektronik, die sehr unterschiedlich bei den einzelnen Pins sein kann.
Ein Port ist in der Regel 8 Bit lang, jeder Pin eines Ports hat mindestens 1 Funktion, die meisten haben zwei oder manche sogar noch mehr Funktionen.
Das Datenblatt des Mikrocontroller gibt darüber Auskunft.
Da wir uns hier mit dem Arduino Uno beschäftigen, schauen wir mal einen kurzen Blick auf den Mikrocontroller ATmega328p, der hier auf dem Board seinen Dienst verrichtet:
Hier sehen wir die einzelnen Bezeichnungen der Ports, zB PortB, besttehend aus PB0, PB1, etc.
Aber auch andere Pins gibt es noch, GND für den Anschluss an den Minuspol der Spannungsversorgung, VCC an den Pluspol, AREF für die Spannungsrefenz der AD-Einheit, usw.
Wir beschränken uns hier in diesem Kapitel mit den digitalen Eingängen, wobei erwähnt werden muss, das jeder Pin als Eingang, aber auch als Ausgang geschaltet bzw programmiert werden kann.
Aber das soll man in einem Tutorial ja auch lernen
Wenn man sich die Bascom-Zeile
Portb.5 = Pinc.5
aus UNO_Input1.BAS ansieht, dann könnte man meinen, das ein Eingangssignal direkt auf ein Ausgang umgeleitet werden kann.
Dem ist aber nicht so! Eingangs- und Ausgangszustände werden jeweils in Register gespeichert. Der Eingang zB wird im Register PINC, und den dafür zuständigen Eingang 5 ≡ PINC5 gepseichert.
Wie man sieht, ist PINC nur lesbar, nicht beschreibbar.
Am C-Beispiel sieht man nun, wie hardware-nahe C ist; der Eingangspin wird gelesen, und je nachdem, welcher Wert gelesen wurde, wird der Ausgang (hier Portb.5) ein- oder ausgeschaltet.
/***********************************************************************
* Programm: UNO_Input1
* Autor: Harald Rilling
* Plattform: Arduino Uno
*
* Datum: 25. November 2014
*
* HP: www.rillingpower.de
*
* Beschreibung: Eingang auf Ausgang kopieren
*
***********************************************************************/
#include <avr/io.h>
#include <util/delay.h>
// MCU name
#define MCU = atmega328p
// Konstanten
#define LED_Arduino PB5
int main (void) {
DDRB |= 0xFF; // PortB auf Ausgang
DDRC |= 0x00; // PortC auf Eingang
while(1) {
if (PINC & (1 << PINC5))
{
PORTB |= (1<<PORTB5); // Copy Input to Output
}
else
{
PORTB &= ~(1<<PORTB5); // Copy Input to Output
}
_delay_ms(19); // function aus delay.c
}
/* wird nie erreicht */
return 0;
}
Im Listing 3 soll ein Ausgang getogglet werden, dh, der aktuelle Zustand wird gewissermaßen invertiert.
1 → 0
0 → 1
Dazu wird das aus der Digitaltechnik bekannt XOR genutzt, das sogenannte Exklusiv-Oder oder auch Anti-Valenz Gatter
#include <avr/io.h>
#include <util/delay.h>
// MCU name
#define MCU = atmega328p
// Konstanten
#define LED_Arduino PB5
int main (void) {
DDRB |= 0xFF; // PortB auf Ausgang
DDRC |= 0x00; // PortC auf Eingang
while(1) {
if (PINC & (1 << PINC5)) // wenn Pinc.5 = 1
{
PORTB ^= (1<<PORTB5); // Toggle Portb.5
_delay_ms(250);
}
}
/* wird nie erreicht */
return 0;
}
Das ein "offener" Eingang schon mal viel Mist machen kann, sieht man am obigen Beispiel. Manchmal blinkt die gelbe LED ohne das der Eingang auf einem Potiential liegt, manchmal blinkt sie nicht. Der hochohmige Eingang benötigt ein festes Potential, um richtig zu funktionieren.
Dabei kommt der sogenannte PULL-UP oder PULL-DOWN - Widerstand zum tragen. Dieser verbindet direkt den Eingangsport mit hohem Potential (+5V → Pull-up) oder mit tiefen Potential ( 0V / GND → Pull-down).
Der AVR hat interne Pull-up-Widerstände, die zugeschalten werden, wenn ein Pin (über das DDRx-Register) als Eingang programmiert wird, und im PORTx-Register wird eine 1 eingeschrieben.
Im Quellcode wird das verdeutlicht:
#include <avr/io.h>
#include <util/delay.h>
// MCU name
#define MCU = atmega328p
// Konstanten
#define LED_Arduino PB5
int main (void) {
DDRB |= 0xFF; // PortB auf Ausgang
DDRC |= 0x00; // PortC auf Eingang
PORTC |= (1 << PC5); // Pullup einschalten
while(1) {
if (PINC & (1 << PINC5)) // wenn Pinc.5 = 1
{
PORTB ^= (1 << PB5); // Toggle Portb.5
_delay_ms(250);
}
else
{
PORTB &= ~(1 << PB5); // LED ausschalten = 0
}
}
/* wird nie erreicht */
return 0;
}