(відредагувати. Щоб зрозуміти, багато з перерахованих нижче проблем пов'язані з цілісністю сигналу, спричиненим використанням плати на борт пристроїв I2C / SPI, як правильно вказує Олін.)
Якщо у вас немає обмежень, які сильно підштовхують вас до меншої кількості проводів (у нас був один проект із герметично закритим роз'ємом, що кожен додатковий контакт був досить дорогим), уникайте I2C, коли це можливо, і дотримуйтесь SPI.
Із SPI досить легко впоратися на апаратній та програмній основі. В апараті є дві спільні лінії передачі даних: Master In Slave Out (MISO або SOMI) і Master Out Slave In (MOSI або SIMO), спільний годинник, що генерується майстром, і один вибір мікросхеми на кожному пристрої. Рядок CS знижується, тактовий цикл і, по суті, зміщується у вхідних бітах і зміщується з вихідних бітів, поки транзакція не закінчиться, і в цей момент лінія CS переходить у висоту. Коли їх лінія CS висока, підлеглі пристрої не спілкуються: вони ігнорують лінії CLK та MOSI і ставлять свій штифт MISO у стан високого опору, щоб хтось інший використовував його.
Якщо у вас є мікроконтролер, що використовує декілька пристроїв SPI, і він має вбудовану периферійну модуль SPI, надішліть висновок CS мікроконтролера на демультиплексор (наприклад, 74HC138) та керуйте лініями адреси для вибору пристрою між транзакціями SPI; ви записуєте слова в реєстр, щоб поставити їх у чергу для виведення, і прочитаєте їх назад після того, як штифт CS буде піднятий високо.
Оскільки сигнали SPI є односпрямованими, вони можуть бути буферизовані, використовуватися через бар'єр ізоляції з цифровими ізоляторами і можуть надсилатися з борту на борт за допомогою лінійних драйверів, таких як LVDS. Єдине, про що ви повинні турбуватися, - це затримка поширення в обидва кінці, яка обмежить вашу максимальну частоту.
I2C - зовсім інша історія. Хоча з точки зору проводки це набагато простіше, маючи лише два дроти SCL і SDA, обидві ці лінії є спільними двосторонніми лініями, які використовують пристрої відкритого зливу із зовнішнім підключенням. Існує протокол для I2C, який починається з передачі адреси пристрою, так що можна використовувати декілька пристроїв, якщо кожен має свою власну адресу.
З апаратної точки зору, дуже важко використовувати I2C в системах, які мають будь-який значний шум. Щоб забудувати або ізолювати лінії I2C, вам доведеться вдатися до екзотичних ІС - так, вони існують, але їх не так багато: ми використовували один в одному проекті і зрозуміли, що можна використовувати один ізолятор, але ви не змогли використовуйте два послідовно - використовували невеликі перепади напруги, щоб визначити, яка сторона була рушійним кінцем речей, а два краплі серії - дві.
Пороги логічного рівня I2C залежать від Vcc, тому вам потрібно бути дуже обережним, якщо ви використовуєте пристрої 3V / 3.3V та 5V в одній системі.
Будь-які сигнали, які використовують кабель, більший за фут або два, повинні турбуватися про ємність кабелю. Потужність 100 п / метр не є звичайною для багатопровідникового кабелю. Це призводить до того, що вам доведеться гальмувати шину або використовувати резистори нижчих підтягувачів, щоб мати змогу належним чином працювати з додатковою ємністю та відповідати вимогам часу наростання.
Тож скажімо, у вас є система, яку ви вважаєте, що ви добре спроектували, і ви можете вирішити більшість питань цілісності сигналу, а шум рідкісний (але все ще присутній). Про що ти маєш хвилюватися?
Існує маса умов помилок, з якими ви повинні бути готові впоратися:
Підлеглий пристрій не визнає конкретний байт. Ви повинні виявити це і зупинити та перезапустити послідовність зв'язку. (За допомогою SPI ви можете зазвичай читати назад дані, які ви надсилаєте, якщо ви хочете переконатися, що вони отримані без помилок.)
Ви читаєте байт даних з підлеглого пристрою, і пристрій "загіпнотизоване" через шум на годинниковій лінії: Ви надіслали необхідні 8 годин, щоб прочитати цей байт, але через шум підлеглий пристрій вважає це отримав 7 годин і досі передає 0 в рядку даних. Якби пристрій отримав 8-й годинник, він би випустив лінію даних високою, щоб ведучий міг підняти або опустити лінію передачі даних для передачі біта ACK або NACK, або ведучий міг передати стан зупинки (P). Але раб як і раніше тримає рядок даних низько, марно чекаючи ще одного годинника. Якщо майстер не готовий спробувати додаткові годинники, шина I2C застрягне в тупику. Хоча я використовував декілька мікроконтролерів, які підтримують нормальні умови ACK / NACK,
Дійсно жахливий випадок, коли майстер записує дані в один підлеглий пристрій, а інший підлеглий трактує адресу пристрою неправильно і вважає, що передані дані призначені саме для цього. У нас були пристрої I2C (розширювачі вводу / виводу), які час від часу мають регістри, встановлені неправильно через це. Виявити цей випадок майже неможливо, і щоб бути надійним для шуму, вам доведеться періодично встановлювати всі регістри, так що якщо ви зіткнетеся з цією помилкою, принаймні вона буде виправлена через короткий проміжок часу. (У SPI ніколи не виникає такої проблеми - якщо у вас трапиться збій на лінії CS, вона ніколи не зберігатиметься довго, і ви не отримаєте дані випадково прочитані неправильним підлеглим пристроєм.)
Чимало цих умов можна було б правильно обробити в протоколі, якщо було б виявлення помилок (CRC-коди), але деякі пристрої мають це.
Я вважаю, що мені потрібно створити складне програмне забезпечення у своєму головному пристрої I2C, щоб впоратися з цими умовами. На мою думку, це просто не варто, якщо тільки обмеження в проводці не змусять нас використовувати I2C, а не SPI.