Які компроміси слід враховувати, приймаючи рішення використовувати інтерфейс SPI або I2C?
Ця плата акселерометра / гіроскопа доступна у двох моделях, по одній для кожного інтерфейсу. Чи було б простіше інтегруватися в проект Arduino?
Які компроміси слід враховувати, приймаючи рішення використовувати інтерфейс SPI або I2C?
Ця плата акселерометра / гіроскопа доступна у двох моделях, по одній для кожного інтерфейсу. Чи було б простіше інтегруватися в проект Arduino?
Відповіді:
Підсумок
I2C - шинна система з двонаправленими даними на лінії SDA. SPI - це з'єднання «точка-точка» з даними та виведеннями даних на окремих лініях (MOSI та MISO).
По суті SPI складається з пари регістрів зрушення, де ви переносите дані в один регістр змін, поки ви обробляєте дані з іншого. Зазвичай дані записуються в байтах, кожен раз підряд проводячи 8 тактових імпульсів, але це не вимога SPI. Ви також можете мати довжину слів 16 біт або навіть 13 біт, якщо хочете. У той час як в I2C синхронізація виконується за допомогою послідовності запуску в SPI, це робиться SS, що йде вгору (SS активний низький). Ви самі вирішуєте, скільки це імпульси годин. Якщо ви використовуєте 13-бітові слова, SS зафіксує останній такт в бітах після 13 тактових імпульсів.
Оскільки двонаправлені дані є двома окремими рядками, їх легко інтерфейсувати.
Як каже tcrosley, SPI може працювати на набагато більшій частоті, ніж I2C.
I2C трохи складніший. Оскільки це шина, вам потрібен спосіб адресації пристроїв. Ваша комунікація починається з унікальної послідовності запуску: лінія даних (SDA) знижується низько, тоді як тактова частота (SCL) висока, для решти даних зв'язку можна змінювати лише тоді, коли годинник низький. Ця послідовність запуску синхронізує кожну комунікацію.
Оскільки комунікація включає адресацію, потрібні лише два рядки для будь-якої кількості пристроїв (до 127).
редагувати
Очевидно, що рядок даних є двонаправленим, але варто зазначити, що це також стосується тактової лінії. Раби можуть розтягувати годинник, щоб контролювати швидкість шини. Це робить I2C менш зручним для зміщення рівня або буферизації. (Лінії SPI у стандартному режимі всі односпрямовані.)
Після надсилання кожного байта (адреси або даних) одержувач повинен підтвердити отримання, надіславши імпульс підтвердження на SDA. Якщо у вашого мікроконтролера є інтерфейс I2C, про це автоматично потурбується. Ви все ще можете трохи розбивати його, якщо ваш мікроконтролер не підтримує його, але вам доведеться перемикати штифт вводу / виводу з виводу на вхід для кожного підтвердження чи зчитування даних, якщо ви не використовуєте штифт вводу / виводу для читання та один для написання.
На 400 кГц стандарт I2C набагато повільніше, ніж SPI. Існують високошвидкісні пристрої I2C, які працюють на частоті 1 МГц, все ще набагато повільніше SPI 20 МГц.
(відредагувати. Щоб зрозуміти, багато з перерахованих нижче проблем пов'язані з цілісністю сигналу, спричиненим використанням плати на борт пристроїв 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.
Роздільна плата для пристрою SparkFun насправді лише для версії I2C (MPU-6500). Версія MPU-6000 має інтерфейси SPI та I2C на одній мікросхемі, і я не бачу, що у SparkFun є плата з цим чіпом. Тож я вважаю, що ви обмежені в користуванні I2C, якщо хочете використовувати саме цю плату. Але я збирався рекомендувати використовувати I2C у вашій ситуації з наступних причин.
Загалом, ви побачите, що шину I2C легше використовувати з апаратної точки зору, ніж шину SPI. I2C - двопровідна шина (SCL / SDA):
SCL – Serial clock.
SDA – Serial data (bidirectional).
SPI - це 4-провідна шина (SCLK / MOSI / MISO / CS):
SCLK– Serial clock.
MOSI – Master-out, Slave-in. Data from the CPU to the peripheral.
MISO – Master-in, Slave out. Data from the peripheral back to the CPU.
CS – Chip select.
До однієї шини I2C можна підключити кілька пристроїв. Кожен пристрій має свій власний набір адрес, вбудований у мікросхему. Адреса фактично транслюється по шині як перший байт кожної команди (разом з бітом читання / запису). Це, поряд з деякими іншими накладними, вимагає надсилати більше бітів через шину I2C проти SPI для однакової функціональності.
Різні класи пристроїв (пам'ять, введення / виведення, LCD та ін.) Мають різні діапазони адрес. Деякі пристрої, які зазвичай не раз використовуються в системі (наприклад, розширювач вводу / виводу PCF8574), використовують один або кілька адресних рядків (AD0-2 для PCF8574), які можуть бути пов'язані високими або низькими для визначення низьких бітів. адреси. MPU-6500 має один такий рядок адрес (AD0), тому два з них можна використовувати в одній і тій же системі.
Ви також можете мати кілька пристроїв на шині SPI, але кожен пристрій повинен мати власну лінію вибору чіпа (CS). Тому 4-провідне опис є дещо помилковим - це дійсно трипроводовий інтерфейс + один додатковий провід на пристрій. Я не маю досвіду з серіями дощок Arduino, але я вважаю, що це зробило б використання SPI більше труднощів на Arduino, оскільки якщо вам знадобиться багато ліній для вибору чіпів, це почне ставати громіздким із загальних призначень штифтів, які використовуються різними щитами .
Я вважаю, що більшість плат Arduino працюють на 5 вольт, а новіші працюють на 3,3 В. MPU-6500 працює на 3.3V. Якщо мінімальна вхідна "висока" напруга для шини I2C на процесорі 5 В становить 3 В або нижче, ви можете уникнути проблем з перетворенням рівня, просто надавши 10K резисторів підтяжки до 3,3 В на лініях SCL і SDA, оскільки шина відкрита- колектор. Переконайтесь, що будь-які внутрішні підключення на процесорі 5В вимкнено.
Однак я перевірив таблицю даних для ATmega2560 (використовуючи ADK 5v Arduino як приклад), і її мінімальна вхідна "висока" напруга становить 0,7 * Vcc, або 3,5 V, що перевищує 3,3 В, тому вам потрібен якийсь активний рівень TI PCA9306 , який вимагає підтягування резисторів як на 5В, так і на 3,3В стороні мікросхеми, коштує всього 78 центів в одній кількості.
Чому тоді взагалі вибирати SPI над I2C? Головним чином, SPI можна запустити набагато швидше - в деяких випадках до 10-ти МГц. I2C, як правило, обмежений 400 кГц. Але це насправді не проблема для акселерометра MPU-6050/6000, оскільки він працює на частоті 400 КГц для I2C, і лише 1 МГц для SPI - це не велика різниця.
Загалом, SPI - це швидша шина - тактова частота може знаходитися в діапазоні МГц. Однак SPI вимагає щонайменше 3 ліній для двостороннього зв’язку та додаткового вибору підлеглого для кожного пристрою в шині.
I2C вимагає лише 2 рядки, незалежно від того, скільки у вас пристроїв (звичайно, в межах). Однак швидкість знаходиться в діапазоні кГц (типовим є 100-400 кГц).
В даний час більшість мікроконтролерів мають апаратну підтримку обох шин, тому обидва однаково прості у використанні.
I2C is designed for on-board applications.
- Мабуть, виробники пристроїв I2C не згодні з вами. Візьміть TMP100 . На сторінці продукту прямо вказано: The TMP100 and TMP101 are ideal for extended temperature measurement in a variety of communication, computer, consumer, environmental, industrial, and instrumentation applications.
Те саме стосується TMP75
SPI можна запустити набагато швидше, ніж I2C (деякі SPI-пристрої переходять на 60 МГц; я не знаю, чи "офіційна" специфікація I2C дозволяє пристроям понад 1 МГц). Реалізація веденого пристрою за допомогою будь-якого протоколу вимагає апаратної підтримки, в той час як обидва дозволяють легко реалізувати майстри програмного забезпечення біт-бангу. При відносно мінімальному апаратному забезпеченні можна побудувати сумісний I2C-ведений, який буде працювати правильно, навіть якщо хост може довільно вирішити ігнорувати шину до 500us одночасно, не потребуючи додаткових проводів рукостискання. Надійне функціонування SPI, однак, навіть при апаратній підтримці , як правило, вимагає або додати провід рукостискання, або ж хост "вручну" додати затримку після кожного байту, що дорівнює найгіршому часу реакції підлеглого.
Якби я мав свої барабани, підтримка SPI контролерів містила б кілька простих додаткових функцій, щоб забезпечити 8-бітну прозору двонаправлену передачу даних між контролерами з можливістю рукостискання та пробудження, використовуючи в цілому три однонаправлені дроти (Clock та MOSI [master -out-slave-in] від господаря; MISO [master-in-slave-out] від раба). Для порівняння, ефективний та надійний зв'язок між мікроконтролерами з "запасними" SPI-портами, коли обидва процесори можуть самостійно затримуватися на довільну тривалість часу, вимагає використання набагато більше проводів (Chip-Select, Clock, MISO та MOSI для запуску з, плюс якийсь провід підтвердження від підлеглого. Якщо підлеглий може асинхронно почати мати дані для надсилання (наприклад, через те, що хтось натиснув кнопку), то потрібно або використовувати ще один провід як "пробудження"
I2C не надає всіх можливостей, які мій "покращений" SPI мав би, але він пропонує вбудовані здібності рукостискання, яких не вистачає SPI, і в багатьох реалізаціях його можна збивати і з пробудженням, навіть якщо майстер є програмне забезпечення біт-баг. Тому для міжпроцесорного зв’язку я настійно рекомендую I2C над SPI, за винятком випадків, коли потрібні більші швидкості, ніж SPI, і використання додаткових штифтів є прийнятним. Для міжпроцесорних комунікацій, де потрібна низька кількість контактів, UART мають багато, щоб їх рекомендувати.
Це питання було ретельно досліджено у чудових відповідях тут, але, можливо, є ще одна точка зору на I 2 C, яку я міг би запропонувати з точки зору виробника чіпів.
Електричний інтерфейс I 2 C - це відкритий колектор . Тепер дихайте і думайте про наслідки. Використовуючи I 2 C, я можу створити мікросхему, яка є абсолютно агностичною для робочої напруги шини. Все, що мені потрібно зробити, - це підтягнути лінію ПДД низько, якщо це мені подобається, і порівняти напруги SCL і SDA з деякою пороговою напругою, яку я можу вибрати. І якщо я залишу звичайні конструкції з високою стороною захисту і замінюю їх іншими структурами, я можу зробити мікросхему, яка може повністю жити власним життям незалежно від решти системи - SCL, SDA ніколи не подає струму на мій чіп, і я звичайно, не буде подавати струм на ці шпильки. Ось чому це такий приємний автобус для годинників у режимі реального часу та інших подібних матеріалів.
Одне, що я не бачив згадуваних в інших відповідях, це те, що I2C підтримує декілька майстрів на одній шині. Якщо вам потрібна двонаправлена комунікація і ви не хочете використовувати метод опитування на основі опитування, I2C виконає роботу.
На більших відстанях CAN має таку ж здатність і більш міцний. Але CAN - це асинхронний протокол, який вимагає апаратної підтримки та приймача, тому це може бути не варіантом в системі недорогих.
Використовуйте протокол SPI і записуйте свої біти безпосередньо на пристрій кожного разу, коли годинник синхронізації піднімається. Логічна схема xnor може використовуватися для узгодження "саморобної" адреси з пам'яті для вибору потрібного пристрою, як якщо б це був пристрій i2c.
I2c інтегрує авторську схему всередині формату пристрою, стандартні ... тощо є складними та різними, за допомогою spi можна використовувати спіраль пам'яті для відображення відео на екрані, але не i2c.