Fundamentos · 13 min de leitura

O que é SPI? Pinos MOSI, MISO, SCK e CS explicados para Arduino

O que é SPI e como funciona? Pinos MOSI, MISO, SCK e CS, modos e velocidade do SPI, vários dispositivos, pinos do Uno, Mega, ESP32 e Pico e o conflito entre cartão SD e RFID.

SPI (Serial Peripheral Interface, interface serial de periféricos) é um método de comunicação que permite a um microcontrolador trocar dados muito rapidamente com dispositivos como cartões SD, leitores RFID, displays TFT coloridos ou módulos sem fio usando quatro fios. Há uma linha de clock (SCK), duas linhas separadas para os dados em cada sentido (MOSI e MISO) e uma linha CS que escolhe com qual dispositivo se está conversando. Como pode ser dezenas de vezes mais rápido que o I2C, é o barramento preferido dos módulos que movimentam grandes quantidades de dados.

Neste post você vai aprender como o SPI funciona, os nomes dos pinos e a nomenclatura nova, os quatro modos SPI, os limites de velocidade, os pinos do Arduino Uno, do Mega, do ESP32 (VSPI e HSPI) e do Raspberry Pi Pico, como ligar vários dispositivos no mesmo barramento e por que um cartão SD e um leitor RFID RC522 dão problema juntos. Na última seção comparamos o SPI com o I2C e o UART.

O que é SPI e como funciona?

No SPI há sempre um controlador (antes chamado de master) e um ou mais periféricos (antes chamados de slaves). Só o controlador gera o clock; ou seja, o Arduino inicia a conversa, define a velocidade e a encerra. A cada pulso de clock, o controlador envia um bit pela MOSI enquanto, ao mesmo tempo, o periférico devolve um bit pela MISO. Os registradores de deslocamento dos dois lados formam uma espécie de anel: depois de 8 pulsos de clock, o byte do controlador passou para o periférico e o byte do periférico passou para o controlador. Por isso o SPI é full duplex: leitura e escrita acontecem ao mesmo tempo.

LinhaNome antigoNome novoSentidoFunção
SCK / SCLKSerial ClockSCKControlador → periféricoSinal de clock; um bit é transferido a cada pulso
MOSIMaster Out Slave InCOPI / SDOControlador → periféricoDados do Arduino para o módulo
MISOMaster In Slave OutCIPO / SDIPeriférico → controladorDados que voltam do módulo para o Arduino
CS / SSSlave SelectCS (Chip Select)Controlador → periféricoO módulo escuta enquanto está em LOW; cada dispositivo tem seu próprio CS

As marcações nos módulos nem sempre são iguais, e essa é a maior fonte de confusão. No módulo RFID RC522, a linha CS vem marcada como SDA (não tem nada a ver com o SDA do I2C), no nRF24L01 é CSN, no MCP3008 é CS/SHDN e em alguns displays você vai ver nomes como DIN (MOSI), CLK (SCK) e DOUT (MISO). A regra é simples: a entrada de dados (DIN, SDI, MOSI) vai na MOSI do Arduino e a saída de dados (DOUT, SDO, MISO) vai na MISO do Arduino.

  1. O controlador coloca em LOW a linha CS do dispositivo com que quer conversar. Todos os outros dispositivos mantêm o CS em HIGH e liberam a linha MISO.
  2. O controlador começa a gerar pulsos de clock na SCK.
  3. A cada pulso, um bit sai pela MOSI e um bit entra pela MISO. A ordem dos bits normalmente é o bit mais significativo primeiro (MSB first).
  4. Depois que o número necessário de bytes (comando, endereço, dados) foi transferido, o controlador coloca o CS de volta em HIGH e o dispositivo conclui a operação.

Modos SPI: CPOL e CPHA

O SPI não tem um padrão único; os dispositivos diferem no nível em que o clock fica parado quando ocioso (CPOL, polaridade do clock) e na borda do clock em que os dados são lidos (CPHA, fase do clock). As quatro combinações dessas duas configurações formam os quatro modos SPI. Se o controlador e o dispositivo não estiverem no mesmo modo, os dados ficam deslocados em um bit e você lê valores sem sentido. Felizmente, a grande maioria dos módulos usa o Modo 0.

ModoCPOLCPHAClock em repousoBorda em que os dados são lidosDispositivos de exemplo
SPI_MODE000LOWSubidaCartão SD, RC522, nRF24L01, MAX7219, MCP3008, 74HC595
SPI_MODE101LOWDescidaAlguns CIs de ADC e de driver
SPI_MODE210HIGHDescidaRaramente usado
SPI_MODE311HIGHSubidaAcelerômetro ADXL345, alguns displays ST7789 sem pino CS
Se você lê sempre 0xFF, 0x00 ou valores absurdos diferentes a cada vez de um módulo, confira primeiro no datasheet o modo SPI e a velocidade máxima de clock. Baixar a velocidade para 1 MHz e testar de novo mostra rapidamente se o problema é a fiação ou a configuração.

Velocidade do SPI e comprimento dos fios

No SPI quem define a velocidade é o controlador, e o limite costuma ser o próprio dispositivo. O Arduino Uno chega a 8 MHz, metade do seu clock de 16 MHz; o padrão da biblioteca SPI é 4 MHz. O ESP32 pode gerar até 80 MHz nos seus pinos SPI dedicados (IO_MUX), e o limite cai quando o sinal é roteado para outros pinos pela matriz GPIO. O Raspberry Pi Pico chega a cerca de 62,5 MHz com clock de sistema de 125 MHz. Sinais SPI rápidos pedem fios curtos: com protoboard e jumpers de 10–20 cm, alguns MHz funcionam sem problema; a partir de 20–30 MHz, mantenha os fios curtos e, se possível, use ligações soldadas. Comprimentos de vários metros não servem para SPI.

DispositivoFunçãoClock SPI máximo (datasheet)Modo SPI
Cartão microSDRegistro de dados400 kHz na inicialização, depois até 25 MHzModo 0
RC522 (MFRC522)Leitor RFID10 MHzModo 0
nRF24L01Comunicação sem fio de 2,4 GHz10 MHzModo 0
MAX7219Matriz de LED / 7 segmentos10 MHzModo 0
MCP3008ADC de 8 canais e 10 bits3,6 MHz em 5 V, 1,35 MHz em 2,7 VModo 0 ou 3
ILI9341TFT colorido de 2,4–3,2 polegadas10 MHz na escrita (na prática é usado bem mais rápido)Modo 0

Pinos SPI: Arduino Uno, Mega, ESP32 e Raspberry Pi Pico

LinhaArduino Uno / NanoArduino MegaESP32 VSPI (padrão)ESP32 HSPIRaspberry Pi Pico SPI0
SCKD13D52GPIO 18GPIO 14GP18
MOSID11D51GPIO 23GPIO 13GP19 (TX)
MISOD12D50GPIO 19GPIO 12GP16 (RX)
CS (padrão)D10D53GPIO 5GPIO 15GP17
Nível lógico5 V5 V3,3 V3,3 V3,3 V

No Uno, as mesmas linhas SPI também estão na barra ICSP de 6 pinos na borda da placa; em placas como o Leonardo e o Micro, o SPI só está disponível no ICSP. O D10 não é obrigatório como CS; você pode usar qualquer pino digital. Porém, no Uno não deixe o D10 como entrada: se o hardware SPI ler LOW no D10 enquanto ele é entrada, sai do modo controlador. O SPI.begin() transforma esse pino em saída automaticamente, e você não deve transformá-lo em entrada para outra função. No ESP32, o objeto SPI do Arduino usa o VSPI por padrão; graças à matriz GPIO, você também pode levar o SPI para quase qualquer pino. No Pico, o SPI0 e o SPI1 podem ser atribuídos a vários grupos de pinos diferentes (por exemplo, GP10, GP11, GP12 para o SPI1); veja os detalhes na ferramenta Pinagem.

O RC522, o nRF24L01 e os próprios cartões SD são dispositivos de 3,3 V. Ligá-los direto nos sinais de 5 V do Uno pode danificá-los com o tempo. A maioria dos módulos de cartão SD prontos já tem um conversor de nível; já o RC522 e o nRF24L01, alimente pelo pino 3V3 e considere usar um conversor de nível lógico nas linhas de sinal. O ESP32 e o Pico já trabalham em 3,3 V, então são diretamente compatíveis com esses dispositivos.

A biblioteca SPI do Arduino: funções básicas

FunçãoO que faz?
SPI.begin() (inicialização)Inicia o hardware SPI; configura os pinos SCK, MOSI e SS como saída.
SPISettings(velocidade, MSBFIRST, SPI_MODE0)Guarda a velocidade, a ordem dos bits e o modo de um dispositivo em um único objeto.
SPI.beginTransaction(configuracoes)Aplica as configurações e reserva o barramento para esse dispositivo; torna segura a troca entre dispositivos com configurações diferentes.
SPI.transfer(byte) (um byte)Envia um byte e retorna o byte recebido ao mesmo tempo.
SPI.transfer16(valor)Envia e recebe um valor de 16 bits de uma só vez.
SPI.transfer(buffer, comprimento)Envia um array; os bytes recebidos sobrescrevem o mesmo array.
SPI.endTransaction() (fim da transação)Libera o barramento; é chamada depois de colocar o CS em HIGH.

Primeiro exemplo: enviando dados a um 74HC595 por SPI

O jeito mais fácil de entender o SPI é com um registrador de deslocamento 74HC595, porque o 595 é, na verdade, o periférico SPI mais simples, sem MISO. O pino MOSI do Arduino vai na entrada DS do 595, o SCK no SH_CP e o D10 no ST_CP, que funciona como latch. Diferente da função shiftOut(), o SPI por hardware envia o byte em poucos microssegundos:

C++ (Arduino IDE)
1// Donanım SPI ile 74HC595: 8 LED'i iki kabloyla sürmek / 74HC595 over hardware SPI: 8 LEDs from two data wires
2// D11 (MOSI) -> DS (14), D13 (SCK) -> SH_CP (11), D10 -> ST_CP / latch (12)
3#include <SPI.h>
4
5const int LATCH_PIN = 10;     // 595'te CS gibi davranır / acts like CS on the 595
6
7void write595(byte value) {
8  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));  // 4 MHz, mod 0 / 4 MHz, mode 0
9  digitalWrite(LATCH_PIN, LOW);
10  SPI.transfer(value);                 // 8 biti gönder / shift out 8 bits
11  digitalWrite(LATCH_PIN, HIGH);       // yükselen kenarda çıkışlara aktar / latch on the rising edge
12  SPI.endTransaction();
13}
14
15void setup() {
16  pinMode(LATCH_PIN, OUTPUT);
17  digitalWrite(LATCH_PIN, HIGH);
18  SPI.begin();
19}
20
21void loop() {
22  for (int i = 0; i < 8; i++) {        // yürüyen ışık / running light
23    write595(1 << i);
24    delay(100);
25  }
26}

Lendo dados por SPI: o ADC MCP3008

Para ver a comunicação full duplex, vamos usar o MCP3008. Esse CI adiciona mais 8 entradas analógicas de 10 bits ao Arduino; é uma boa alternativa ao ADC não linear do ESP32 ou às apenas 3 entradas analógicas do Pico. Explicamos o básico da leitura analógica no post O que é ADC?. Ligação: CLK → D13, DOUT → D12, DIN → D11, CS → D10, VDD e VREF → 5V, AGND e DGND → GND.

C++ (Arduino IDE)
1// MCP3008 (8 kanal, 10 bit ADC) okuma / Reading an MCP3008 (8-channel 10-bit ADC)
2// D13 -> CLK, D12 <- DOUT, D11 -> DIN, D10 -> CS/SHDN
3#include <SPI.h>
4
5const int CS_PIN = 10;
6SPISettings mcpSettings(1000000, MSBFIRST, SPI_MODE0);   // 1 MHz, mod 0 / 1 MHz, mode 0
7
8int readMCP3008(byte channel) {
9  SPI.beginTransaction(mcpSettings);
10  digitalWrite(CS_PIN, LOW);                   // cihazı seç / select the chip
11  SPI.transfer(0x01);                          // başlangıç biti / start bit
12  byte high = SPI.transfer(0x80 | (channel << 4));   // tek uçlu + kanal / single-ended + channel
13  byte low = SPI.transfer(0x00);               // kalan 8 bit / remaining 8 bits
14  digitalWrite(CS_PIN, HIGH);                  // seçimi bırak / release the chip
15  SPI.endTransaction();
16  return ((high & 0x03) << 8) | low;           // 10 bitlik sonuç / 10-bit result
17}
18
19void setup() {
20  Serial.begin(9600);
21  pinMode(CS_PIN, OUTPUT);
22  digitalWrite(CS_PIN, HIGH);                  // başta seçili değil / not selected at start
23  SPI.begin();
24}
25
26void loop() {
27  int raw = readMCP3008(0);
28  float volts = raw * 5.0 / 1023.0;
29  Serial.print("CH0: ");
30  Serial.print(raw);
31  Serial.print("  ");
32  Serial.print(volts, 2);
33  Serial.println(" V");
34  delay(500);
35}

Aqui enviamos três bytes e recebemos três bytes ao mesmo tempo. O primeiro byte (0x01) é só o bit de início; o segundo byte leva o modo de medição simples (single-ended) e o número do canal, enquanto o MCP3008 devolve os 2 bits mais altos do resultado. O terceiro byte é 0x00; o conteúdo não importa, ele só é enviado para gerar pulsos de clock e receber os 8 bits restantes do resultado. No SPI, “ler” sempre significa enviar alguma coisa. O resultado fica entre 0 e 1023 e é convertido em volts em relação ao VREF (aqui, 5 V).

Vários dispositivos SPI: linhas CS separadas

A maior diferença entre o SPI e o I2C é que o SPI não usa endereços. Os dispositivos compartilham as linhas SCK, MOSI e MISO, e cada um recebe do Arduino seu próprio fio de CS. Só o dispositivo cujo CS está em LOW escuta, e só ele escreve dados na MISO. Três dispositivos precisam de 3 + 3 = 6 fios, cinco dispositivos de 3 + 5 = 8 fios; o número de pinos cresce com o número de dispositivos. Alguns CIs, como o 74HC595 e o MAX7219, podem ser ligados em cascata (daisy chain): a saída de um vai na entrada do próximo e todos são controlados com um único CS.

  • Só um CS deve estar em LOW por vez. Se dois dispositivos forem selecionados juntos, eles colidem na linha MISO e você lê dados corrompidos dos dois.
  • No setup(), primeiro configure todos os pinos CS como saída e coloque-os em HIGH, depois inicie as bibliotecas. Um pino CS flutuando pode parecer LOW aleatoriamente e ocupar o barramento.
  • Use beginTransaction para cada dispositivo. Um cartão SD pode querer 25 MHz e um MCP3008 1 MHz; as transações aplicam automaticamente a velocidade e o modo corretos a cada troca.
  • Se você usa SPI dentro de interrupções, avise a biblioteca com SPI.usingInterrupt() ou não faça operações SPI dentro da interrupção.
  • Colocar um pull-up de 10 kΩ na linha CS de cada dispositivo evita que os dispositivos se selecionem sozinhos enquanto o Arduino liga ou reinicia.

Cartão SD e RFID no mesmo barramento: por que não funciona?

Uma pergunta clássica nos fóruns de Arduino: o leitor RFID RC522 funciona sozinho, o módulo de cartão SD funciona sozinho, mas quando os dois estão no mesmo barramento SPI um deles ou ambos param de responder. Mesmo com os pinos CS corretos no software, o problema geralmente está no hardware. Muitos módulos de cartão SD baratos têm um CI buffer 74LVC125 que converte sinais de 5 V para 3,3 V, e o canal desse CI que aciona a linha MISO fica sempre habilitado. Ou seja, mesmo com o CS do cartão SD em HIGH, o módulo não solta a MISO; quando o RC522 tenta responder, a linha fica disputada por duas saídas.

  • Escolha o módulo certo: módulos que colocam a MISO em alta impedância quando o CS está em HIGH compartilham o barramento sem problemas. Para saber se um módulo libera a linha, com o CS em HIGH puxe a MISO por 10 kΩ primeiro para o GND e depois para 5 V e meça com um multímetro.
  • Ligue o pino de habilitação do buffer ao CS: se você tem prática com solda, desligar do GND o pino OE do canal MISO do 74LVC125 e ligá-lo à linha CS do módulo resolve o problema de vez.
  • Coloque um resistor em série na MISO: um resistor em série de cerca de 1 kΩ na saída MISO do módulo SD permite que o RC522 domine a linha. É um paliativo fácil, mas que limita a velocidade.
  • Use um barramento SPI separado: no ESP32, se você ligar o cartão SD no VSPI e o RC522 no HSPI, os dois dispositivos nunca se encontram. O Uno não tem um segundo SPI por hardware, então essa opção não existe nele.
  • Cuidado com a ordem de inicialização: primeiro coloque todos os CS em HIGH, depois chame SPI.begin() e, em seguida, SD.begin() e PCD_Init(). O exemplo abaixo segue essa ordem.
C++ (Arduino IDE)
1// Aynı SPI hattında SD kart ve RC522 RFID / SD card and RC522 RFID on the same SPI bus
2// Ortak / shared: D11 MOSI, D12 MISO, D13 SCK. CS: SD -> D4, RC522 SDA(SS) -> D10, RC522 RST -> D9
3#include <SPI.h>
4#include <SD.h>
5#include <MFRC522.h>
6
7const int SD_CS = 4;
8const int RFID_CS = 10;
9const int RFID_RST = 9;
10
11MFRC522 rfid(RFID_CS, RFID_RST);
12
13void setup() {
14  Serial.begin(9600);
15  // Önce TÜM CS pinlerini HIGH yap: hiçbir cihaz hattı meşgul etmesin
16  // First drive ALL CS pins HIGH so no device grabs the bus
17  pinMode(SD_CS, OUTPUT);
18  digitalWrite(SD_CS, HIGH);
19  pinMode(RFID_CS, OUTPUT);
20  digitalWrite(RFID_CS, HIGH);
21
22  SPI.begin();
23  if (!SD.begin(SD_CS)) {
24    Serial.println(F("SD bulunamadi / SD not found"));
25  }
26  rfid.PCD_Init();
27  Serial.println(F("Karti okut / Scan a card"));
28}
29
30void loop() {
31  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;
32
33  String uid = "";
34  for (byte i = 0; i < rfid.uid.size; i++) {
35    if (rfid.uid.uidByte[i] < 0x10) uid += "0";
36    uid += String(rfid.uid.uidByte[i], HEX);
37  }
38  rfid.PICC_HaltA();
39
40  File f = SD.open("kartlar.txt", FILE_WRITE);   // kütüphane CS'yi kendisi yönetir / the library handles CS itself
41  if (f) {
42    f.print(millis());
43    f.print(";");
44    f.println(uid);
45    f.close();
46    Serial.println("Kaydedildi / Saved: " + uid);
47  } else {
48    Serial.println(F("Dosya acilamadi / File open failed"));
49  }
50}

Neste código, a biblioteca SD e a biblioteca MFRC522 colocam seus próprios pinos CS em LOW e HIGH; você só precisa deixar os dois em HIGH no início e garantir que o hardware compartilhe a MISO corretamente. O código grava o UID de cada cartão lido, junto com a marcação de tempo, no arquivo kartlar.txt. No Uno, essas duas bibliotecas juntas usam cerca de metade da RAM; a macro F() libera espaço guardando os textos constantes na flash.

VSPI e HSPI no ESP32: dois barramentos SPI separados

O ESP32 tem quatro unidades SPI internas; o SPI0 e o SPI1 são reservados para a memória flash interna, o que deixa o VSPI (SPI3) e o HSPI (SPI2) para você. Usar os dois é a forma mais limpa de separar dispositivos com velocidades e modos muito diferentes ou de escapar do conflito na MISO descrito acima. No core do Arduino, você cria um objeto SPIClass para o segundo barramento e informa os pinos com begin(). O código abaixo roda o cartão SD no VSPI padrão e o MCP3008 no HSPI, e acrescenta uma leitura a um arquivo CSV a cada segundo:

C++ (Arduino IDE)
1// ESP32: iki ayrı SPI hattı / two separate SPI buses
2// VSPI (varsayılan SPI / default SPI): SD kart / SD card -> SCK 18, MISO 19, MOSI 23, CS 5
3// HSPI: MCP3008 -> SCK 14, MISO 12, MOSI 13, CS 15
4#include <SPI.h>
5#include <SD.h>
6
7const int SD_CS = 5;
8const int ADC_CS = 15;
9
10SPIClass hspi(HSPI);                              // ikinci donanım SPI / second hardware SPI
11SPISettings mcpSettings(1000000, MSBFIRST, SPI_MODE0);
12
13int readMCP3008(byte channel) {
14  hspi.beginTransaction(mcpSettings);
15  digitalWrite(ADC_CS, LOW);
16  hspi.transfer(0x01);
17  byte high = hspi.transfer(0x80 | (channel << 4));
18  byte low = hspi.transfer(0x00);
19  digitalWrite(ADC_CS, HIGH);
20  hspi.endTransaction();
21  return ((high & 0x03) << 8) | low;
22}
23
24void setup() {
25  Serial.begin(115200);
26  pinMode(ADC_CS, OUTPUT);
27  digitalWrite(ADC_CS, HIGH);
28  hspi.begin(14, 12, 13, ADC_CS);                 // SCK, MISO, MOSI, SS
29
30  if (!SD.begin(SD_CS)) {                         // SD varsayılan VSPI'yi kullanır / SD uses the default VSPI
31    Serial.println("SD bulunamadi / SD not found");
32  }
33}
34
35void loop() {
36  int raw = readMCP3008(0);
37  File f = SD.open("/olcum.csv", FILE_APPEND);    // ekle kipinde aç / open in append mode
38  if (f) {
39    f.printf("%lu,%d\n", millis(), raw);
40    f.close();
41  }
42  Serial.printf("CH0: %d\n", raw);
43  delay(1000);
44}
O GPIO 12, pino MISO do HSPI, é um dos pinos de boot (strapping) do ESP32: se estiver em HIGH na inicialização, a placa acha que a flash trabalha em 1,8 V e não liga. Não ligue no HSPI módulos com resistor de pull-up na MISO (como a maioria dos módulos de cartão SD) ou mude a MISO para outro pino. É por isso que, neste exemplo, o cartão SD fica no VSPI.

SPI com o Raspberry Pi Pico (MicroPython)

O Pico tem duas unidades SPI por hardware (SPI0 e SPI1), usadas no MicroPython pela classe machine.SPI. Os parâmetros polarity e phase correspondem a CPOL e CPHA; se os dois forem 0, é o Modo 0. Você controla o CS por conta própria, como um pino de saída comum. A função write_readinto() é a que melhor mostra a natureza full duplex do SPI: enquanto envia um array, grava os bytes recebidos em outro. Vamos ler o mesmo MCP3008, desta vez alimentado com 3,3 V:

MicroPython
1# Raspberry Pi Pico: SPI0 ile MCP3008 okuma / reading an MCP3008 on SPI0
2# GP18 -> CLK, GP19 -> DIN (MOSI), GP16 <- DOUT (MISO), GP17 -> CS. MCP3008 VDD ve VREF 3V3 / VDD and VREF on 3V3
3from machine import Pin, SPI
4import time
5
6spi = SPI(0, baudrate=1_000_000, polarity=0, phase=0,   # mod 0 / mode 0
7          sck=Pin(18), mosi=Pin(19), miso=Pin(16))
8cs = Pin(17, Pin.OUT, value=1)                          # başta seçili değil / not selected at start
9
10def read_mcp3008(channel):
11    tx = bytearray([0x01, 0x80 | (channel << 4), 0x00])
12    rx = bytearray(3)
13    cs.value(0)                                          # cihazı seç / select the chip
14    spi.write_readinto(tx, rx)                           # aynı anda gönder ve al / send and receive at once
15    cs.value(1)
16    return ((rx[1] & 0x03) << 8) | rx[2]
17
18while True:
19    raw = read_mcp3008(0)
20    print("CH0:", raw, "{:.2f} V".format(raw * 3.3 / 1023))
21    time.sleep(0.5)

SPI x I2C x UART

CaracterísticaSPII2CUART
Número de fios4 (+1 CS para cada dispositivo extra)2 (SDA, SCL)2 (TX, RX)
Velocidade típica1–80 MHz100 kHz, 400 kHz, 1 MHz9600–115200 baud (até alguns Mbit/s)
ClockSim (gerado pelo controlador)Sim (gerado pelo controlador)Não; os dois lados combinam a mesma baud rate
SentidoFull duplexHalf duplexFull duplex
Seleção do dispositivoFio de CS separadoEndereço de 7 bitsSó dois dispositivos (ponto a ponto)
Componentes extrasNão precisaResistores de pull-upNão precisa
DistânciaCurta (na placa, algumas dezenas de cm)Curta (cerca de 1 m)Alguns metros; muito mais com RS-485
Módulos típicosCartão SD, RC522, TFT, nRF24L01, MAX7219OLED, módulo I2C para LCD, RTC, BME280, MPU6050GPS, HC-05, SIM800L, ESP-01, computador

A escolha normalmente é feita pelo módulo, mas nos seus próprios projetos esta regra ajuda: se velocidade e volume de dados importam (imagens no display, arquivos, áudio), use SPI; se você precisa de poucos fios e muitos sensores lentos, use I2C; se quer uma ligação simples, baseada em texto, entre dois dispositivos, use UART. Você encontra o UART em detalhes no post comunicação serial UART. Usar os três no mesmo projeto também é muito comum: por exemplo, um datalogger que lê sensores por I2C, grava no cartão SD por SPI e recebe a posição de um GPS por UART.

Módulos que usam SPI e ideias de projetos

  • Fechadura com cartão e registro de acesso: leia o cartão com um RC522 e grave a data e o UID em um cartão SD.
  • Registrador de temperatura: grave os dados do sensor em um cartão microSD como CSV e faça o gráfico no Excel.
  • Painel de texto rolante: mostre a hora e mensagens em módulos de matriz de LED MAX7219 ligados em cascata.
  • Interface colorida: desenhe gráficos e menus em um display TFT ILI9341; ligue também o painel touch no mesmo barramento SPI.
  • Controle sem fio: envie comandos ao seu carrinho robô com dois módulos nRF24L01.
  • Medição multicanal: monte um controlador MIDI com 8 potenciômetros ou um sistema de irrigação com 8 sensores de umidade do solo usando um MCP3008.

Erros comuns e como resolver

SintomaCausa provávelSolução
Sempre lê 0xFF ou 0x00MISO desconectada, MOSI e MISO trocadas ou o dispositivo sem alimentaçãoLigue DIN na MOSI e DOUT na MISO; meça o VCC do dispositivo
Valores sem sentido ou deslocados em um bitModo SPI errado ou clock rápido demais para o dispositivoUse o modo indicado no datasheet, baixe a velocidade para 1 MHz e teste de novo
Dois dispositivos que funcionam sozinhos não funcionam juntosUm módulo não libera a MISO ou os pinos CS não estão em HIGH no inícioColoque todos os CS em HIGH primeiro; troque o módulo que não libera a MISO ou use um barramento SPI separado
O SPI para de repente no UnoO D10 foi usado como entrada e puxado para LOWDeixe o D10 como saída; você pode usá-lo como CS
O ESP32 não liga com o HSPI conectadoO GPIO 12 fica em HIGH na inicializaçãoLeve a MISO com pull-up para o VSPI ou escolha outro pino para a MISO
Erros aleatórios com fios longosReflexões e ruído em um sinal rápidoEncurte os fios, reduza a velocidade, passe um fio de GND junto dos sinais
Um analisador lógico barato de 8 canais é extremamente útil para ver o que está acontecendo no SPI: ele grava SCK, MOSI, MISO e CS ao mesmo tempo e decodifica qual byte saiu e qual voltou. Na hora em que você diz “o código está certo, mas não funciona”, ele mostra em segundos se o problema está na fiação ou na configuração.

O SPI é a linguagem comum dos módulos rápidos do mundo Arduino, dos cartões SD aos displays coloridos: depois que você aprende os quatro fios, a lógica do CS e os quatro modos, ligar um novo módulo SPI é questão de poucos minutos. No app BlueGrays você encontra os projetos de leitura de cartão RFID e fechadura, registrador de temperatura com microSD e relógio com matriz de pontos MAX7219, passo a passo, com esquemas do circuito e códigos.

Perguntas frequentes

O que significa SPI?

SPI é a sigla de Serial Peripheral Interface (interface serial de periféricos). Ela permite que um controlador troque dados de forma rápida e síncrona com periféricos por quatro linhas: SCK, MOSI, MISO e CS.

O que são MOSI e MISO?

MOSI (Master Out Slave In) é a linha de dados do controlador para o periférico; MISO (Master In Slave Out) é a linha de dados que volta do periférico para o controlador. Na nomenclatura nova, elas também aparecem como COPI e CIPO. Nos módulos, o DIN normalmente vai na MOSI e o DOUT na MISO.

Quais são os pinos SPI do Arduino Uno?

No Arduino Uno e no Nano, o SCK é o D13, a MISO é o D12, a MOSI é o D11 e o CS padrão é o D10. As mesmas linhas também estão na barra ICSP de 6 pinos da placa. No Arduino Mega, o SCK é o D52, a MISO o D50, a MOSI o D51 e o CS o D53.

Qual é a diferença entre SPI e I2C?

O SPI usa quatro fios, é full duplex e pode chegar a dezenas de MHz; cada dispositivo precisa do seu próprio fio de CS. O I2C usa só dois fios e seleciona os dispositivos por endereço, mas trabalha em velocidades bem menores, como 100–400 kHz, e precisa de resistores de pull-up.

Quantos dispositivos podem ser ligados em um barramento SPI?

Não há limite teórico; basta ter um pino CS livre no controlador para cada dispositivo. Na prática, surgem problemas em altas velocidades conforme a capacitância do barramento e o comprimento dos fios aumentam. Se faltarem pinos, você pode multiplicar as linhas CS com um decodificador 74HC138 ou usar dispositivos que podem ser ligados em cascata.

Por que um cartão SD e um leitor RFID não funcionam no mesmo barramento SPI?

O conversor de nível de muitos módulos de cartão SD baratos não libera a linha MISO mesmo com o CS em HIGH e corrompe a resposta do RC522. Usar um módulo que libere a MISO corretamente, ligar o pino de habilitação do CI buffer ao CS ou colocar os dois dispositivos em barramentos SPI separados no ESP32 resolve o problema.

Ver todos os projetos
Leitura de valores RFID
#53Iniciante
Premium

Leitura de valores RFID

O chaveiro de acesso do seu prédio ou seu cartão de entrada guarda um número de identificação oculto, e este projeto faz a leitura dele. Aproxime o cartão do leitor RFID e o Arduino escreve o número d

4.7(47)
61
Autenticação por RFID
#54Intermediário
Premium

Autenticação por RFID

Como na entrada com cartão de um prédio: você aproxima o cartão do leitor RFID e o Arduino compara o número dele com o número salvo. Com o cartão correto, o LED verde acende por três segundos; com um

4.8(64)
83
Leitor de cartões RFID RC522 com ESP32 e LCD
#123Intermediário

Leitor de cartões RFID RC522 com ESP32 e LCD

Neste projeto, vamos conectar o módulo RFID RC522, baseado no MFRC522, ao ESP32 via SPI e ler o UID do cartão ou da etiqueta. Isso serve de base para aplicações como fechaduras, sistemas de associados e controle de acesso. Vamos exibir o UID lido em um display LCD; nesta versão, ele não é comparado com uma lista de cartões autorizados. ATENÇÃO: o RC522 funciona apenas com 3,3V; alimentá-lo com 5V queima o módulo!

4.8(21)
39
Fechadura RFID com ESP32 (RC522 + servo + OLED + buzzer + LED)
#137Avançado
Premium

Fechadura RFID com ESP32 (RC522 + servo + OLED + buzzer + LED)

Vamos montar uma fechadura inteligente com ESP32, módulo RFID RC522, servo motor SG90, display OLED SSD1306, buzzer ativo e 2 LEDs. Ao ler um cartão, seu UID é comparado à lista de cartões autorizados definida no código. Se estiver autorizado, o servo motor gira para abrir a fechadura (LED verde + 2 bipes curtos), que trava novamente após 5 segundos. Com um cartão não autorizado, o LED vermelho acende, 3 bipes rápidos soam e o UID lido aparece no OLED.

4.8(9)
15
Registrador de temperatura com ESP32 (DHT22 + DS1307 RTC + microSD + OLED)
#144Avançado
Premium

Registrador de temperatura com ESP32 (DHT22 + DS1307 RTC + microSD + OLED)

Monte um registrador de temperatura com data e hora usando ESP32! Leia a temperatura e a umidade do DHT22 a cada minuto, obtenha a hora real do DS1307 RTC e grave os dados em CSV no cartão microSD. O OLED exibe a temperatura atual em letras grandes, a porcentagem de umidade, a data e a hora e o contador de registros. O arquivo /temp_log.csv no cartão SD pode ser aberto no Excel, Google Sheets ou pandas do Python para análise — ideal para monitorar estufas, acompanhar a temperatura de casa ou…

4.7(7)
12
Relógio e calendário de matriz de LEDs (MAX7219, DS1307)
#84Intermediário
Premium

Relógio e calendário de matriz de LEDs (MAX7219, DS1307)

Um painel luminoso para a mesa ou a parede que mostra a hora e a data em texto deslizante. O display de LEDs 8x32 exibe um relógio com dígitos grandes e dois pontos que piscam a cada segundo; no iníci

5.0(37)
59
Animação e texto em 4 matrizes LED 32x8
#90Intermediário
Premium

Animação e texto em 4 matrizes LED 32x8

Empilhe quatro módulos longos de matriz LED para formar um display quadrado com mais de mil pontos de luz. Primeiro, letras caem do alto como chuva, como nos filmes. Depois, uma cortina se abre e duas

4.6(40)
66
Cobrinha em pixels: matriz 8x8
#88Avançado
Premium

Cobrinha em pixels: matriz 8x8

Monte o clássico jogo da cobrinha com as próprias mãos e jogue. Em uma matriz de luzes coloridas 8x8, você guia uma cobra verde com um joystick e come maçãs vermelhas; a cada maçã, a cobra cresce, ace

4.7(39)
57