class I2C – ett tvåtrådigt seriellt protokoll

I2C är ett tvåtrådigt protokoll för kommunikation mellan enheter. På den fysiska nivån består det av 2 ledningar: SCL och SDA, klock- respektive dataledningen.

I2C-objekt skapas anslutna till en specifik buss. De kan initialiseras vid skapandet eller initialiseras senare.

Att skriva ut I2C-objektet ger dig information om dess konfiguration.

Det finns både hårdvaru- och mjukvaruimplementationer av I2C via klasserna I2C och SoftI2C. Hårdvaru-I2C använder systemets underliggande hårdvarustöd för att utföra läsningarna/skrivningarna och är vanligtvis effektiv och snabb, men kan ha begränsningar för vilka stift som kan användas. Mjukvaru-I2C implementeras genom bit-banging och kan användas på vilket stift som helst, men är inte lika effektiv. Dessa klasser har samma metoder tillgängliga och skiljer sig främst i hur de konstrueras.

Anteckning

I2C-bussen kräver pull-up-kretsar på både SDA och SCL för att fungera. Vanligtvis är detta motstånd i intervallet 1 - 10 kOhm, anslutna från varje SDA/SCL till Vcc. Utan dessa är beteendet odefinierat och kan variera från blockering och oväntad watchdog-återställning till bara felaktiga värden. Ofta är dessa pull-up-kretsar redan inbyggda i MCU-kortet eller sensorernas breakout-kort, men det finns ingen regel för det. Kontrollera därför vid problem. Se även den utmärkta lärguiden från Adafruit om I2C-kabeldragning.

Exempel på användning:

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

Konstruktorer

class machine.I2C(id: int, *, scl: Pin | None = None, sda: Pin | None = None, freq: int = 400000, timeout: int = 50000)

Konstruera och returnera ett nytt I2C-objekt med följande parametrar:

  • id identifierar en viss I2C-kringutrustning. Tillåtna värden beror på den specifika porten/kortet

  • scl ska vara ett stiftobjekt som anger vilket stift som ska användas för SCL.

  • sda ska vara ett stiftobjekt som anger vilket stift som ska användas för SDA.

  • freq ska vara ett heltal som anger den maximala frekvensen för SCL.

  • timeout är den maximala tiden i mikrosekunder som tillåts för I2C-transaktioner. Denna parameter är inte tillåten på vissa portar.

Observera att vissa portar/kort har standardvärden för scl och sda som kan ändras i denna konstruktor. Andra har fasta värden för scl och sda som inte kan ändras.

Allmänna metoder

init(scl: Pin, sda: Pin, *, freq: int = 400000) None

Initialisera I2C-bussen med de angivna argumenten:

  • scl är ett stiftobjekt för SCL-ledningen

  • sda är ett stiftobjekt för SDA-ledningen

  • freq är SCL-klockfrekvensen

I fallet med hårdvaru-I2C kan den faktiska klockfrekvensen vara lägre än den begärda frekvensen. Detta beror på plattformens hårdvara. Den faktiska frekvensen kan fastställas genom att skriva ut I2C-objektet.

scan() List[int]

Skanna alla I2C-adresser mellan 0x08 och 0x77 inklusive och returnera en lista över dem som svarar. En enhet svarar om den drar SDA-ledningen låg efter att dess adress (inklusive en skrivbit) har skickats på bussen.

Primitiva I2C-operationer

Följande metoder implementerar de primitiva I2C-styrenhetens bussoperationer och kan kombineras för att skapa vilken I2C-transaktion som helst. De tillhandahålls om du behöver mer kontroll över bussen, annars kan standardmetoderna (se nedan) användas.

Dessa metoder är endast tillgängliga i klassen SoftI2C.

start() None

Generera ett START-villkor på bussen (SDA övergår till låg medan SCL är hög).

stop() None

Generera ett STOP-villkor på bussen (SDA övergår till hög medan SCL är hög).

readinto(buf: bytearray, nack: bool = True, /) None

Läser byte från bussen och lagrar dem i buf. Antalet byte som läses är längden på buf. En ACK skickas på bussen efter att alla utom den sista byten har tagits emot. Efter att den sista byten har tagits emot skickas en NACK om nack är sant, annars skickas en ACK (och i detta fall antar kringutrustningen att fler byte kommer att läsas i ett senare anrop).

write(buf: bytes) int

Skriver byten från buf till bussen. Kontrollerar att en ACK tas emot efter varje byte och slutar sända de återstående byten om en NACK tas emot. Funktionen returnerar antalet ACK:ar som togs emot.

Standardbussoperationer

Följande metoder implementerar de standardiserade I2C-styrenhetens läs- och skrivoperationer som riktar sig mot en given kringutrustningsenhet.

readfrom(addr: int, nbytes: int, stop: bool = True, /) bytes

Läs nbytes från kringutrustningen som anges av addr. Om stop är sant genereras ett STOP-villkor i slutet av överföringen. Returnerar ett bytes-objekt med de lästa data.

readfrom_into(addr: int, buf: bytearray, stop: bool = True, /) None

Läs in i buf från kringutrustningen som anges av addr. Antalet byte som läses är längden på buf. Om stop är sant genereras ett STOP-villkor i slutet av överföringen.

Metoden returnerar None.

writeto(addr: int, buf: bytes, stop: bool = True, /) int

Skriv byten från buf till kringutrustningen som anges av addr. Om en NACK tas emot efter skrivning av en byte från buf skickas inte de återstående byten. Om stop är sant genereras ett STOP-villkor i slutet av överföringen, även om en NACK tas emot. Funktionen returnerar antalet ACK:ar som togs emot.

writevto(addr: int, vector: tuple | list, stop: bool = True, /) int

Skriv byten som finns i vector till kringutrustningen som anges av addr. vector ska vara en tupel eller lista med objekt som har buffertprotokollet. addr skickas en gång och sedan skrivs byten från varje objekt i vector ut sekventiellt. Objekten i vector kan vara noll byte långa, i vilket fall de inte bidrar till utdatan.

Om en NACK tas emot efter skrivning av en byte från ett av objekten i vector skickas inte de återstående byten och eventuella återstående objekt. Om stop är sant genereras ett STOP-villkor i slutet av överföringen, även om en NACK tas emot. Funktionen returnerar antalet ACK:ar som togs emot.

Minnesoperationer

Vissa I2C-enheter fungerar som en minnesenhet (eller en uppsättning register) som kan läsas från och skrivas till. I detta fall finns det två adresser kopplade till en I2C-transaktion: kringutrustningsadressen och minnesadressen. Följande metoder är bekvämlighetsfunktioner för att kommunicera med sådana enheter.

readfrom_mem(addr: int, memaddr: int, nbytes: int, *, addrsize: int = 8) bytes

Läs nbytes från kringutrustningen som anges av addr med början från minnesadressen som anges av memaddr. Argumentet addrsize anger adressstorleken i bitar. Returnerar ett bytes-objekt med de lästa data.

readfrom_mem_into(addr: int, memaddr: int, buf: bytearray, *, addrsize: int = 8) None

Läs in i buf från kringutrustningen som anges av addr med början från minnesadressen som anges av memaddr. Antalet byte som läses är längden på buf. Argumentet addrsize anger adressstorleken i bitar.

Metoden returnerar None.

writeto_mem(addr: int, memaddr: int, buf: bytes, *, addrsize: int = 8) None

Skriv buf till kringutrustningen som anges av addr med början från minnesadressen som anges av memaddr. Argumentet addrsize anger adressstorleken i bitar.

Metoden returnerar None.

class SoftI2C – en mjukvaruemulerad I2C-buss

Klassen SoftI2C implementerar I2C genom bit-banging av godtyckliga GPIO-stift. Den exponerar samma metodyta som I2C plus de lågnivåprimitiva bussoperationerna (start(), stop(), readinto(), write()) för anropare som behöver sätta samman icke-standardiserade transaktioner. Använd den när de stift du behöver inte är kopplade till ett hårdvaru-I2C-block, när du behöver fler bussar än hårdvaran erbjuder, eller för att kommunicera med enheter som kräver ovanliga sekvenser (extra klockpulser, upprepade starter efter skrivningar osv.).

Konstruktorer

class machine.SoftI2C(scl: Pin, sda: Pin, *, freq: int = 400000, timeout: int = 50000)

Konstruera en mjukvaru-I2C-buss som drivs av scl / sda.

freq är mål-SCL-klockfrekvensen i Hz (den faktiska frekvensen är vanligtvis lägre på grund av bit-bang-loopens overhead).

timeout är den maximala tiden i mikrosekunder att vänta på clock stretching (SCL hålls låg av en annan enhet på bussen); vid utgång genereras ett OSError(ETIMEDOUT).

Allmänna metoder

init(scl: Pin, sda: Pin, *, freq: int = 400000) None

Återinitialisera mjukvaru-I2C-bussen med de angivna stiften och frekvensen. Motsvarar att konstruera en ny SoftI2C på samma objekt.

scan() List[int]

Skanna alla I2C-adresser mellan 0x08 och 0x77 inklusive och returnera en lista över dem som svarade.

Primitiva I2C-operationer

Följande metoder implementerar de primitiva I2C-styrenhetens bussoperationer och kan kombineras för att skapa vilken I2C-transaktion som helst. De är endast tillgängliga för SoftI2C – hårdvaruklassen I2C exponerar dem inte.

start() None

Generera ett START-villkor på bussen (SDA övergår till låg medan SCL är hög).

stop() None

Generera ett STOP-villkor på bussen (SDA övergår till hög medan SCL är hög).

readinto(buf: bytearray, nack: bool = True, /) None

Läs byte från bussen in i buf. len(buf) byte läses; en ACK skickas efter varje byte utom den sista. Efter den sista byten skickar nack=True (standardvärdet) en NACK för att avsluta överföringen; nack=False skickar en ACK så att enheten förblir vald för en efterföljande readinto().

write(buf: bytes) int

Skriv buf till bussen och kontrollera ACK efter varje byte. Sändningen stoppas vid den första NACK:en. Returnerar antalet mottagna ACK:ar.

Standardbussoperationer

Följande metoder implementerar de standardiserade I2C-styrenhetens läs- och skrivoperationer som riktar sig mot en given kringutrustningsenhet.

readfrom(addr: int, nbytes: int, stop: bool = True, /) bytes

Läs nbytes från enheten på den 7-bitars adressen addr. Om stop är sant genereras ett STOP-villkor i slutet av överföringen.

readfrom_into(addr: int, buf: bytearray, stop: bool = True, /) None

Läs len(buf) byte från enheten på addr in i buf. Om stop är sant genereras ett STOP-villkor i slutet av överföringen.

writeto(addr: int, buf: bytes, stop: bool = True, /) int

Skriv buf till enheten på addr. Sändningen stoppas vid den första NACK:en. Om stop är sant genereras alltid ett STOP-villkor i slutet av överföringen (även vid tidig NACK). Returnerar antalet mottagna ACK:ar.

writevto(addr: int, vector: tuple | list, stop: bool = True, /) int

Skriv sammanfogningen av buffertarna i vector till enheten på addr som en enda transaktion. Tomma buffertar ignoreras. Beter sig som writeto() vad gäller stop-semantik och returvärde.

Minnesoperationer

Vissa I2C-enheter fungerar som en minnesenhet (eller en uppsättning register) som kan läsas från och skrivas till. I detta fall finns det två adresser kopplade till en I2C-transaktion: kringutrustningsadressen och minnesadressen. Följande metoder är bekvämlighetshjälpmedel för att kommunicera med sådana enheter.

readfrom_mem(addr: int, memaddr: int, nbytes: int, *, addrsize: int = 8) bytes

Läs nbytes från enheten på addr med början på registret memaddr. addrsize är registeradressens bredd i bitar (vanligtvis 8 eller 16).

readfrom_mem_into(addr: int, memaddr: int, buf: bytearray, *, addrsize: int = 8) None

Läs in i buf från enheten på addr med början på registret memaddr.

writeto_mem(addr: int, memaddr: int, buf: bytes, *, addrsize: int = 8) None

Skriv buf till enheten på addr med början på registret memaddr.