class I2C – ein serielles Zweidraht-Protokoll¶
I2C ist ein Zweidraht-Protokoll zur Kommunikation zwischen Geräten. Auf physikalischer Ebene besteht es aus 2 Leitungen: SCL und SDA, also der Takt- bzw. der Datenleitung.
I2C-Objekte werden mit einem bestimmten Bus verbunden erstellt. Sie können bei der Erstellung oder auch später initialisiert werden.
Das Ausgeben des I2C-Objekts liefert Informationen über seine Konfiguration.
Es existieren sowohl Hardware- als auch Software-I2C-Implementierungen über die Klassen I2C und SoftI2C. Hardware-I2C nutzt die zugrundeliegende Hardware-Unterstützung des Systems, um die Lese-/Schreibvorgänge durchzuführen, und ist üblicherweise effizient und schnell, kann aber Einschränkungen dahingehend haben, welche Pins verwendet werden können. Software-I2C wird per Bit-Banging implementiert und kann an jedem Pin verwendet werden, ist aber nicht so effizient. Diese Klassen bieten dieselben Methoden und unterscheiden sich hauptsächlich in der Art, wie sie konstruiert werden.
Bemerkung
Der I2C-Bus benötigt für seinen Betrieb eine Pull-up-Beschaltung an SDA und SCL. Üblicherweise sind dies Widerstände im Bereich von 1 - 10 kOhm, die jeweils von SDA/SCL nach Vcc geschaltet werden. Ohne diese ist das Verhalten undefiniert und kann von Blockieren über unerwartetes Watchdog-Reset bis hin zu schlicht falschen Werten reichen. Oft ist diese Pull-up-Beschaltung bereits auf der MCU-Platine oder auf Sensor-Breakout-Platinen integriert, doch eine Regel gibt es dafür nicht. Bitte prüfen Sie dies daher im Problemfall. Siehe auch diesen hervorragenden Lernleitfaden von Adafruit zur I2C-Verdrahtung.
Beispielverwendung:
from machine import I2C
i2c = I2C(freq=400000) # create I2C peripheral at frequency of 400kHz
# depending on the port, extra parameters may be required
# to select the peripheral and/or pins to use
i2c.scan() # scan for peripherals, returning a list of 7-bit addresses
i2c.writeto(42, b'123') # write 3 bytes to peripheral with 7-bit address 42
i2c.readfrom(42, 4) # read 4 bytes from peripheral with 7-bit address 42
i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of peripheral 42,
# starting at memory-address 8 in the peripheral
i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of peripheral 42
# starting at address 2 in the peripheral
Konstruktoren¶
- class machine.I2C(id: int, *, scl: Pin | None = None, sda: Pin | None = None, freq: int = 400000, timeout: int = 50000)¶
Konstruiert ein neues I2C-Objekt mit den folgenden Parametern und gibt es zurück:
id identifiziert ein bestimmtes I2C-Peripheriegerät. Die zulässigen Werte hängen vom jeweiligen Port/Board ab
scl sollte ein Pin-Objekt sein, das den für SCL zu verwendenden Pin angibt.
sda sollte ein Pin-Objekt sein, das den für SDA zu verwendenden Pin angibt.
freq sollte eine Ganzzahl sein, die die maximale Frequenz für SCL festlegt.
timeout ist die maximale Zeit in Mikrosekunden, die für I2C-Transaktionen erlaubt ist. Dieser Parameter ist auf einigen Ports nicht zulässig.
Beachten Sie, dass einige Ports/Boards Standardwerte für scl und sda haben, die in diesem Konstruktor geändert werden können. Andere haben feste Werte für scl und sda, die nicht geändert werden können.
Allgemeine Methoden¶
- init(scl: Pin, sda: Pin, *, freq: int = 400000) None¶
Initialisiert den I2C-Bus mit den angegebenen Argumenten:
scl ist ein Pin-Objekt für die SCL-Leitung
sda ist ein Pin-Objekt für die SDA-Leitung
freq ist die SCL-Taktrate
Im Fall von Hardware-I2C kann die tatsächliche Taktfrequenz niedriger sein als die angeforderte Frequenz. Dies hängt von der Plattform-Hardware ab. Die tatsächliche Rate lässt sich durch Ausgeben des I2C-Objekts ermitteln.
Primitive I2C-Operationen¶
Die folgenden Methoden implementieren die primitiven I2C-Controller-Busoperationen und können kombiniert werden, um jede beliebige I2C-Transaktion zu bilden. Sie werden bereitgestellt, falls Sie mehr Kontrolle über den Bus benötigen; andernfalls können die Standardmethoden (siehe unten) verwendet werden.
Diese Methoden sind nur in der Klasse
SoftI2Cverfügbar.- start() None¶
Erzeugt eine START-Bedingung auf dem Bus (SDA wechselt auf Low, während SCL High ist).
- readinto(buf: bytearray, nack: bool = True, /) None¶
Liest Bytes vom Bus und speichert sie in buf. Die Anzahl der gelesenen Bytes entspricht der Länge von buf. Nach dem Empfang aller Bytes außer dem letzten wird ein ACK auf den Bus gesendet. Nachdem das letzte Byte empfangen wurde, wird, falls nack true ist, ein NACK gesendet, andernfalls ein ACK (in diesem Fall geht das Peripheriegerät davon aus, dass in einem späteren Aufruf weitere Bytes gelesen werden).
Standard-Busoperationen¶
Die folgenden Methoden implementieren die Standard-I2C-Controller-Lese- und Schreiboperationen, die auf ein bestimmtes Peripheriegerät abzielen.
- readfrom(addr: int, nbytes: int, stop: bool = True, /) bytes¶
Liest nbytes von dem durch addr angegebenen Peripheriegerät. Wenn stop true ist, wird am Ende der Übertragung eine STOP-Bedingung erzeugt. Gibt ein
bytes-Objekt mit den gelesenen Daten zurück.
- readfrom_into(addr: int, buf: bytearray, stop: bool = True, /) None¶
Liest von dem durch addr angegebenen Peripheriegerät in buf. Die Anzahl der gelesenen Bytes entspricht der Länge von buf. Wenn stop true ist, wird am Ende der Übertragung eine STOP-Bedingung erzeugt.
Die Methode gibt
Nonezurück.
- writeto(addr: int, buf: bytes, stop: bool = True, /) int¶
Schreibt die Bytes aus buf an das durch addr angegebene Peripheriegerät. Wenn nach dem Schreiben eines Bytes aus buf ein NACK empfangen wird, werden die verbleibenden Bytes nicht gesendet. Wenn stop true ist, wird am Ende der Übertragung eine STOP-Bedingung erzeugt, selbst wenn ein NACK empfangen wird. Die Funktion gibt die Anzahl der empfangenen ACKs zurück.
- writevto(addr: int, vector: tuple | list, stop: bool = True, /) int¶
Schreibt die in vector enthaltenen Bytes an das durch addr angegebene Peripheriegerät. vector sollte ein Tupel oder eine Liste von Objekten mit dem Buffer-Protokoll sein. Die addr wird einmal gesendet, und dann werden die Bytes aus jedem Objekt in vector nacheinander ausgegeben. Die Objekte in vector dürfen eine Länge von null Bytes haben, in welchem Fall sie nichts zur Ausgabe beitragen.
Wenn nach dem Schreiben eines Bytes aus einem der Objekte in vector ein NACK empfangen wird, werden die verbleibenden Bytes sowie alle verbleibenden Objekte nicht gesendet. Wenn stop true ist, wird am Ende der Übertragung eine STOP-Bedingung erzeugt, selbst wenn ein NACK empfangen wird. Die Funktion gibt die Anzahl der empfangenen ACKs zurück.
Speicheroperationen¶
Einige I2C-Geräte verhalten sich wie ein Speichergerät (oder ein Satz von Registern), das gelesen und beschrieben werden kann. In diesem Fall sind mit einer I2C-Transaktion zwei Adressen verbunden: die Peripherieadresse und die Speicheradresse. Die folgenden Methoden sind Komfortfunktionen für die Kommunikation mit solchen Geräten.
- readfrom_mem(addr: int, memaddr: int, nbytes: int, *, addrsize: int = 8) bytes¶
Liest nbytes von dem durch addr angegebenen Peripheriegerät, beginnend bei der durch memaddr angegebenen Speicheradresse. Das Argument addrsize gibt die Adressgröße in Bits an. Gibt ein
bytes-Objekt mit den gelesenen Daten zurück.
- readfrom_mem_into(addr: int, memaddr: int, buf: bytearray, *, addrsize: int = 8) None¶
Liest von dem durch addr angegebenen Peripheriegerät in buf, beginnend bei der durch memaddr angegebenen Speicheradresse. Die Anzahl der gelesenen Bytes entspricht der Länge von buf. Das Argument addrsize gibt die Adressgröße in Bits an.
Die Methode gibt
Nonezurück.
class SoftI2C – ein softwareemulierter I2C-Bus¶
Die Klasse SoftI2C implementiert I2C durch Bit-Banging beliebiger GPIO-Pins. Sie bietet dieselbe Methodenoberfläche wie I2C zuzüglich der primitiven Low-Level-Busoperationen (start(), stop(), readinto(), write()) für Aufrufer, die nicht standardmäßige Transaktionen zusammenstellen müssen. Verwenden Sie sie, wenn die benötigten Pins nicht mit einem Hardware-I2C-Block verdrahtet sind, wenn Sie mehr Busse benötigen, als die Hardware bietet, oder um mit Geräten zu kommunizieren, die ungewöhnliche Sequenzen erfordern (zusätzliche Takte, wiederholte Starts nach Schreibvorgängen usw.).
Konstruktoren¶
- class machine.SoftI2C(scl: Pin, sda: Pin, *, freq: int = 400000, timeout: int = 50000)¶
Konstruiert einen Software-I2C-Bus, der von
scl/sdaangesteuert wird.freqist die angestrebte SCL-Taktrate in Hz (die tatsächliche Rate ist aufgrund des Overheads der Bit-Bang-Schleife typischerweise niedriger).timeoutist die maximale Zeit in Mikrosekunden, die auf Clock-Stretching gewartet wird (SCL wird von einem anderen Gerät auf dem Bus auf Low gehalten); bei Ablauf wird einOSError(ETIMEDOUT)ausgelöst.Allgemeine Methoden¶
Primitive I2C-Operationen¶
Die folgenden Methoden implementieren die primitiven I2C-Controller-Busoperationen und können kombiniert werden, um jede beliebige I2C-Transaktion zu bilden. Sie sind ausschließlich für SoftI2C verfügbar – die Hardware-Klasse
I2Cstellt sie nicht bereit.- start() None¶
Erzeugt eine START-Bedingung auf dem Bus (SDA wechselt auf Low, während SCL High ist).
- readinto(buf: bytearray, nack: bool = True, /) None¶
Liest Bytes vom Bus in
buf. Es werdenlen(buf)Bytes gelesen; nach jedem Byte außer dem letzten wird ein ACK gesendet. Nach dem letzten Byte sendetnack=True(der Standard) ein NACK, um die Übertragung zu beenden;nack=Falsesendet ein ACK, sodass das Gerät für ein nachfolgendesreadinto()ausgewählt bleibt.
Standard-Busoperationen¶
Die folgenden Methoden implementieren die Standard-I2C-Controller-Lese- und Schreiboperationen, die auf ein bestimmtes Peripheriegerät abzielen.
- readfrom(addr: int, nbytes: int, stop: bool = True, /) bytes¶
Liest
nbytesvon dem Gerät mit der 7-Bit-Adresseaddr. Wennstoptrue ist, wird am Ende der Übertragung eine STOP-Bedingung erzeugt.
- readfrom_into(addr: int, buf: bytearray, stop: bool = True, /) None¶
Liest
len(buf)Bytes von dem Gerät mit der Adresseaddrinbuf. Wennstoptrue ist, wird am Ende der Übertragung eine STOP-Bedingung erzeugt.
- writeto(addr: int, buf: bytes, stop: bool = True, /) int¶
Schreibt
bufan das Gerät mit der Adresseaddr. Die Übertragung stoppt beim ersten NACK. Wennstoptrue ist, wird am Ende der Übertragung immer eine STOP-Bedingung erzeugt (auch bei einem frühen NACK). Gibt die Anzahl der empfangenen ACKs zurück.
Speicheroperationen¶
Einige I2C-Geräte verhalten sich wie ein Speichergerät (oder ein Satz von Registern), das gelesen und beschrieben werden kann. In diesem Fall sind mit einer I2C-Transaktion zwei Adressen verbunden: die Peripherieadresse und die Speicheradresse. Die folgenden Methoden sind Komforthelfer für die Kommunikation mit solchen Geräten.
- readfrom_mem(addr: int, memaddr: int, nbytes: int, *, addrsize: int = 8) bytes¶
Liest
nbytesvon dem Gerät mit der Adresseaddr, beginnend beim Registermemaddr.addrsizeist die Breite der Registeradresse in Bits (typischerweise8oder16).