kelas I2C -- protokol serial dua kabel

I2C adalah protokol dua kabel untuk komunikasi antar perangkat. Pada level fisik, terdiri dari 2 kabel: SCL dan SDA, masing-masing merupakan jalur clock dan data.

Objek I2C dibuat dan dikaitkan dengan bus tertentu. Objek dapat diinisialisasi saat dibuat, atau diinisialisasi di kemudian waktu.

Mencetak objek I2C akan memberikan informasi tentang konfigurasinya.

Implementasi I2C hardware maupun software tersedia melalui kelas I2C dan SoftI2C. I2C hardware menggunakan dukungan hardware yang mendasari sistem untuk melakukan operasi baca/tulis dan biasanya efisien dan cepat, namun mungkin memiliki batasan pada pin mana yang dapat digunakan. I2C software diimplementasikan dengan cara bit-banging dan dapat digunakan pada pin apa pun, tetapi tidak seefisien. Kelas-kelas ini memiliki metode yang sama dan berbeda terutama dalam cara pembuatannya.

Catatan

Bus I2C memerlukan rangkaian pull-up pada SDA dan SCL agar dapat beroperasi. Biasanya berupa resistor dengan rentang 1 - 10 kOhm, yang dihubungkan dari masing-masing SDA/SCL ke Vcc. Tanpa rangkaian ini, perilaku tidak terdefinisi dan dapat berkisar dari pemblokiran, reset watchdog yang tidak terduga hingga nilai yang salah. Seringkali, rangkaian pull-up ini sudah terpasang di board MCU atau board breakout sensor, tetapi tidak ada aturan yang pasti. Jadi silakan periksa jika terjadi masalah. Lihat juga panduan belajar yang sangat baik dari Adafruit tentang wiring I2C.

Contoh penggunaan:

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

Konstruktor

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

Membangun dan mengembalikan objek I2C baru menggunakan parameter berikut:

  • id mengidentifikasi periferal I2C tertentu. Nilai yang diizinkan bergantung pada port/board tertentu

  • scl harus berupa objek pin yang menentukan pin yang digunakan untuk SCL.

  • sda harus berupa objek pin yang menentukan pin yang digunakan untuk SDA.

  • freq harus berupa bilangan bulat yang menetapkan frekuensi maksimum untuk SCL.

  • timeout adalah waktu maksimum dalam mikrodetik yang diizinkan untuk transaksi I2C. Parameter ini tidak diizinkan pada beberapa port.

Perhatikan bahwa beberapa port/board akan memiliki nilai default scl dan sda yang dapat diubah dalam konstruktor ini. Yang lain akan memiliki nilai tetap scl dan sda yang tidak dapat diubah.

Metode Umum

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

Inisialisasi bus I2C dengan argumen yang diberikan:

  • scl adalah objek pin untuk jalur SCL

  • sda adalah objek pin untuk jalur SDA

  • freq adalah laju clock SCL

Dalam kasus I2C hardware, frekuensi clock aktual mungkin lebih rendah dari frekuensi yang diminta. Hal ini bergantung pada hardware platform. Laju aktual dapat ditentukan dengan mencetak objek I2C.

scan() List[int]

Memindai semua alamat I2C antara 0x08 dan 0x77 (inklusif) dan mengembalikan daftar yang memberikan respons. Suatu perangkat merespons jika menarik jalur SDA ke rendah setelah alamatnya (termasuk bit tulis) dikirim di bus.

Operasi I2C Primitif

Metode-metode berikut mengimplementasikan operasi bus I2C controller primitif dan dapat dikombinasikan untuk membuat transaksi I2C apa pun. Metode ini tersedia jika Anda memerlukan lebih banyak kontrol atas bus, jika tidak, metode standar (lihat di bawah) dapat digunakan.

Metode-metode ini hanya tersedia pada kelas SoftI2C.

start() None

Menghasilkan kondisi START pada bus (SDA beralih ke rendah saat SCL tinggi).

stop() None

Menghasilkan kondisi STOP pada bus (SDA beralih ke tinggi saat SCL tinggi).

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

Membaca byte dari bus dan menyimpannya ke dalam buf. Jumlah byte yang dibaca adalah panjang buf. ACK akan dikirim di bus setelah menerima semua byte kecuali yang terakhir. Setelah byte terakhir diterima, jika nack bernilai true maka NACK akan dikirim, jika tidak maka ACK akan dikirim (dan dalam kasus ini periferal mengasumsikan lebih banyak byte akan dibaca dalam panggilan berikutnya).

write(buf: bytes) int

Menulis byte dari buf ke bus. Memeriksa bahwa ACK diterima setelah setiap byte dan menghentikan transmisi byte yang tersisa jika NACK diterima. Fungsi ini mengembalikan jumlah ACK yang diterima.

Operasi bus standar

Metode-metode berikut mengimplementasikan operasi baca dan tulis I2C controller standar yang menargetkan perangkat periferal tertentu.

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

Membaca nbytes dari periferal yang ditentukan oleh addr. Jika stop bernilai true maka kondisi STOP dihasilkan di akhir transfer. Mengembalikan objek bytes dengan data yang dibaca.

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

Membaca ke dalam buf dari periferal yang ditentukan oleh addr. Jumlah byte yang dibaca akan sesuai dengan panjang buf. Jika stop bernilai true maka kondisi STOP dihasilkan di akhir transfer.

Metode mengembalikan None.

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

Menulis byte dari buf ke periferal yang ditentukan oleh addr. Jika NACK diterima setelah penulisan sebuah byte dari buf, maka byte yang tersisa tidak dikirim. Jika stop bernilai true maka kondisi STOP dihasilkan di akhir transfer, bahkan jika NACK diterima. Fungsi ini mengembalikan jumlah ACK yang diterima.

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

Menulis byte yang terdapat dalam vector ke periferal yang ditentukan oleh addr. vector harus berupa tuple atau list objek dengan protokol buffer. addr dikirim sekali dan kemudian byte dari setiap objek dalam vector ditulis secara berurutan. Objek dalam vector mungkin memiliki panjang nol byte, dalam hal ini tidak berkontribusi pada output.

Jika NACK diterima setelah penulisan sebuah byte dari salah satu objek dalam vector, maka byte yang tersisa, dan semua objek yang tersisa, tidak dikirim. Jika stop bernilai true maka kondisi STOP dihasilkan di akhir transfer, bahkan jika NACK diterima. Fungsi ini mengembalikan jumlah ACK yang diterima.

Operasi Memori

Beberapa perangkat I2C berfungsi sebagai perangkat memori (atau serangkaian register) yang dapat dibaca dan ditulis. Dalam kasus ini terdapat dua alamat yang terkait dengan transaksi I2C: alamat periferal dan alamat memori. Metode-metode berikut adalah fungsi kenyamanan untuk berkomunikasi dengan perangkat semacam itu.

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

Membaca nbytes dari periferal yang ditentukan oleh addr dimulai dari alamat memori yang ditentukan oleh memaddr. Argumen addrsize menentukan ukuran alamat dalam bit. Mengembalikan objek bytes dengan data yang dibaca.

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

Membaca ke dalam buf dari periferal yang ditentukan oleh addr dimulai dari alamat memori yang ditentukan oleh memaddr. Jumlah byte yang dibaca adalah panjang buf. Argumen addrsize menentukan ukuran alamat dalam bit.

Metode mengembalikan None.

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

Menulis buf ke periferal yang ditentukan oleh addr dimulai dari alamat memori yang ditentukan oleh memaddr. Argumen addrsize menentukan ukuran alamat dalam bit.

Metode mengembalikan None.

kelas SoftI2C -- bus I2C berbasis software

Kelas SoftI2C mengimplementasikan I2C dengan cara bit-banging pin GPIO sembarang. Kelas ini mengekspos permukaan metode yang sama seperti I2C ditambah operasi bus primitif tingkat rendah (start(), stop(), readinto(), write()) untuk pemanggil yang perlu merakit transaksi non-standar. Gunakan kelas ini ketika pin yang dibutuhkan tidak terhubung ke blok I2C hardware, ketika Anda memerlukan lebih banyak bus daripada yang disediakan hardware, atau untuk berkomunikasi dengan perangkat yang memerlukan urutan yang tidak biasa (clock tambahan, start berulang setelah penulisan, dll.).

Konstruktor

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

Membangun bus I2C software yang dikendalikan oleh scl / sda.

freq adalah target laju clock SCL dalam Hz (laju aktual biasanya lebih rendah karena overhead loop bit-bang).

timeout adalah waktu maksimum dalam mikrodetik untuk menunggu clock stretching (SCL ditahan rendah oleh perangkat lain di bus); saat habis, OSError(ETIMEDOUT) akan dimunculkan.

Metode Umum

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

Inisialisasi ulang bus I2C software dengan pin dan frekuensi yang diberikan. Setara dengan membangun SoftI2C baru pada objek yang sama.

scan() List[int]

Memindai semua alamat I2C antara 0x08 dan 0x77 (inklusif) dan mengembalikan daftar yang memberikan respons.

Operasi I2C Primitif

Metode-metode berikut mengimplementasikan operasi bus I2C controller primitif dan dapat dikombinasikan untuk membuat transaksi I2C apa pun. Metode ini khusus untuk SoftI2C -- kelas I2C hardware tidak mengeksposnya.

start() None

Menghasilkan kondisi START pada bus (SDA beralih ke rendah saat SCL tinggi).

stop() None

Menghasilkan kondisi STOP pada bus (SDA beralih ke tinggi saat SCL tinggi).

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

Membaca byte dari bus ke dalam buf. Dibaca sebanyak len(buf) byte; ACK dikirim setelah setiap byte kecuali yang terakhir. Setelah byte terakhir, nack=True (default) mengirim NACK untuk mengakhiri transfer; nack=False mengirim ACK sehingga perangkat tetap dipilih untuk readinto() berikutnya.

write(buf: bytes) int

Menulis buf ke bus, memeriksa ACK setelah setiap byte. Transmisi berhenti pada NACK pertama. Mengembalikan jumlah ACK yang diterima.

Operasi bus standar

Metode-metode berikut mengimplementasikan operasi baca dan tulis I2C controller standar yang menargetkan perangkat periferal tertentu.

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

Membaca nbytes dari perangkat pada alamat 7-bit addr. Jika stop bernilai true, kondisi STOP dihasilkan di akhir transfer.

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

Membaca len(buf) byte dari perangkat pada addr ke dalam buf. Jika stop bernilai true, kondisi STOP dihasilkan di akhir transfer.

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

Menulis buf ke perangkat pada addr. Transmisi berhenti pada NACK pertama. Jika stop bernilai true, kondisi STOP selalu dihasilkan di akhir transfer (bahkan pada NACK dini). Mengembalikan jumlah ACK yang diterima.

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

Menulis penggabungan buffer dalam vector ke perangkat pada addr sebagai satu transaksi. Buffer kosong diabaikan. Berperilaku seperti writeto() untuk semantik stop dan nilai kembalian.

Operasi Memori

Beberapa perangkat I2C berfungsi sebagai perangkat memori (atau serangkaian register) yang dapat dibaca dan ditulis. Dalam kasus ini terdapat dua alamat yang terkait dengan transaksi I2C: alamat periferal dan alamat memori. Metode-metode berikut adalah pembantu kenyamanan untuk berkomunikasi dengan perangkat semacam itu.

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

Membaca nbytes dari perangkat pada addr dimulai dari register memaddr. addrsize adalah lebar alamat register dalam bit (biasanya 8 atau 16).

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

Membaca ke dalam buf dari perangkat pada addr dimulai dari register memaddr.

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

Menulis buf ke perangkat pada addr dimulai dari register memaddr.