Portexpander PCF8574
Mit Hilfe eines Portexpanders, hier mit dem PCF8574, kann man die Anzahl der Ein- und Ausgänge eines Mikrocontrollers um 8 bidirektionale Ein-/Ausgänge (P0 - P7) erweitern, die bei einem Uno oder einem Attiny schnell einmal knapp werden können. Angesprochen werden die Ein- und Ausgänge (I/O-Port) dabei über die I2C-Schnittstelle.
Testaufbau PCF8574:
Verwendete Bauteile:
- 1 Arduino Uno oder Attiny45/85
- 1 Portexpander PCF8574
- 1 Widerstand 220 Ohm
- 2 Widerstände 10 kOhm
- 1 LED
- 1 Taster
Anschlussbelegung PCF8574:
Hinweis zur Beschaltung des PCF8574:
Als Ausgang programmiert können die einzelnen Ausgangspins des PCF8574 als Stromquelle nur Ströme in der Größenordnung von 100 µA liefern, als Stromsenke vertragen sie dagegen ca. 25 mA, also ausreichend um eine LED anzusteuern. Die LED leuchtet also, wenn sie anodenseitig auf 5 V liegt und der Ausgangspin auf LOW gesetzt wird.
Warum im Internet auch viele Beispiele existieren, die die LED über den Ausgangspin als Stromquelle ansteuern, ist mir nicht bekannt. Gibt es einen PCF8574-Typ der im HIGH-Zustand mehr als die angegebenen 100 µA liefern kann? Auch im Arduino Kochbuch von O'Reilly ist das Beispiel auf Seite 449, meiner Meinung nach, falsch dargestellt.
Beispiele über die Beschaltung der Ein- bzw. Ausgänge des Portexpanders findet man z.B. hier: www.mikrocontroller.net/articles/Port-Expander_PCF8574
I2C-Adresse:
Die I2C-Adresse ist hardwaremäßig über die Adresseingänge A0 - A2 an der Porterweiterung einstellbar. Jedoch ist der Adressbereich nicht bei allen PCF8574x-Typen gleich. Bisher habe ich folgende Adressen bzw. Adressbereiche festgestellt:
- PCF8574N, PCF8574P und PCF8574T: 0x20 bis 0x27
- PCF8574AN, PCF8574AT: 0x38 bis 0x3F
Librariy MyPCF8574 für Arduino und Attiny45/85
Folgende Funktionen stehen derzeit zur Verfügung:
- Abfrage, ob der Baustein über I2C ansprechbar ist
Verwendung von Pins als Eingänge: 1)
- Ein Byte wird vom I/O-Port gelesen
- Ein einzelnes Bit wird vom I/O-Port gelesen
Verwendung von Pins als Ausgänge:
- Ein Byte wird in den I/O-Port geschrieben
- Ein einzelnes Bit wird im I/O-Port HIGH oder LOW gesetzt, ohne die anderen Bits zu verändern
- Ein einzelnes Bit wird im I/O-Port auf HIGH gesetzt, ohne die anderen Bits zu verändern
- Ein einzelnes Bit wird im I/O-Port auf LOW gesetzt, ohne die anderen Bits zu verändern
- Ein Byte, als Ausgang betriebenen, wird vom I/O-Port zurückgelesen 2)
- Ein einzelnes Bit, als Ausgang betrieben, wird vom I/O-Port zurückgelesen 2)
- Der Zustand der einzelnen Bits des Ausgangsbyte wird negiert
- Der Zustand eines einzelnen Bit, als Ausgang betrieben, wird negiert
1) Der PCF8574 besitzt kein Datenrichtungsregister!
Pins, die als Eingänge verwendet werden, müssen vor dem Einlesen auf logisch 1 gesetzt werden (Aktivierung der internen Pullup-Widerstände). Das wird aber bereits in der Library gemacht!
2) Werden Pins vor dem Lesen nicht auf logisch 1 gesetzt, so können mit den Bit- bzw. Byte-Lese-Funktionen die binären Zustände von Ausgängen rückgelesen werden.
Die Library kann hier heruntergeladen werden:
Sollte die Library jemand verwenden oder testen, würde ich mich über eine Rückmeldung sehr freuen!
Version 2.1 für Arduino und Attiny45/85
Leider kann ich hier keine "cpp"- oder "h"-Files hochladen, daher zum Verwenden der Library das Suffix ".txt" aus diesen Dateinamen entfernen und in einem neuen Verzeichnis mit dem Namen "MyPCF8574" im Sketchbook-Ordner im Ordner "libraries" speichern.
Zur Auflistung der Funktionen der Library geht es hier: Funktionen
Eingesetzt wird die Library z.B. hier: 16er-Tastatur mit I2C (in der Library "MyKeypad_I2C_2")
Programmbeispiel MyPCF8574:
Im nachfolgenden Programmbeispiel für die Library MyPCF8574 wird - entsprechend dem Testaufbau -bei gedrücktem Taster (aktiv LOW) die LED eingeschaltet.
//Programmbeispiel für Portexpander PCF8574-Library
//Code fuer Arduino und Attiny45/85
//Author Retian
//Version 1.2
#include <MyPCF8574.h>
MyPCF8574 MyPCF;
#define keyPin 1 //Taste auf PCF8574 - Pin 1
#define ledPin 2 //LED auf PCF8574 - Pin 2
void setup() {
MyPCF.init(0x20); //oder 0x38 - I2C-Adresse des PCF8574
if (MyPCF.isReady()) //Wenn PCF8574 bereit, dann blinke 3x
{
MyPCF.writeBitLow(ledPin);
for (byte i = 0; i < 5; i++)
{
delay(300);
MyPCF.toggleBit(ledPin);
}
}
else while (1); //Im Fehlerfall geht's nicht weiter!
}
void loop() {
//Wenn Taster gedrückt (aktiv LOW), dann LED ein
if (MyPCF.readBit(keyPin) == 0) MyPCF.writeBit(ledPin, 0);
//Wenn Taster nicht gedrück, LED aus
else MyPCF.writeBit(ledPin, 1);
delay(100);
}