class I2C – iki telli bir seri protokol

I2C, cihazlar arasında iletişim kurmak için kullanılan iki telli bir protokoldür. Fiziksel düzeyde 2 telden oluşur: sırasıyla saat ve veri hatları olan SCL ve SDA.

I2C nesneleri belirli bir veri yoluna bağlı olarak oluşturulur. Oluşturuldukları sırada veya daha sonra başlatılabilirler.

I2C nesnesini yazdırmak, yapılandırması hakkında bilgi verir.

I2C ve SoftI2C sınıfları aracılığıyla hem donanım hem de yazılım I2C uygulamaları mevcuttur. Donanım I2C, okuma/yazma işlemlerini gerçekleştirmek için sistemin altta yatan donanım desteğini kullanır ve genellikle verimli ve hızlıdır, ancak hangi pinlerin kullanılabileceği konusunda kısıtlamaları olabilir. Yazılım I2C ise bit-banging yöntemiyle uygulanır ve herhangi bir pinde kullanılabilir, ancak o kadar verimli değildir. Bu sınıflar aynı metotlara sahiptir ve esas olarak oluşturulma biçimleriyle farklılaşır.

Not

I2C veri yolu, çalışması için hem SDA hem de SCL üzerinde pull-up devresi gerektirir. Genellikle bunlar, her SDA/SCL hattından Vcc’ye bağlanan 1 - 10 kOhm aralığındaki dirençlerdir. Bunlar olmadan davranış tanımsızdır ve bloklanmadan beklenmeyen watchdog sıfırlamasına veya yalnızca yanlış değerlere kadar değişebilir. Çoğu zaman bu pull-up devresi MCU kartına veya sensör breakout kartlarına zaten yerleşik olarak gelir, ancak bunun için bir kural yoktur. Bu nedenle bir sorun olması durumunda lütfen kontrol edin. I2C kablolaması hakkında Adafruit’in bu mükemmel öğrenme kılavuzuna da bakın.

Örnek kullanım:

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

Yapıcılar

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

Aşağıdaki parametreleri kullanarak yeni bir I2C nesnesi oluşturur ve döndürür:

  • id belirli bir I2C çevre birimini tanımlar. İzin verilen değerler belirli porta/karta bağlıdır

  • scl, SCL için kullanılacak pini belirten bir pin nesnesi olmalıdır.

  • sda, SDA için kullanılacak pini belirten bir pin nesnesi olmalıdır.

  • freq, SCL için maksimum frekansı ayarlayan bir tam sayı olmalıdır.

  • timeout, I2C işlemleri için izin verilen mikrosaniye cinsinden maksimum süredir. Bu parametreye bazı portlarda izin verilmez.

Bazı portların/kartların bu yapıcıda değiştirilebilen varsayılan scl ve sda değerlerine sahip olacağını unutmayın. Diğerlerinin ise değiştirilemeyen sabit scl ve sda değerleri olacaktır.

Genel Metotlar

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

I2C veri yolunu verilen argümanlarla başlatır:

  • scl, SCL hattı için bir pin nesnesidir

  • sda, SDA hattı için bir pin nesnesidir

  • freq, SCL saat hızıdır

Donanım I2C durumunda gerçek saat frekansı, istenen frekanstan daha düşük olabilir. Bu, platform donanımına bağlıdır. Gerçek hız, I2C nesnesi yazdırılarak belirlenebilir.

scan() List[int]

0x08 ile 0x77 dahil arasındaki tüm I2C adreslerini tarar ve yanıt verenlerin bir listesini döndürür. Adresi (bir yazma biti dahil) veri yoluna gönderildikten sonra SDA hattını alçağa çeken bir cihaz yanıt vermiş olur.

İlkel I2C işlemleri

Aşağıdaki metotlar ilkel I2C denetleyici veri yolu işlemlerini uygular ve herhangi bir I2C işlemini oluşturmak için birleştirilebilir. Veri yolu üzerinde daha fazla denetime ihtiyaç duymanız durumunda sağlanmışlardır; aksi takdirde standart metotlar (aşağıya bakın) kullanılabilir.

Bu metotlar yalnızca SoftI2C sınıfında mevcuttur.

start() None

Veri yolunda bir START koşulu oluşturur (SCL yüksekken SDA alçağa geçer).

stop() None

Veri yolunda bir STOP koşulu oluşturur (SCL yüksekken SDA yükseğe geçer).

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

Veri yolundan baytları okur ve bunları buf içine depolar. Okunan bayt sayısı buf uzunluğu kadardır. Son bayt hariç tüm baytlar alındıktan sonra veri yoluna bir ACK gönderilir. Son bayt alındıktan sonra, nack doğruysa bir NACK gönderilir, aksi takdirde bir ACK gönderilir (ve bu durumda çevre birimi daha sonraki bir çağrıda daha fazla bayt okunacağını varsayar).

write(buf: bytes) int

buf içindeki baytları veri yoluna yazar. Her bayttan sonra bir ACK alınıp alınmadığını denetler ve bir NACK alınırsa kalan baytları iletmeyi durdurur. Fonksiyon alınan ACK sayısını döndürür.

Standart veri yolu işlemleri

Aşağıdaki metotlar, belirli bir çevre birimi cihazını hedefleyen standart I2C denetleyici okuma ve yazma işlemlerini uygular.

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

addr ile belirtilen çevre biriminden nbytes okur. stop doğruysa aktarımın sonunda bir STOP koşulu oluşturulur. Okunan verileri içeren bir bytes nesnesi döndürür.

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

addr ile belirtilen çevre biriminden buf içine okur. Okunan bayt sayısı buf uzunluğu kadar olur. stop doğruysa aktarımın sonunda bir STOP koşulu oluşturulur.

Bu metot None döndürür.

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

buf içindeki baytları addr ile belirtilen çevre birimine yazar. buf içinden bir baytın yazılmasının ardından bir NACK alınırsa kalan baytlar gönderilmez. stop doğruysa, bir NACK alınsa bile aktarımın sonunda bir STOP koşulu oluşturulur. Fonksiyon alınan ACK sayısını döndürür.

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

vector içinde bulunan baytları addr ile belirtilen çevre birimine yazar. vector, buffer protokolüne sahip nesnelerden oluşan bir demet veya liste olmalıdır. addr bir kez gönderilir ve ardından vector içindeki her nesnenin baytları sırayla yazılır. vector içindeki nesneler sıfır bayt uzunluğunda olabilir; bu durumda çıktıya katkıda bulunmazlar.

vector içindeki nesnelerden birinden bir baytın yazılmasının ardından bir NACK alınırsa kalan baytlar ve kalan nesnelerin tümü gönderilmez. stop doğruysa, bir NACK alınsa bile aktarımın sonunda bir STOP koşulu oluşturulur. Fonksiyon alınan ACK sayısını döndürür.

Bellek işlemleri

Bazı I2C cihazları, okunabilen ve yazılabilen bir bellek cihazı (veya bir yazmaç kümesi) gibi davranır. Bu durumda bir I2C işlemiyle ilişkili iki adres bulunur: çevre birimi adresi ve bellek adresi. Aşağıdaki metotlar bu tür cihazlarla iletişim kurmak için kolaylık fonksiyonlarıdır.

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

addr ile belirtilen çevre biriminden, memaddr ile belirtilen bellek adresinden başlayarak nbytes okur. addrsize argümanı, adres boyutunu bit cinsinden belirtir. Okunan verileri içeren bir bytes nesnesi döndürür.

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

addr ile belirtilen çevre biriminden, memaddr ile belirtilen bellek adresinden başlayarak buf içine okur. Okunan bayt sayısı buf uzunluğu kadardır. addrsize argümanı, adres boyutunu bit cinsinden belirtir.

Bu metot None döndürür.

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

buf içeriğini, memaddr ile belirtilen bellek adresinden başlayarak addr ile belirtilen çevre birimine yazar. addrsize argümanı, adres boyutunu bit cinsinden belirtir.

Bu metot None döndürür.

class SoftI2C – yazılımla taklit edilen I2C veri yolu

SoftI2C sınıfı, rastgele GPIO pinlerini bit-banging yöntemiyle kullanarak I2C uygular. I2C ile aynı metot yüzeyini ve buna ek olarak, standart olmayan işlemleri bir araya getirmesi gereken çağıranlar için düşük seviyeli ilkel veri yolu işlemlerini (start(), stop(), readinto(), write()) sunar. İhtiyaç duyduğunuz pinler bir donanım I2C bloğuna bağlı değilken, donanımın sağladığından daha fazla veri yoluna ihtiyaç duyduğunuzda veya olağan dışı diziler (ek saat darbeleri, yazma işlemlerinden sonra tekrarlanan start’lar vb.) gerektiren cihazlarla konuşmak için bunu kullanın.

Yapıcılar

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

scl / sda ile sürülen bir yazılım I2C veri yolu oluşturur.

freq, Hz cinsinden hedef SCL saat hızıdır (gerçek hız, bit-bang döngüsünün ek yükü nedeniyle genellikle daha düşüktür).

timeout, saat uzatması (veri yolundaki başka bir cihaz tarafından SCL’nin alçakta tutulması) için beklenecek mikrosaniye cinsinden maksimum süredir; süre dolduğunda bir OSError(ETIMEDOUT) yükseltilir.

Genel Metotlar

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

Yazılım I2C veri yolunu verilen pinler ve frekansla yeniden başlatır. Aynı nesne üzerinde yeni bir SoftI2C oluşturmaya eşdeğerdir.

scan() List[int]

0x08 ile 0x77 dahil arasındaki tüm I2C adreslerini tarar ve yanıt verenlerin bir listesini döndürür.

İlkel I2C işlemleri

Aşağıdaki metotlar ilkel I2C denetleyici veri yolu işlemlerini uygular ve herhangi bir I2C işlemini oluşturmak için birleştirilebilir. Bunlar yalnızca SoftI2C’ye özgüdür – donanım I2C sınıfı bunları sunmaz.

start() None

Veri yolunda bir START koşulu oluşturur (SCL yüksekken SDA alçağa geçer).

stop() None

Veri yolunda bir STOP koşulu oluşturur (SCL yüksekken SDA yükseğe geçer).

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

Veri yolundan buf içine baytları okur. len(buf) bayt okunur; son bayt hariç her bayttan sonra bir ACK gönderilir. Son bayttan sonra nack=True (varsayılan) aktarımı sonlandırmak için bir NACK gönderir; nack=False ise cihazın sonraki bir readinto() için seçili kalması amacıyla bir ACK gönderir.

write(buf: bytes) int

buf içeriğini veri yoluna yazar ve her bayttan sonra ACK kontrolü yapar. İletim ilk NACK’te durur. Alınan ACK sayısını döndürür.

Standart veri yolu işlemleri

Aşağıdaki metotlar, belirli bir çevre birimi cihazını hedefleyen standart I2C denetleyici okuma ve yazma işlemlerini uygular.

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

7 bitlik addr adresindeki cihazdan nbytes okur. stop doğruysa aktarımın sonunda bir STOP koşulu oluşturulur.

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

addr adresindeki cihazdan buf içine len(buf) bayt okur. stop doğruysa aktarımın sonunda bir STOP koşulu oluşturulur.

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

buf içeriğini addr adresindeki cihaza yazar. İletim ilk NACK’te durur. stop doğruysa aktarımın sonunda (erken bir NACK durumunda bile) her zaman bir STOP koşulu oluşturulur. Alınan ACK sayısını döndürür.

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

vector içindeki arabelleklerin birleştirilmiş halini addr adresindeki cihaza tek bir işlem olarak yazar. Boş arabellekler yok sayılır. stop semantiği ve dönüş değeri açısından writeto() gibi davranır.

Bellek işlemleri

Bazı I2C cihazları, okunabilen ve yazılabilen bir bellek cihazı (veya bir yazmaç kümesi) gibi davranır. Bu durumda bir I2C işlemiyle ilişkili iki adres bulunur: çevre birimi adresi ve bellek adresi. Aşağıdaki metotlar bu tür cihazlarla konuşmak için kolaylık yardımcılarıdır.

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

addr adresindeki cihazdan memaddr yazmacından başlayarak nbytes okur. addrsize, yazmaç adresinin bit cinsinden genişliğidir (genellikle 8 veya 16).

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

addr adresindeki cihazdan memaddr yazmacından başlayarak buf içine okur.

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

buf içeriğini addr adresindeki cihaza memaddr yazmacından başlayarak yazar.