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.
| Linha | Nome antigo | Nome novo | Sentido | Função |
|---|---|---|---|---|
| SCK / SCLK | Serial Clock | SCK | Controlador → periférico | Sinal de clock; um bit é transferido a cada pulso |
| MOSI | Master Out Slave In | COPI / SDO | Controlador → periférico | Dados do Arduino para o módulo |
| MISO | Master In Slave Out | CIPO / SDI | Periférico → controlador | Dados que voltam do módulo para o Arduino |
| CS / SS | Slave Select | CS (Chip Select) | Controlador → periférico | O 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.
- 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.
- O controlador começa a gerar pulsos de clock na SCK.
- 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).
- 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.
| Modo | CPOL | CPHA | Clock em repouso | Borda em que os dados são lidos | Dispositivos de exemplo |
|---|---|---|---|---|---|
| SPI_MODE0 | 0 | 0 | LOW | Subida | Cartão SD, RC522, nRF24L01, MAX7219, MCP3008, 74HC595 |
| SPI_MODE1 | 0 | 1 | LOW | Descida | Alguns CIs de ADC e de driver |
| SPI_MODE2 | 1 | 0 | HIGH | Descida | Raramente usado |
| SPI_MODE3 | 1 | 1 | HIGH | Subida | Acelerômetro ADXL345, alguns displays ST7789 sem pino CS |
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.
| Dispositivo | Função | Clock SPI máximo (datasheet) | Modo SPI |
|---|---|---|---|
| Cartão microSD | Registro de dados | 400 kHz na inicialização, depois até 25 MHz | Modo 0 |
| RC522 (MFRC522) | Leitor RFID | 10 MHz | Modo 0 |
| nRF24L01 | Comunicação sem fio de 2,4 GHz | 10 MHz | Modo 0 |
| MAX7219 | Matriz de LED / 7 segmentos | 10 MHz | Modo 0 |
| MCP3008 | ADC de 8 canais e 10 bits | 3,6 MHz em 5 V, 1,35 MHz em 2,7 V | Modo 0 ou 3 |
| ILI9341 | TFT colorido de 2,4–3,2 polegadas | 10 MHz na escrita (na prática é usado bem mais rápido) | Modo 0 |
Pinos SPI: Arduino Uno, Mega, ESP32 e Raspberry Pi Pico
| Linha | Arduino Uno / Nano | Arduino Mega | ESP32 VSPI (padrão) | ESP32 HSPI | Raspberry Pi Pico SPI0 |
|---|---|---|---|---|---|
| SCK | D13 | D52 | GPIO 18 | GPIO 14 | GP18 |
| MOSI | D11 | D51 | GPIO 23 | GPIO 13 | GP19 (TX) |
| MISO | D12 | D50 | GPIO 19 | GPIO 12 | GP16 (RX) |
| CS (padrão) | D10 | D53 | GPIO 5 | GPIO 15 | GP17 |
| Nível lógico | 5 V | 5 V | 3,3 V | 3,3 V | 3,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.
A biblioteca SPI do Arduino: funções básicas
| Função | O 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:
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.
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.
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:
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}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:
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ística | SPI | I2C | UART |
|---|---|---|---|
| Número de fios | 4 (+1 CS para cada dispositivo extra) | 2 (SDA, SCL) | 2 (TX, RX) |
| Velocidade típica | 1–80 MHz | 100 kHz, 400 kHz, 1 MHz | 9600–115200 baud (até alguns Mbit/s) |
| Clock | Sim (gerado pelo controlador) | Sim (gerado pelo controlador) | Não; os dois lados combinam a mesma baud rate |
| Sentido | Full duplex | Half duplex | Full duplex |
| Seleção do dispositivo | Fio de CS separado | Endereço de 7 bits | Só dois dispositivos (ponto a ponto) |
| Componentes extras | Não precisa | Resistores de pull-up | Não precisa |
| Distância | Curta (na placa, algumas dezenas de cm) | Curta (cerca de 1 m) | Alguns metros; muito mais com RS-485 |
| Módulos típicos | Cartão SD, RC522, TFT, nRF24L01, MAX7219 | OLED, módulo I2C para LCD, RTC, BME280, MPU6050 | GPS, 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
| Sintoma | Causa provável | Solução |
|---|---|---|
| Sempre lê 0xFF ou 0x00 | MISO desconectada, MOSI e MISO trocadas ou o dispositivo sem alimentação | Ligue DIN na MOSI e DOUT na MISO; meça o VCC do dispositivo |
| Valores sem sentido ou deslocados em um bit | Modo SPI errado ou clock rápido demais para o dispositivo | Use o modo indicado no datasheet, baixe a velocidade para 1 MHz e teste de novo |
| Dois dispositivos que funcionam sozinhos não funcionam juntos | Um módulo não libera a MISO ou os pinos CS não estão em HIGH no início | Coloque 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 Uno | O D10 foi usado como entrada e puxado para LOW | Deixe o D10 como saída; você pode usá-lo como CS |
| O ESP32 não liga com o HSPI conectado | O GPIO 12 fica em HIGH na inicialização | Leve a MISO com pull-up para o VSPI ou escolha outro pino para a MISO |
| Erros aleatórios com fios longos | Reflexões e ruído em um sinal rápido | Encurte os fios, reduza a velocidade, passe um fio de GND junto dos sinais |
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.
Projetos para montar depois desta leitura
Ver todos os projetos
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

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

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!

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.

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…

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

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

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
Mais artigos
- O que é I2C? SDA, SCL, resistores de pull-up e um scanner com Arduino
- Módulo de cartão SD no Arduino: datalogger em CSV com data e hora do RTC
- Como usar o RFID RC522: lendo cartões com Arduino e uma fechadura acionada por cartão
- O que é UART? Guia de ligação TX/RX, baud rate e comunicação serial com Arduino
App BlueGrays
Monte este circuito passo a passo pelo celular
Esquema do circuito, código e lista de componentes em uma só tela. Mais de 200 projetos com Arduino, ESP32 e Pico prontos para montar.
Escaneie com seu celular
Aponte a câmera para o código para abrir a loja de aplicativos do seu celular.
ou abrir a loja

