class I2C – kaksijohtiminen sarjaprotokolla

I2C on kaksijohtiminen protokolla laitteiden väliseen tiedonsiirtoon. Fyysisellä tasolla se koostuu kahdesta johtimesta: SCL ja SDA, eli kello- ja datalinjasta.

I2C-objektit luodaan liitettyinä tiettyyn väylään. Ne voidaan alustaa luonnin yhteydessä tai myöhemmin.

I2C-objektin tulostaminen antaa tietoa sen kokoonpanosta.

Sekä laitteistopohjaisia että ohjelmistopohjaisia I2C-toteutuksia on olemassa I2C- ja SoftI2C-luokkien kautta. Laitteistopohjainen I2C käyttää järjestelmän laitteistotukea luku- ja kirjoitusoperaatioiden suorittamiseen, ja se on yleensä tehokas ja nopea, mutta voi asettaa rajoituksia siihen, mitä nastoja voidaan käyttää. Ohjelmistopohjainen I2C toteutetaan bittien manuaalisella ohjauksella (bit-banging), ja sitä voidaan käyttää millä tahansa nastalla, mutta se ei ole yhtä tehokas. Näillä luokilla on käytettävissä samat metodit, ja ne eroavat toisistaan ensisijaisesti siinä, miten ne luodaan.

Muista

I2C-väylä vaatii toimiakseen ylösvetokytkennän sekä SDA- että SCL-linjoille. Yleensä nämä ovat vastuksia välillä 1–10 kOhm, jotka on kytketty kustakin SDA/SCL-linjasta Vcc:hen. Ilman näitä käyttäytyminen on määrittelemätöntä ja voi vaihdella jumiutumisesta ja odottamattomasta vahtikoiran (watchdog) nollauksesta aina pelkästään virheellisiin arvoihin. Usein tämä ylösvetokytkentä on jo sisäänrakennettu MCU-korttiin tai sensorin laajennuskortteihin, mutta tästä ei ole mitään sääntöä. Tarkista siis tämä ongelmatilanteissa. Katso myös tämä erinomainen Adafruitin oppimisopas I2C-johdotuksesta.

Esimerkki käytöstä:

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

Konstruktorit

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

Luo ja palauta uusi I2C-objekti käyttäen seuraavia parametreja:

  • id yksilöi tietyn I2C-oheislaitteen. Sallitut arvot riippuvat tietystä portista/kortista

  • scl tulee olla pin-objekti, joka määrittää SCL-linjalle käytettävän nastan.

  • sda tulee olla pin-objekti, joka määrittää SDA-linjalle käytettävän nastan.

  • freq tulee olla kokonaisluku, joka asettaa SCL:n enimmäistaajuuden.

  • timeout on enimmäisaika mikrosekunteina, joka sallitaan I2C-tapahtumille. Tätä parametria ei sallita kaikissa porteissa.

Huomaa, että joillakin porteilla/korteilla on oletusarvot scl:lle ja sda:lle, jotka voidaan muuttaa tässä konstruktorissa. Toisilla on kiinteät scl- ja sda-arvot, joita ei voi muuttaa.

Yleiset metodit

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

Alusta I2C-väylä annetuilla argumenteilla:

  • scl on pin-objekti SCL-linjaa varten

  • sda on pin-objekti SDA-linjaa varten

  • freq on SCL-kellotaajuus

Laitteistopohjaisen I2C:n tapauksessa todellinen kellotaajuus voi olla pyydettyä taajuutta alhaisempi. Tämä riippuu alustan laitteistosta. Todellinen taajuus voidaan selvittää tulostamalla I2C-objekti.

scan() List[int]

Skannaa kaikki I2C-osoitteet välillä 0x08–0x77 (mukaan lukien) ja palauta lista niistä, jotka vastaavat. Laite vastaa, jos se vetää SDA-linjan alas sen jälkeen, kun sen osoite (mukaan lukien kirjoitusbitti) on lähetetty väylälle.

I2C:n primitiivioperaatiot

Seuraavat metodit toteuttavat I2C-ohjaimen primitiiviset väyläoperaatiot, ja ne voidaan yhdistää minkä tahansa I2C-tapahtuman muodostamiseksi. Ne ovat saatavilla, jos tarvitset enemmän hallintaa väylästä; muutoin voidaan käyttää vakiometodeja (katso alta).

Nämä metodit ovat saatavilla vain SoftI2C-luokassa.

start() None

Muodosta väylälle START-ehto (SDA siirtyy alas SCL:n ollessa ylhäällä).

stop() None

Muodosta väylälle STOP-ehto (SDA siirtyy ylös SCL:n ollessa ylhäällä).

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

Lukee tavuja väylältä ja tallentaa ne buf-puskuriin. Luettujen tavujen määrä on buf:n pituus. ACK lähetetään väylälle jokaisen vastaanotetun tavun jälkeen viimeistä lukuun ottamatta. Viimeisen tavun vastaanottamisen jälkeen, jos nack on tosi, lähetetään NACK, muutoin lähetetään ACK (ja tässä tapauksessa oheislaite olettaa, että lisää tavuja luetaan myöhemmässä kutsussa).

write(buf: bytes) int

Kirjoita tavut buf-puskurista väylälle. Tarkistaa, että ACK vastaanotetaan jokaisen tavun jälkeen, ja lopettaa loppujen tavujen lähettämisen, jos NACK vastaanotetaan. Funktio palauttaa vastaanotettujen ACK-kuittausten määrän.

Vakioväyläoperaatiot

Seuraavat metodit toteuttavat I2C-ohjaimen vakioluku- ja vakiokirjoitusoperaatiot, jotka kohdistuvat tiettyyn oheislaitteeseen.

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

Lue nbytes tavua addr:lla määritetystä oheislaitteesta. Jos stop on tosi, siirron lopussa muodostetaan STOP-ehto. Palauttaa bytes-objektin luetun datan kanssa.

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

Lue addr:lla määritetystä oheislaitteesta buf-puskuriin. Luettujen tavujen määrä on buf:n pituus. Jos stop on tosi, siirron lopussa muodostetaan STOP-ehto.

Metodi palauttaa None.

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

Kirjoita tavut buf-puskurista addr:lla määritettyyn oheislaitteeseen. Jos NACK vastaanotetaan buf:n tavun kirjoituksen jälkeen, loppuja tavuja ei lähetetä. Jos stop on tosi, siirron lopussa muodostetaan STOP-ehto, vaikka NACK olisi vastaanotettu. Funktio palauttaa vastaanotettujen ACK-kuittausten määrän.

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

Kirjoita vector:ssa olevat tavut addr:lla määritettyyn oheislaitteeseen. vector:n tulee olla monikko tai lista objekteja, jotka tukevat puskuriprotokollaa. addr lähetetään kerran, minkä jälkeen kunkin vector:n objektin tavut kirjoitetaan ulos peräkkäin. vector:n objektit voivat olla pituudeltaan nolla tavua, jolloin ne eivät vaikuta tulosteeseen.

Jos NACK vastaanotetaan jonkin vector:n objektin tavun kirjoituksen jälkeen, loppuja tavuja ja jäljellä olevia objekteja ei lähetetä. Jos stop on tosi, siirron lopussa muodostetaan STOP-ehto, vaikka NACK olisi vastaanotettu. Funktio palauttaa vastaanotettujen ACK-kuittausten määrän.

Muistioperaatiot

Jotkin I2C-laitteet toimivat muistilaitteena (tai rekisterijoukkona), josta voidaan lukea ja johon voidaan kirjoittaa. Tässä tapauksessa I2C-tapahtumaan liittyy kaksi osoitetta: oheislaitteen osoite ja muistiosoite. Seuraavat metodit ovat apufunktioita tällaisten laitteiden kanssa kommunikointiin.

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

Lue nbytes tavua addr:lla määritetystä oheislaitteesta alkaen memaddr:lla määritetystä muistiosoitteesta. Argumentti addrsize määrittää osoitteen koon bitteinä. Palauttaa bytes-objektin luetun datan kanssa.

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

Lue addr:lla määritetystä oheislaitteesta buf-puskuriin alkaen memaddr:lla määritetystä muistiosoitteesta. Luettujen tavujen määrä on buf:n pituus. Argumentti addrsize määrittää osoitteen koon bitteinä.

Metodi palauttaa None.

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

Kirjoita buf addr:lla määritettyyn oheislaitteeseen alkaen memaddr:lla määritetystä muistiosoitteesta. Argumentti addrsize määrittää osoitteen koon bitteinä.

Metodi palauttaa None.

class SoftI2C – ohjelmistoemuloitu I2C-väylä

SoftI2C-luokka toteuttaa I2C:n ohjaamalla mielivaltaisia GPIO-nastoja bittitasolla (bit-banging). Se tarjoaa saman metodipinnan kuin I2C sekä matalan tason primitiiviset väyläoperaatiot (start(), stop(), readinto(), write()) niitä kutsujia varten, jotka tarvitsevat epästandardien tapahtumien kokoamista. Käytä sitä, kun tarvitsemiasi nastoja ei ole kytketty laitteistopohjaiseen I2C-lohkoon, kun tarvitset enemmän väyliä kuin laitteisto tarjoaa, tai kun haluat kommunikoida laitteiden kanssa, jotka vaativat epätavallisia sekvenssejä (ylimääräisiä kelloja, toistettuja startteja kirjoitusten jälkeen jne.).

Konstruktorit

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

Muodosta ohjelmistopohjainen I2C-väylä, jota ohjaavat scl / sda.

freq on kohde-SCL-kellotaajuus hertseinä (todellinen taajuus on tyypillisesti alhaisempi bit-bang-silmukan yleisrasitteen vuoksi).

timeout on enimmäisaika mikrosekunteina, joka odotetaan kellon venyttämistä (clock stretching) varten (toinen väylän laite pitää SCL:n alhaalla); ajan umpeutuessa nostetaan OSError(ETIMEDOUT).

Yleiset metodit

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

Alusta ohjelmistopohjainen I2C-väylä uudelleen annetuilla nastoilla ja taajuudella. Vastaa uuden SoftI2C:n muodostamista samaan objektiin.

scan() List[int]

Skannaa kaikki I2C-osoitteet välillä 0x08–0x77 (mukaan lukien) ja palauta lista niistä, jotka vastasivat.

I2C:n primitiivioperaatiot

Seuraavat metodit toteuttavat I2C-ohjaimen primitiiviset väyläoperaatiot, ja ne voidaan yhdistää minkä tahansa I2C-tapahtuman muodostamiseksi. Ne ovat vain SoftI2C-luokassa – laitteistopohjainen I2C-luokka ei tarjoa niitä.

start() None

Muodosta väylälle START-ehto (SDA siirtyy alas SCL:n ollessa ylhäällä).

stop() None

Muodosta väylälle STOP-ehto (SDA siirtyy ylös SCL:n ollessa ylhäällä).

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

Lue tavuja väylältä buf-puskuriin. Luetaan len(buf) tavua; ACK lähetetään jokaisen tavun jälkeen viimeistä lukuun ottamatta. Viimeisen tavun jälkeen nack=True (oletus) lähettää NACK:n siirron päättämiseksi; nack=False lähettää ACK:n, jolloin laite pysyy valittuna seuraavaa readinto()-kutsua varten.

write(buf: bytes) int

Kirjoita buf väylälle ja tarkista ACK jokaisen tavun jälkeen. Lähetys pysähtyy ensimmäiseen NACK:iin. Palauttaa vastaanotettujen ACK-kuittausten määrän.

Vakioväyläoperaatiot

Seuraavat metodit toteuttavat I2C-ohjaimen vakioluku- ja vakiokirjoitusoperaatiot, jotka kohdistuvat tiettyyn oheislaitteeseen.

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

Lue nbytes tavua laitteesta 7-bittisessä osoitteessa addr. Jos stop on tosi, siirron lopussa muodostetaan STOP-ehto.

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

Lue len(buf) tavua laitteesta osoitteessa addr buf-puskuriin. Jos stop on tosi, siirron lopussa muodostetaan STOP-ehto.

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

Kirjoita buf laitteeseen osoitteessa addr. Lähetys pysähtyy ensimmäiseen NACK:iin. Jos stop on tosi, siirron lopussa muodostetaan aina STOP-ehto (myös aikaisen NACK:in tapauksessa). Palauttaa vastaanotettujen ACK-kuittausten määrän.

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

Kirjoita vector:n puskureiden yhdistelmä laitteeseen osoitteessa addr yhtenä tapahtumana. Tyhjät puskurit ohitetaan. Toimii stop-semantiikan ja paluuarvon osalta kuten writeto().

Muistioperaatiot

Jotkin I2C-laitteet toimivat muistilaitteena (tai rekisterijoukkona), josta voidaan lukea ja johon voidaan kirjoittaa. Tässä tapauksessa I2C-tapahtumaan liittyy kaksi osoitetta: oheislaitteen osoite ja muistiosoite. Seuraavat metodit ovat apuvälineitä tällaisten laitteiden kanssa kommunikointiin.

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

Lue nbytes tavua laitteesta osoitteessa addr alkaen rekisteristä memaddr. addrsize on rekisteriosoitteen leveys bitteinä (tyypillisesti 8 tai 16).

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

Lue laitteesta osoitteessa addr buf-puskuriin alkaen rekisteristä memaddr.

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

Kirjoita buf laitteeseen osoitteessa addr alkaen rekisteristä memaddr.