(sunting: Agar jelas, banyak dari keprihatinan berikut ini berkaitan dengan integritas sinyal yang disebabkan oleh penggunaan perangkat I2C / SPI dari papan ke papan, seperti yang ditunjukkan Olin dengan benar.)
Kecuali Anda memiliki kendala yang sangat mendorong Anda ke arah kabel yang lebih sedikit (kami memiliki satu proyek dengan konektor yang tertutup rapat sehingga setiap kontak tambahan agak mahal), hindari I2C jika memungkinkan, dan tetap menggunakan SPI.
SPI cukup mudah untuk ditangani berdasarkan perangkat keras dan perangkat lunak. Dalam perangkat keras, ada dua jalur data bersama, Master In Slave Out (MISO atau SOMI) dan Master Out Slave In (MOSI atau SIMO), clock bersama yang dihasilkan oleh master, dan satu chip pilih per perangkat. Garis CS menjadi rendah, clock cycle dan pada dasarnya menggeser bit input dan menggeser bit output, sampai transaksi selesai, pada titik mana garis CS menjadi tinggi. Ketika garis CS mereka tinggi, perangkat slave tidak berkomunikasi: mereka mengabaikan garis CLK dan MOSI, dan menempatkan pin MISO mereka ke keadaan impedansi tinggi untuk membiarkan orang lain menggunakannya.
Jika Anda memiliki mikrokontroler menggunakan beberapa perangkat SPI, dan memiliki perangkat SPI bawaan, kirim output CS mikrokontroler ke demultiplexer (mis. 74HC138) dan kendalikan garis alamat untuk memilih perangkat di antara transaksi SPI; Anda menulis kata-kata ke register untuk membuat antrian untuk output, dan membacanya kembali setelah pin CS dinaikkan tinggi.
Karena sinyal SPI semuanya searah, mereka dapat disangga, digunakan melintasi penghalang isolasi dengan isolator digital, dan dapat dikirim dari papan ke papan menggunakan driver garis seperti LVDS. Satu-satunya hal yang harus Anda khawatirkan adalah penundaan propagasi bolak-balik, yang akan membatasi frekuensi maksimum Anda.
I2C adalah cerita yang sangat berbeda. Meskipun jauh lebih sederhana dari sudut pandang pemasangan kabel, dengan hanya dua kabel SCL dan SDA, kedua saluran ini adalah saluran dua arah bersama yang menggunakan perangkat saluran terbuka dengan pullup eksternal. Ada protokol untuk I2C yang dimulai dengan mengirimkan alamat perangkat, sehingga beberapa perangkat dapat digunakan jika masing-masing memiliki alamat mereka sendiri.
Dari sudut pandang perangkat keras, sangat sulit untuk menggunakan I2C dalam sistem yang memiliki noise yang signifikan. Untuk buffer atau mengisolasi jalur I2C, Anda harus menggunakan IC eksotis - ya, mereka ada, tetapi tidak ada banyak: kami menggunakan satu pada satu proyek dan menyadari bahwa Anda bisa menggunakan satu isolator, tetapi Anda tidak bisa gunakan dua seri - menggunakan tetesan voltase kecil untuk mengetahui sisi mana yang menjadi ujung penggerak, dan dua tetes seri dua.
Ambang level logika I2C bergantung pada Vcc sehingga Anda harus sangat berhati-hati jika menggunakan perangkat 3V / 3.3V dan 5V dalam sistem yang sama.
Setiap sinyal yang menggunakan kabel lebih dari satu atau dua kaki harus khawatir tentang kapasitansi kabel. Kapasitansi 100pf / meter tidak biasa untuk kabel multikonduktor. Ini menyebabkan Anda harus memperlambat bus, atau menggunakan resistor pullup yang lebih rendah, untuk dapat menangani kapasitansi tambahan dengan benar dan memenuhi persyaratan waktu naik.
Jadi katakanlah Anda memiliki sistem yang Anda pikir telah Anda rancang dengan baik, dan Anda dapat menangani sebagian besar masalah integritas sinyal, dan kebisingan jarang terjadi (tetapi masih ada). Apa yang harus kamu khawatirkan?
Ada banyak kondisi kesalahan yang harus siap Anda tangani:
Perangkat slave tidak mengakui byte tertentu. Anda harus mendeteksi ini dan menghentikan dan memulai kembali urutan komunikasi. (Dengan SPI, Anda biasanya dapat membaca kembali data yang Anda kirim jika Anda ingin memastikan itu diterima tanpa kesalahan.)
Anda membaca byte data dari perangkat slave, dan perangkat "terhipnotis" karena noise pada garis jam: Anda telah mengirim 8 jam yang diperlukan untuk membaca byte itu, tetapi karena noise, perangkat slave menganggapnya telah menerima 7 jam, dan masih mentransmisikan 0 pada baris data. Jika perangkat menerima clock ke-8, itu akan melepaskan jalur data tinggi sehingga master dapat menaikkan atau menurunkan jalur data untuk mengirimkan bit ACK atau NACK, atau master dapat mengirimkan kondisi stop (P). Tapi budak itu masih menahan garis data rendah, menunggu sia-sia untuk jam lain. Jika master tidak siap untuk mencoba jam tambahan, bus I2C akan macet. Sementara saya telah menggunakan beberapa mikrokontroler yang menangani kondisi ACK / NACK normal,
Kasus yang sangat mengerikan adalah ketika master menulis data ke satu perangkat slave, dan slave lain mengartikan alamat perangkat secara salah dan berpikir bahwa data yang dikirimkan dimaksudkan untuk itu. Kami memiliki perangkat I2C (I / O ekspander) yang terkadang memiliki register yang salah karena hal ini. Hampir tidak mungkin untuk mendeteksi kasus ini, dan agar kuat terhadap noise, Anda harus mengatur semua register secara berkala, sehingga jika Anda mengalami kesalahan ini, setidaknya itu akan diperbaiki setelah periode waktu yang singkat. (SPI tidak pernah memiliki masalah ini - jika Anda memiliki kesalahan pada saluran CS, itu tidak akan pernah bertahan lama dan Anda tidak akan mendapatkan data yang tidak sengaja terbaca oleh perangkat budak yang salah.)
Banyak dari kondisi ini dapat ditangani dengan benar dalam protokol jika ada deteksi kesalahan (kode CRC), tetapi beberapa perangkat memilikinya.
Saya menemukan bahwa saya harus membangun perangkat lunak yang kompleks di perangkat master I2C saya untuk menangani kondisi ini. Menurut pendapat saya, itu tidak layak kecuali kendala pada kabel memaksa kita untuk menggunakan I2C dan bukan SPI.