Seri Protokoller
TEKNİK REHBER SERİ PROTOKOLLER I²C 2026

I²C protokolü
ve i2c-tools.

İki telden sensör, EEPROM, ADC — her şey adresle ayrılır. i2cdetect ile tara, i2cget/i2cset ile oku/yaz, smbus2 ile Python'dan kontrol et.

00 I²C protokolü temelleri

I²C (Inter-Integrated Circuit) — Philips'in 1982'de geliştirdiği, sadece iki tel gerektiren senkron seri protokol.

I²C'nin temel özellikleri onu sensör haberleşmesinde popüler yapan şeydir: 7-bit adresleme ile 112 farklı cihaz (10-bit ile 1008 cihaza kadar) aynı iki teli paylaşabilir. Her işlem master tarafından başlatılır; slave'ler sadece yanıt verir.

  Master ─────────────────────────────── Slave 1 (0x48)
         │                               Slave 2 (0x76)
  SDA ───┤─────────────────────────────── Slave 3 (0x3C)
  SCL ───┘
         │←── 4.7kΩ pull-up ───→ VCC
    

SDA ve SCL hatları

Sadece iki sinyal söz konusudur:

SDASerial Data — veri hattı. Hem master hem slave sürülebilir (open-drain). Pull-up direnci gereklidir.
SCLSerial Clock — saat hattı. Master tarafından üretilir. Clock stretching özelliğiyle slave saat hattını düşük tutarak master'ı bekletebilir.

Pull-up dirençler

I²C open-drain protokolüdür: her iki hat da pull-up direnci üzerinden VCC'ye bağlanır. Direnç değeri bus kapasitansına ve hıza bağlıdır:

HızÖnerilen RMaks. kapasitans
Standard Mode (100 kHz)4.7 kΩ400 pF
Fast Mode (400 kHz)2.2 kΩ400 pF
Fast-Plus (1 MHz)1 kΩ550 pF

Start / Stop koşulları ve ACK/NACK

Bir I²C transaction şu adımlarla ilerler:

  1. START condition: SCL yüksekken SDA düşer.
  2. 7-bit slave adresi gönderilir, ardından 1 bit R/W (0=yaz, 1=oku).
  3. Slave adresi tanırsa ACK (SDA'yı düşürür), tanımazsa NACK gönderir.
  4. Veri baytları gönderilir; her bayt sonrası alıcıdan ACK beklenir.
  5. STOP condition: SCL yüksekken SDA yükselir.
  6. Tekrarlanan START (Repeated START) ile STOP vermeden yeni transaction başlatılabilir — bu özellikle register oku işlemlerinde kullanılır.
NOT

Repeated START çok önemlidir: I²C cihazlarının çoğu bir register'dan okumak için önce register adresini yazar (write transaction), ardından Repeated START ile okuma başlatır. Bu iki ayrı mesajı tek transaction içinde birleştirir.

Multi-master

I²C multi-master destekler: birden fazla master aynı anda bus kullanmak isterse arbitration mekanizması devreye girer. SDA'ya logic-1 süren master, diğerinin logic-0 sürdüğünü fark eder ve bus'ı bırakır. Gömülü Linux'ta genellikle tek master kullanılır.

01 Linux I²C subsystem

Linux'ta I²C desteği üç katmandan oluşur: donanım adaptörü (adapter), bağlı cihaz (client) ve driver.

  Userspace     /dev/i2c-0  /dev/i2c-1  ...
                     │
  Kernel       i2c-dev (character device driver)
                     │
             i2c_adapter (bcm2835_i2c, i2c-imx, i2c-mv64xxx ...)
                     │
             Hardware   (SoC I²C controller register'ları)
    

Kernel yapılandırması

I²C userspace erişimi için i2c-dev modülü yüklü olmalıdır. Raspberry Pi ve BeagleBone gibi kartlarda genellikle varsayılan olarak aktifdir.

kernel config
# menuconfig / defconfig içinde gerekli seçenekler:
CONFIG_I2C=y
CONFIG_I2C_CHARDEV=y          # /dev/i2c-N erişimi için
CONFIG_I2C_BCM2835=y          # Raspberry Pi SoC adaptörü (örnek)
CONFIG_I2C_IMX=y              # NXP i.MX adaptörü (örnek)

# Modül olarak da derlenebilir (=m):
CONFIG_I2C_CHARDEV=m
bash
# i2c-dev modülünü yükle (=m ise):
sudo modprobe i2c-dev

# Mevcut I²C adaptörlerini gör:
ls /dev/i2c-*
# /dev/i2c-0  /dev/i2c-1

# i2c-dev karakteristik cihaz bilgisi:
ls -la /dev/i2c-1
# crw-rw---- 1 root i2c 89, 1 Jan  1 00:00 /dev/i2c-1

# Kullanıcıyı i2c grubuna ekle (her seferinde sudo kullanmamak için):
sudo usermod -aG i2c $USER
# Oturumu yeniden aç veya: newgrp i2c

Device Tree bağlaması

SoC'ye bağlı I²C slave'ler device tree'de tanımlanır. Bu sayede kernel boot sırasında ilgili driver'ı otomatik yükler.

device-tree.dts
&i2c1 {
    clock-frequency = <400000>;   /* Fast Mode: 400 kHz */
    status = "okay";

    bme280: bme280@76 {
        compatible = "bosch,bme280";
        reg = <0x76>;              /* 7-bit I²C adresi */
    };

    eeprom@50 {
        compatible = "atmel,24c32";
        reg = <0x50>;
        pagesize = <32>;
    };
};
NOT

i2c_adapter: SoC'nin donanım I²C controller'ını temsil eder. i2c_client: bus'a bağlı bir slave cihazı temsil eder (adres + adapter bilgisi içerir). i2c_driver: belirli bir donanım modelini destekleyen kernel driver yapısıdır.

02 i2c-tools kurulumu ve i2cdetect

i2c-tools paketi userspace'den I²C bus'ına doğrudan erişimi sağlayan araç seti içerir.

bash — kurulum
# Debian / Ubuntu / Raspberry Pi OS:
sudo apt install i2c-tools

# Yocto (meta-oe layer):
# IMAGE_INSTALL += "i2c-tools"

# Buildroot:
# BR2_PACKAGE_I2C_TOOLS=y

# Kurulu araçları kontrol et:
which i2cdetect i2cget i2cset i2cdump i2ctransfer

i2cdetect ile bus tarama

bash
# Sistemdeki tüm I²C bus'ları listele:
i2cdetect -l
# i2c-0   i2c         bcm2835 (i2c@7e205000)      I2C adapter
# i2c-1   i2c         bcm2835 (i2c@7e804000)      I2C adapter

# Bus 1'deki tüm cihazları tara:
sudo i2cdetect -y 1

Tipik i2cdetect -y 1 çıktısı:

i2cdetect -y 1 çıktısı
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- 76 --

Bu çıktıda 0x3C adresinde bir SSD1306 OLED ekran, 0x76 adresinde ise BME280 sensörü görünmektedir. -- o adreste cihaz olmadığını gösterir.

-yOnay istemeden çalıştır (non-interactive). Script'lerde kullan.
-rSMBus read byte yerine I²C read kullan. Bazı cihazlar write probe ile bozulabilir.
-a0x00–0x7F tüm adres aralığını tara (reserved adresler dahil).
-F NBus N'in desteklediği fonksiyonları listele (I2C_FUNC_*).
UYARI

i2cdetect tarama sırasında her adrese yazma denemesi yapar. Bazı cihazlar (özellikle EEPROM ve motor sürücüler) bu yazma probundan etkilenebilir. Cihaz tipini biliyorsan -r seçeneğini kullan.

03 i2cget ve i2cset

Tek register okuma ve yazma işlemleri için kullanılan komutlar. SMBus protokol modlarını destekler.

i2cget — register okuma

bash
# Sözdizimi: i2cget [-y] BUS ADDR [REG [MODE]]

# BME280 (0x76) chip ID register'ını oku (0xD0 = 0x60 döndürür):
sudo i2cget -y 1 0x76 0xD0
# 0x60

# Word (16-bit, little-endian) okuma:
sudo i2cget -y 1 0x48 0x00 w
# 0x7d00  ← TMP102 sıcaklık register'ı

# Block okuma (SMBus block read):
sudo i2cget -y 1 0x50 0x00 i
bByte mode (varsayılan). 1 bayt okur.
wWord mode. 2 bayt okur, little-endian sırayla döner.
iI²C block read. SMBus block read'den farklı: length byte beklenmez.
sSMBus block read. İlk bayt kaç bayt geleceğini belirtir.

i2cset — register yazma

bash
# Sözdizimi: i2cset [-y] BUS ADDR REG VALUE [MODE]

# BME280 reset register'ına yazma (0xB6 = soft reset):
sudo i2cset -y 1 0x76 0xE0 0xB6

# BME280 ctrl_meas register'ı: osrs_t=2 (2x), osrs_p=5 (16x), mode=3 (normal):
# osrs_t[7:5]=010, osrs_p[4:2]=101, mode[1:0]=11 → 0b01010111 = 0x57
sudo i2cset -y 1 0x76 0xF4 0x57

# 16-bit word yazma (word mode, little-endian):
sudo i2cset -y 1 0x48 0x01 0x6000 w

# Birden fazla bayt (I²C block write):
sudo i2cset -y 1 0x50 0x00 0xAB 0xCD 0xEF i

# -e: PEC (Packet Error Check) ile CRC doğrulama:
sudo i2cset -y -e 1 0x60 0x05 0x01
UYARI

EEPROM'lara yazarken sayfa sınırlarına dikkat et. 24Cxx EEPROM'ların sayfa boyutu 8-128 bayt arasında değişir; sayfa sınırını aşan yazma işlemleri sayfa başına geri döner ve veri bozulur.

04 i2cdump — register haritası dökümü

Bir cihazın tüm register'larını tek seferde okuyarak görsel harita çıkaran araç.

bash
# Sözdizimi: i2cdump [-y] BUS ADDR [MODE]

# BME280 tüm register'larını oku (byte mode):
sudo i2cdump -y 1 0x76
i2cdump çıktısı (kısmi)
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
...
80: a0 6b 4d 67 32 00 4a 93 5a d7 d0 0b 2f fb cf 16    .mMg2.J.Z..../..
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
...
d0: 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    `...............
...
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 57    ...............W
f4: 57 00 00 b6 00 00 00 00 00 00 00 00 00 00 00 00    W...............
# 0xD0 = 0x60 → chip_id = BME280 doğrulandı
# 0xF4 = 0x57 → ctrl_meas: osrs_t=2, osrs_p=5, mode=normal
bByte data access (varsayılan). Her register'ı ayrı ayrı okur.
wWord data access. 16-bit okur.
sSMBus block read.
iI²C block read. Bazı cihazlarla daha uyumludur.
cConsecutive (ardışık): register adresi göndermeden sadece okur. FIFO tabanlı cihazlar için.
NOT

i2cdump çıktısında sol taraf onaltılık değer, sağ taraf ASCII karşılıklarıdır. Register adresi bilinen cihazlarda belirli satırları izlemek daha verimlidir: i2cdump -y 1 0x76 | grep "^d0" sadece 0xD0–0xDF satırını gösterir.

05 i2ctransfer — raw message gönderme

SMBus protokol kısıtlamalarını aşarak ham I²C mesajları gönderir. Combined message ve custom transaction'lar için kullanılır.

bash
# Sözdizimi: i2ctransfer [-y] BUS DESC [DATA] [DESC [DATA] ...]
# DESC: {r|w}LENGTH[@ADDR]

# Tek write: BME280'e 0xF4 = 0x57 yaz:
sudo i2ctransfer -y 1 w2@0x76 0xF4 0x57

# Combined message (write + repeated start + read):
# BME280 register 0xF7'den 8 bayt oku (ham ADC verileri):
sudo i2ctransfer -y 1 w1@0x76 0xF7 r8@0x76
# 0x50 0xea 0x00 0x80 0xdc 0x00 0x6f 0xc0

# EEPROM 24C32: adres 0x0010'dan 4 bayt oku:
# Önce 2-bayt adres yaz (big-endian), sonra oku:
sudo i2ctransfer -y 1 w2@0x50 0x00 0x10 r4@0x50

# Birden fazla bağımsız transaction:
sudo i2ctransfer -y 1 w1@0x48 0x00 r2@0x48

i2ctransfer, SMBus olmayan saf I²C mesajları gönderebilir. Bu özellik şu durumlarda kritiktir:

  • SMBus'ın desteklemediği uzunluklarda block transfer (33 bayttan fazla)
  • 10-bit adresleme kullanan cihazlar
  • Özel protokol gerektiren sensörler (combined message mantığı)
NOT

SMBus protokolü I²C'nin bir alt kümesidir. i2cget/i2cset SMBus komutlarını kullanırken, i2ctransfer I2C_RDWR ioctl'ini kullanarak ham mesaj gönderir. Mevcut fonksiyon setini i2cdetect -F 1 ile kontrol edebilirsin.

06 Python ile I²C: smbus2

smbus2 kütüphanesi Python'dan /dev/i2c-N arayüzüne doğrudan erişim sağlar. SMBus ve I²C combined message destekler.

bash — kurulum
pip3 install smbus2
# veya sistem paketi:
sudo apt install python3-smbus2
i2c_basic.py
from smbus2 import SMBus, i2c_msg

# Bus 1'i aç (/dev/i2c-1)
with SMBus(1) as bus:

    # Tek bayt okuma (SMBus read_byte_data):
    chip_id = bus.read_byte_data(0x76, 0xD0)
    print(f"Chip ID: 0x{chip_id:02X}")   # 0x60

    # Tek bayt yazma (SMBus write_byte_data):
    bus.write_byte_data(0x76, 0xF4, 0x57)

    # 16-bit word okuma (little-endian):
    raw = bus.read_word_data(0x48, 0x00)
    print(f"Word: 0x{raw:04X}")

    # Block okuma — 6 bayt (register 0xF7'den):
    data = bus.read_i2c_block_data(0x76, 0xF7, 6)
    print(f"Raw ADC: {[hex(b) for b in data]}")

    # Combined message (write + repeated start + read):
    write_msg = i2c_msg.write(0x76, [0x88])   # register adresi
    read_msg  = i2c_msg.read(0x76, 24)         # 24 bayt oku
    bus.i2c_rdwr(write_msg, read_msg)
    calib_raw = list(read_msg)
    print(f"Calibration bytes: {calib_raw}")

Önemli SMBus2 metodları

read_byte(addr)Register adresi olmadan tek bayt okur.
write_byte(addr, val)Register adresi olmadan tek bayt yazar.
read_byte_data(addr, reg)SMBus Read Byte Data: 8-bit register'dan 1 bayt okur.
write_byte_data(addr, reg, val)SMBus Write Byte Data: 8-bit register'a 1 bayt yazar.
read_word_data(addr, reg)SMBus Read Word Data: 16-bit okur, little-endian.
read_i2c_block_data(addr, reg, length)I²C block read: register adresinden başlayarak length bayt okur (max 32).
write_i2c_block_data(addr, reg, data)I²C block write: register adresinden başlayarak bayt listesi yazar.
i2c_rdwr(*msgs)Ham I²C mesajları gönder. i2c_msg.write() ve i2c_msg.read() ile oluşturulur. Combined message için kullan.

07 Pratik: BME280 sensör okuma

Bosch BME280, tek çipte sıcaklık + nem + basınç ölçen popüler bir I²C sensörüdür. Register haritası ve kalibrasyon mekanizmasını anlayarak ham veriden fiziksel değer elde edelim.

BME280 register haritası (önemli register'lar)

RegisterAdıAçıklama
0xD0idChip ID: BME280=0x60, BMP280=0x58
0xE0reset0xB6 yazılırsa soft reset
0xF2ctrl_humNem oversampling (osrs_h[2:0])
0xF3statusmeasuring[3], im_update[0]
0xF4ctrl_measosrs_t[7:5], osrs_p[4:2], mode[1:0]
0xF5configt_sb[7:5], filter[4:2], spi3w_en[0]
0xF7–0xF9press_msb/lsb/xlsbHam basınç verisi (20-bit)
0xFA–0xFCtemp_msb/lsb/xlsbHam sıcaklık verisi (20-bit)
0xFD–0xFEhum_msb/lsbHam nem verisi (16-bit)
0x88–0x9Fcalib00–17Sıcaklık/Basınç kalibrasyon verileri
0xE1–0xE7calib26–32Nem kalibrasyon verileri
bme280_read.py
import struct
from smbus2 import SMBus, i2c_msg

BME280_ADDR = 0x76
I2C_BUS     = 1

def read_calibration(bus):
    """Kalibrasyon register'larını oku ve parse et."""
    # 0x88'den 24 bayt: dig_T1..T3, dig_P1..P9
    w = i2c_msg.write(BME280_ADDR, [0x88])
    r = i2c_msg.read(BME280_ADDR, 24)
    bus.i2c_rdwr(w, r)
    raw = list(r)

    calib = {}
    calib['T1'] = struct.unpack_from('<H', bytes(raw[0:2]))[0]
    calib['T2'] = struct.unpack_from('<h', bytes(raw[2:4]))[0]
    calib['T3'] = struct.unpack_from('<h', bytes(raw[4:6]))[0]

    calib['P1'] = struct.unpack_from('<H', bytes(raw[6:8]))[0]
    calib['P2'] = struct.unpack_from('<h', bytes(raw[8:10]))[0]
    calib['P3'] = struct.unpack_from('<h', bytes(raw[10:12]))[0]
    calib['P4'] = struct.unpack_from('<h', bytes(raw[12:14]))[0]
    calib['P5'] = struct.unpack_from('<h', bytes(raw[14:16]))[0]
    calib['P6'] = struct.unpack_from('<h', bytes(raw[16:18]))[0]
    calib['P7'] = struct.unpack_from('<h', bytes(raw[18:20]))[0]
    calib['P8'] = struct.unpack_from('<h', bytes(raw[20:22]))[0]
    calib['P9'] = struct.unpack_from('<h', bytes(raw[22:24]))[0]

    # 0xA1: dig_H1
    calib['H1'] = bus.read_byte_data(BME280_ADDR, 0xA1)

    # 0xE1'den 7 bayt: dig_H2..H6
    w2 = i2c_msg.write(BME280_ADDR, [0xE1])
    r2 = i2c_msg.read(BME280_ADDR, 7)
    bus.i2c_rdwr(w2, r2)
    h = list(r2)
    calib['H2'] = struct.unpack_from('<h', bytes(h[0:2]))[0]
    calib['H3'] = h[2]
    calib['H4'] = (h[3] << 4) | (h[4] & 0x0F)
    calib['H5'] = (h[5] << 4) | (h[4] >> 4)
    calib['H6'] = struct.unpack_from('<b', bytes([h[6]]))[0]
    return calib

def compensate_temperature(adc_T, calib):
    """Bosch datasheet formülü (32-bit integer versiyonu)."""
    var1 = ((adc_T >> 3) - (calib['T1'] << 1)) * calib['T2'] >> 11
    var2 = ((adc_T >> 4) - calib['T1'])
    var2 = (var2 * var2 >> 12) * calib['T3'] >> 14
    t_fine = var1 + var2
    T = (t_fine * 5 + 128) >> 8
    return T / 100.0, t_fine

def compensate_humidity(adc_H, t_fine, calib):
    x = t_fine - 76800
    x = (adc_H << 14) - (calib['H4'] << 20) - calib['H5'] * x
    x = (x + 16384) >> 15
    x = x * (((((((x * calib['H6']) >> 10) *
                  (((x * calib['H3']) >> 11) + 32768)) >> 10) + 2097152) *
                calib['H2'] + 8192) >> 14)
    x = x - (((((x >> 15) ** 2) >> 7) * calib['H1']) >> 4)
    x = max(0, min(x, 419430400))
    return (x >> 12) / 1024.0

with SMBus(I2C_BUS) as bus:
    # Chip ID kontrol:
    chip_id = bus.read_byte_data(BME280_ADDR, 0xD0)
    assert chip_id == 0x60, f"BME280 değil: 0x{chip_id:02X}"

    # Kalibrasyon oku:
    calib = read_calibration(bus)

    # Forced mode: tek ölçüm al
    bus.write_byte_data(BME280_ADDR, 0xF2, 0x01)  # ctrl_hum: osrs_h=1
    bus.write_byte_data(BME280_ADDR, 0xF4, 0x25)  # osrs_t=1, osrs_p=1, forced

    import time; time.sleep(0.01)  # ölçüm tamamlanmasını bekle

    # Ham verileri oku (0xF7'den 8 bayt):
    w = i2c_msg.write(BME280_ADDR, [0xF7])
    r = i2c_msg.read(BME280_ADDR, 8)
    bus.i2c_rdwr(w, r)
    d = list(r)

    adc_P = (d[0] << 12) | (d[1] << 4) | (d[2] >> 4)
    adc_T = (d[3] << 12) | (d[4] << 4) | (d[5] >> 4)
    adc_H = (d[6] << 8)  |  d[7]

    temp, t_fine = compensate_temperature(adc_T, calib)
    hum          = compensate_humidity(adc_H, t_fine, calib)

    print(f"Sıcaklık : {temp:.2f} °C")
    print(f"Nem      : {hum:.2f} %")

08 Troubleshooting

I²C sorunlarının büyük çoğunluğu pull-up değerleri, clock stretching veya bus stuck durumundan kaynaklanır.

Bus stuck — SDA veya SCL sürekli düşük

Ani güç kesintisi veya hatalı transaction sonrası slave SDA'yı düşük tutabilir. Çözüm:

bash — bus recovery
# 1) Hata mesajını kontrol et:
dmesg | grep i2c
# [ 142.3] i2c i2c-1: adapter timeout
# [ 142.3] i2c i2c-1: sendbytes: error -11

# 2) 9 dummy clock pulse ile slave'i serbest bırak (yazılımsal):
sudo i2cdetect -y 1  # bus'ı test et

# 3) I²C adaptörünü kernel'den sıfırla (BCM2835 örneği):
echo "3e804000.i2c" | sudo tee /sys/bus/platform/drivers/i2c-bcm2835/unbind
echo "3e804000.i2c" | sudo tee /sys/bus/platform/drivers/i2c-bcm2835/bind

Clock stretching sorunu

Bazı SoC'ler (özellikle Raspberry Pi BCM2835) clock stretching'i yanlış uygular. Slave yavaşsa SCL'yi düşük tutarak zaman kazanır; BCM2835 bu durumu yanlış işler. Çözüm: I²C hızını düşür.

/boot/config.txt (Raspberry Pi)
# I²C hızını 50 kHz'e düşür (clock stretching sorunları için):
dtparam=i2c_arm=on,i2c_arm_baudrate=50000

Oscilloscope ile I²C decode

Logic analyzer veya oscilloscope ile I²C trafiği analiz edilebilir:

  • SDA ve SCL kanallarını ayrı ayrı bağla.
  • Trigger: SCL düşen kenar (falling edge) veya SDA düşen kenar (SCL yüksekken = START).
  • Sigrok / PulseView ile "I²C" protocol decoder seç: adres, R/W biti, ACK/NACK, data baytları otomatik decode edilir.
  • ACK yerine NACK görünüyorsa: yanlış adres, cihaz powered off veya bus stuck.
BelirtiOlası nedenÇözüm
i2cdetect çıktısı tamamen boş (--)Pull-up yok, cihaz beslenmiyor, SDA/SCL tersBağlantıları kontrol et, 4.7kΩ pull-up ekle
UU gösterimi (cihaz meşgul)Kernel driver cihazı zaten açmışKernel driver'ı devre dışı bırak ya da i2ctransfer kullan
NACK alınıyorYanlış adres veya cihaz powered offDatasheet'ten adresi doğrula, ADDR pinini kontrol et
Veri bozuk / CRC hatasıBus hızı çok yüksek, pull-up yetersizHızı düşür, pull-up direncini küçült
Intermittent hatalarEMI, uzun kablo, kapasitif yükKablo uzunluğunu kıs, buffer IC kullan