Под TTL вы подразумеваете UART (где периферийное устройство получает / отправляет последовательный поток автоматически) или битовые удары (где вы вручную устанавливаете / сбрасываете / переключаете биты)?
Я бы, вероятно, порекомендовал SPI. Это относительно простой протокол, и на стороне мастера, если вам нужно, вы можете его побить. (Но гораздо проще использовать встроенную периферию SPI.) Мастер SPI отправляет линию синхронизации (SCLK) и линию данных (MOSI = master out slave in), где биты данных действительны на назначенном фронте тактовой частоты. линия; он получает линию данных (MISO = master in slave out) от подчиненного устройства, где биты данных действительны на обозначенном фронте линии синхронизации. Если у вас есть несколько ведомых, обычно используется одна строка выбора чипа (CS) для каждого подчиненного устройства; если CS низок, то рассматриваемый ведомый активен, в противном случае он должен игнорировать сигналы часов / данных и не нарушать линию MISO. SPI прост и будет работать даже с выходным регистром HC594 или HC595 (свяжите MOSI с SER, SCLK с SCK, CS с RCK), если у вашего микроконтроллера нет контактов на выходном порте, и вам нужно несколько дополнительных. Если у вас более 3 SPI-устройств, рассмотрите возможность использования HC138 в качестве декодера для получения линий CS отдельных устройств из набора битов адреса и линии выбора мастер-чипа из микропроцессора. (поскольку предполагается, что только одна линия CS должна быть низкой одновременно)
I2C - это боль. Его главное преимущество заключается в том, что вы можете делать все по 2 проводам (+ питание и земля), совместно используемым множеством периферийных устройств. Но вы должны справиться с конфликтом адресов и кучей других вещей. Он также медленнее, чем SPI, и имеет линии с открытым коллектором, поэтому его энергопотребление + помехоустойчивость связаны с тем, что вы используете для нагрузочных резисторов (или источников тока).
UART может быть самым быстрым решением. SPI имеет ограничение скорости, связанное с временем распространения в оба конца, поскольку обе стороны используют один и тот же тактовый сигнал. (путь сигнала = ведущий меняет вывод SCLK, ведомый видит его и отвечает изменением вывода MISO, затем ведущий использует сигнал MISO на следующем фронте SCLK, так что сигнал от ведомого должен был прибыть к тому времени) являются независимыми, и задержка не означает, что ваша пропускная способность снижается, если протокол высокого уровня не предназначен для того, чтобы конечная точка UART A отправляла команду в конечную точку UART B, ожидала ответа B и затем отправляла следующую команду. Действительно быстрые последовательные потоки должны рассмотреть возможность использования LVDS для поддержания целостности сигнала. Но анализ байтов UART является своего рода болью по сравнению с SPI; в SPI есть четко разграниченные пакеты, тогда как в UART вы имеете дело с неограниченным последовательным потоком, и любое пакетирование должно выполняться путем анализа самих данных.
edit: еще один плюс с UART, заключается в том, что иногда процессор может автоматически обрабатывать большие буферы отправки / получения, так что ваша программа может поставить в очередь большой блок байтов для отправки, а затем проанализировать группу полученных байтов когда тебе хочется Аппаратное обеспечение может обрабатывать немедленную отправку / получение каждого отдельного байта и освобождает вашу программу от беспокойства о пропущенных отдельных байтах, которые появляются, когда ваша программа делает что-то еще.