Pengorbanan apa yang harus saya pertimbangkan ketika memutuskan untuk menggunakan antarmuka SPI atau I2C?
Papan breakout accelerometer / gyro ini tersedia dalam dua model, satu untuk setiap antarmuka. Apakah salah satu lebih mudah untuk diintegrasikan ke dalam proyek Arduino?
Jawaban:
Ringkasan
I2C adalah sistem bus dengan data dua arah pada jalur SDA. SPI adalah koneksi point-to-point dengan data masuk dan data keluar pada jalur terpisah (MOSI dan MISO).
Pada dasarnya SPI terdiri dari sepasang register geser, di mana Anda memasukkan data ke satu register geser sementara Anda mengeluarkan data dari yang lain. Biasanya data ditulis dalam byte dengan setiap kali pulsa 8 jam berturut-turut, tapi itu bukan persyaratan SPI. Anda juga dapat memiliki panjang kata 16 bit atau bahkan 13 bit, jika Anda mau. Sementara dalam sinkronisasi I2C dilakukan oleh urutan mulai di SPI itu dilakukan oleh SS menjadi tinggi (SS aktif rendah). Anda memutuskan sendiri setelah berapa jam pulsa ini. Jika Anda menggunakan kata-kata 13 bit, SS akan mengunci yang terakhir di-bit setelah 13 pulsa.
Karena data dua arah ada di dua jalur yang terpisah, mudah untuk dihubungi.
SPI dalam mode standar membutuhkan setidaknya empat baris: SCLK (jam serial), MOSI (Master Out Slave In), MISO (Master In Slave Out) dan SS (Slave Select). Dalam mode bideroctional memerlukan setidaknya tiga baris: SCLK (jam serial), MIMO (Master In Master Out) yang merupakan salah satu jalur MOSI atau MISO dan SS (Slave Select). Dalam sistem dengan lebih dari satu budak, Anda memerlukan garis SS untuk setiap budak, sehingga untuk budak Anda memiliki baris dalam mode standar dan baris dalam mode dua arah. Jika Anda tidak menginginkan itu, dalam mode standar Anda dapat daisy-chain para budak dengan menghubungkan sinyal MOSI satu budak ke MISO berikutnya. Ini akan memperlambat komunikasi karena Anda harus menggilir semua data budak.N + 3 N + 2N N+ 3 N+ 2
Seperti kata tcrosley, SPI dapat beroperasi pada frekuensi yang jauh lebih tinggi daripada I2C.
I2C sedikit lebih kompleks. Karena ini adalah bus, Anda perlu cara untuk mengatasi perangkat. Komunikasi Anda dimulai dengan urutan awal yang unik: jalur data (SDA) ditarik rendah sementara jam (SCL) tinggi, untuk sisa data komunikasi hanya diperbolehkan untuk berubah ketika jam rendah. Urutan mulai ini menyinkronkan setiap komunikasi.
Karena komunikasi mencakup pengalamatan, maka hanya dua jalur yang diperlukan untuk sejumlah perangkat (hingga 127).
Setelah setiap byte (alamat atau data) dikirim, penerima harus mengakui tanda terima dengan menempatkan pulsa yang diakui pada SDA. Jika mikrokontroler Anda memiliki antarmuka I2C ini secara otomatis akan diurus. Anda masih dapat menggigitnya jika mikrokontroler tidak mendukungnya, tetapi Anda harus mengganti pin I / O dari output ke input untuk setiap data yang diakui atau dibaca, kecuali jika Anda menggunakan pin I / O untuk membaca dan satu untuk menulis.
Pada standar 400kHz I2C jauh lebih lambat daripada SPI. Ada perangkat I2C kecepatan tinggi yang beroperasi pada 1MHz, masih jauh lebih lambat dari 20MHz SPI.
sumber
(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.
sumber
Papan breakout untuk perangkat di SparkFun sebenarnya hanya untuk versi I2C (MPU-6500). Versi MPU-6000 memiliki antarmuka SPI dan I2C pada chip yang sama, dan saya tidak melihat bahwa SparkFun memiliki papan dengan chip itu. Jadi saya yakin Anda terbatas untuk menggunakan I2C jika Anda ingin menggunakan papan khusus itu. Tapi saya tetap akan merekomendasikan menggunakan I2C dalam situasi Anda karena alasan berikut.
Secara umum, Anda akan menemukan bahwa bus I2C lebih mudah digunakan dari sudut pandang perangkat keras daripada bus SPI. I2C adalah bus 2 kawat (SCL / SDA):
SPI adalah bus 4 kawat (SCLK / MOSI / MISO / CS):
Anda dapat memiliki beberapa perangkat yang terhubung ke satu bus I2C. Setiap perangkat memiliki set alamat bawaan untuk chip tersebut. Alamat sebenarnya disiarkan melalui bus sebagai byte pertama dari setiap perintah (bersama dengan bit baca / tulis). Ini, bersama dengan beberapa overhead lainnya, membutuhkan lebih banyak bit untuk dikirim melalui bus I2C vs SPI untuk fungsi yang sama.
Kelas perangkat yang berbeda (memori, I / O, LCD, dll.) Memiliki rentang alamat yang berbeda. Beberapa perangkat, yang biasa digunakan lebih dari satu kali dalam suatu sistem (seperti PCF8574 I / O expander), menggunakan satu atau lebih garis alamat (AD0-2 untuk PCF8574) yang dapat diikat tinggi atau rendah untuk menentukan bit rendah dari alamat. MPU-6500 memiliki satu baris alamat seperti itu (AD0), sehingga dua di antaranya dapat digunakan dalam sistem yang sama.
Anda juga dapat memiliki banyak perangkat di bus SPI, tetapi setiap perangkat harus memiliki jalur pilih chip (CS) sendiri. Oleh karena itu deskripsi 4-kawat sedikit keliru - itu benar-benar antarmuka tiga kawat + satu kawat tambahan per perangkat. Saya tidak berpengalaman dengan seri papan Arduino, tapi saya percaya ini akan membuat menggunakan SPI lebih sulit pada Arduino, karena jika Anda membutuhkan banyak garis pilih chip ini akan mulai menjadi rumit dengan penugasan pin umum yang digunakan oleh berbagai perisai .
Saya percaya sebagian besar papan Arduino berjalan pada 5 volt, dengan beberapa yang lebih baru berjalan pada 3.3V. MPU-6500 beroperasi pada 3.3v. Jika tegangan input "tinggi" minimum untuk bus I2C pada CPU 5v adalah 3v atau di bawah, Anda dapat menghindari masalah konversi level dengan hanya menyediakan resistor penarik 10K hingga 3,3v pada jalur SCL dan SDA, karena bus terbuka pengumpul. Pastikan 5v internal pullup pada CPU dinonaktifkan.
Namun saya memeriksa datasheet untuk ATmega2560 (menggunakan ADK 5v Arduino sebagai contoh), dan tegangan minimum input 'tinggi "adalah 0,7 * Vcc, atau 3,5v yang lebih besar dari 3,3 v. Jadi, Anda perlu semacam level aktif Konversi. TI PCA9306 , yang membutuhkan resistor pullup pada sisi 5v dan 3.3v chip, harganya hanya 78 sen dalam jumlah tunggal.
Lalu mengapa memilih SPI daripada I2C? Terutama karena SPI dapat berjalan jauh lebih cepat - hingga 10-an MHz dalam beberapa kasus. I2C umumnya dibatasi hingga 400 KHz. Tapi ini bukan masalah untuk accelerometer MPU-6050/6000, karena beroperasi pada 400 KHz untuk I2C, dan hanya 1 MHz untuk SPI - tidak banyak perbedaan.
sumber
Secara umum, SPI adalah bus yang lebih cepat - frekuensi clock dapat berada dalam kisaran MHz. Namun, SPI membutuhkan setidaknya 3 jalur untuk komunikasi dua arah dan tambahan budak yang dipilih untuk setiap perangkat di bus.
I2C hanya membutuhkan 2 baris, terlepas dari berapa banyak perangkat yang Anda miliki (dalam batas, tentu saja). Kecepatannya, bagaimanapun, adalah dalam kisaran kHz (100-400kHz khas).
Sebagian besar mikrokontroler, saat ini, memiliki dukungan perangkat keras untuk kedua bus, sehingga keduanya sama-sama mudah digunakan.
sumber
I2C is designed for on-board applications.
- Rupanya produsen perangkat I2C tidak setuju dengan Anda. Ambil TMP100 . Halaman produk secara eksplisit menyatakan:The TMP100 and TMP101 are ideal for extended temperature measurement in a variety of communication, computer, consumer, environmental, industrial, and instrumentation applications.
Hal yang sama berlaku untuk TMP75SPI dapat berjalan jauh lebih cepat daripada I2C (beberapa perangkat SPI melebihi 60MHz; Saya tidak tahu apakah "IHS" spec resmi memungkinkan perangkat lebih dari 1MHz). Implementasi perangkat budak menggunakan protokol mana pun membutuhkan dukungan perangkat keras, sementara keduanya memungkinkan implementasi master "software bit-bang" yang mudah. Dengan perangkat keras yang relatif minimal, seseorang dapat membangun budak yang sesuai dengan I2C yang akan beroperasi dengan benar bahkan jika tuan rumah dapat secara sewenang-wenang memutuskan untuk mengabaikan bus hingga 500 us pada suatu waktu, tanpa perlu kabel handshaking tambahan. Namun, operasi SPI yang andal, bahkan dengan dukungan perangkat keras , umumnya mengharuskan seseorang untuk menambahkan kawat jabat tangan, atau jika tuan rumah "secara manual" menambahkan penundaan setelah setiap byte sama dengan waktu respons kasus terburuk budak.
Jika saya memiliki pemabuk saya, dukungan SPI controller akan berisi beberapa fitur tambahan sederhana untuk memberikan transfer data dua arah transparan 8-bit antara controller dengan kemampuan handshaking dan wake-up, menggunakan total tiga kabel searah (Clock dan MOSI [master -out-slave-in] dari master; MISO [master-in-slave-out] dari slave). Sebagai perbandingan, komunikasi yang efisien dan andal antara mikrokontroler dengan port SPI "stock", ketika kedua prosesor mungkin secara independen ditunda untuk jangka waktu yang sewenang-wenang, membutuhkan penggunaan lebih banyak kabel (Pilih Chip, Clock, MISO, dan MOSI untuk memulai) dengan, ditambah semacam kawat yang diakui dari budak. Jika budak tersebut secara asinkron mulai mengirim data (misalnya karena seseorang menekan tombol), maka seseorang harus menggunakan kabel lain sebagai "bangun"
I2C tidak menyediakan semua kemampuan yang dimiliki SPI "ditingkatkan" saya, tetapi ia menawarkan kemampuan handshaking bawaan yang tidak dimiliki SPI, dan dalam banyak implementasi dapat dikompilasi untuk menyediakan bangun juga, bahkan jika masternya adalah seorang perangkat lunak bit-bang. Untuk komunikasi antar-prosesor, oleh karena itu saya akan sangat merekomendasikan I2C lebih dari SPI kecuali ketika kecepatan yang lebih tinggi diperlukan daripada yang dapat disediakan SPI, dan penggunaan pin tambahan dapat diterima. Untuk komunikasi antar-prosesor di mana jumlah pin rendah diperlukan, UART harus banyak merekomendasikannya.
sumber
Pertanyaan ini telah sepenuhnya dieksplorasi dalam jawaban yang sangat baik di sini, tetapi mungkin ada satu sudut pandang lagi untuk I 2 C yang bisa saya tawarkan dari sudut pandang pembuat chip.
Antarmuka listrik I 2 C adalah kolektor terbuka . Sekarang bernafas dan pikirkan implikasinya. Dengan menggunakan I 2 C, saya dapat merancang chip yang benar-benar agnostik terhadap tegangan pengoperasian bus. Yang perlu saya lakukan hanyalah menarik garis SDA rendah jika itu menyenangkan saya, dan membandingkan tegangan SCL dan SDA dengan beberapa tegangan ambang batas tanah yang direferensikan, yang dapat saya pilih. Dan jika saya meninggalkan struktur perlindungan sisi tinggi normal dan menggantinya dengan struktur lain, saya dapat membuat chip yang benar-benar dapat hidup sendiri tanpa tergantung dari sisa sistem - SCL, SDA tidak pernah memberi makan arus ke chip saya dan saya tentu tidak akan memberi makan arus ke pin tersebut. Itu sebabnya bus yang bagus untuk jam waktu nyata dan hal-hal berdaya rendah lainnya seperti itu.
sumber
Satu hal yang belum saya lihat disebutkan dalam jawaban lain adalah bahwa I2C mendukung banyak master di bus yang sama. Jika Anda memerlukan komunikasi dua arah dan tidak ingin menggunakan metode berbasis polling, I2C akan menyelesaikan pekerjaan.
Jarak yang lebih jauh, CAN memiliki kemampuan yang sama dan lebih kuat. Tetapi CAN adalah protokol asinkron yang memerlukan dukungan perangkat keras dan transceiver, sehingga mungkin bukan opsi dalam sistem berbiaya rendah.
sumber
Gunakan protokol SPI dan tulis bit Anda langsung ke perangkat setiap kali jam sinkronisasi naik. Rangkaian logika xnor dapat digunakan untuk mencocokkan alamat "buatan sendiri" dari memori untuk memilih perangkat yang diinginkan seolah-olah itu adalah perangkat i2c.
I2c mengintegrasikan sirkuit authorial di dalam format perangkat, standar ... dll yang kompleks dan berbeda, dengan spi Anda dapat menggunakan memori spi untuk menampilkan video di layar, tetapi tidak i2c.
sumber