Guia Completo: Protocolos I²C & SPI no PIC Microcontrolador

Índice🔗

Arquitetura e Fundamentos🔗

Protocolo I²C

Topologia e Física do Barramento

graph TD PIC[PIC Master] -->|SCL| Dispositivo1[BMP280 0x76] PIC -->|SDA| Dispositivo1 PIC -->|SCL| Dispositivo2[SHTC3 0x70] PIC -->|SDA| Dispositivo2

Parâmetros Elétricos:

  • Tensão de operação: 1.8V a 5.5V
  • Cálculo de pull-up:
$$ R_{pull-up} = \frac{t_r}{0.8473 \times C_{bus}} $$

Exemplo: Para t<sub>r = 300ns e Cbus = 200pF → R ≈ 1.8kΩ

Modos Avançados:

  • High-Speed (3.4 MHz)
  • Ultra Fast-mode (5 MHz)
  • Endereçamento 10-bit:
Byte 1: 11110XX X
Byte 2: XXXX XXXX

Protocolo SPI

Modos de Operação:

ModoCPOLCPHABorda de Amostragem
000Rising Edge
101Falling Edge
210Falling Edge
311Rising Edge

Técnicas de Conexão:

graph LR PIC -->|MOSI| Dispositivo1[FLASH] Dispositivo1 -->|MISO| PIC PIC -->|SCK| Dispositivo1 PIC -->|CS1| Dispositivo1 PIC -->|CS2| Dispositivo2[ADC]

Implementação em PIC🔗

Configuração I²C

Inicialização para PIC18F4550:

void I2C_Init_Extended() {
    SSPCON1 = 0x28;       // Modo I²C Master
    SSPCON2 = 0x00;
    SSPADD = ((_XTAL_FREQ/4)/100000) - 1;
    TRISC3 = 1;           // SCL como entrada
    TRISC4 = 1;           // SDA como entrada
    SSPSTAT = 0x80;       // Disable slew rate
}
uint8_t I2C_Read_10bit(uint16_t addr) {
    // Primeiro byte: 11110 A9 A8 W
    I2C_Write((0xF0 | ((addr >> 8) & 0x03)) << 1);
    // Segundo byte: A7-A0
    I2C_Write(addr & 0xFF);
    // Leitura dos dados...
    return I2C_Read(NACK);
}

Configuração SPI

Conexão Daisy-Chaining:

void SPI_Send_DaisyChain(uint32_t data1, uint32_t data2) {
    CS = 0;
    // Envia 32 bits para dois dispositivos concatenados
    SPI_Transfer((data1 >> 24) & 0xFF);
    SPI_Transfer((data1 >> 16) & 0xFF);
    SPI_Transfer((data1 >> 8) & 0xFF);
    SPI_Transfer(data1 & 0xFF);
    SPI_Transfer((data2 >> 24) & 0xFF);
    SPI_Transfer((data2 >> 16) & 0xFF);
    SPI_Transfer((data2 >> 8) & 0xFF);
    SPI_Transfer(data2 & 0xFF);
    CS = 1;
}

Casos Práticos🔗

Sistema Multi-Sensor

Diagrama de Conexões:

PIC18F46K22
├─ I²C
│  ├─ BMP280 (Pressão) @0x76
│  └─ SHTC3 (Umidade) @0x70
└─ SPI
   ├─ MAX7219 (LED) CS=RB1
   └─ W25Q64 (Flash) CS=RB2

Leitura Simultânea:

void Read_All_Sensors() {
    // I²C - Pressão
    uint8_t press_data[3];
    I2C_Read_Array(0x76, 0xF7, press_data, 3);
    // SPI - Flash
    CS_FLASH = 0;
    SPI_Transfer(0x03); // Comando READ
    SPI_Transfer(0x00); // Endereço 24-bit
    SPI_Transfer(0x00);
    SPI_Transfer(0x00);
    uint8_t flash_data = SPI_Transfer(0xFF);
    CS_FLASH = 1;
}

Análise Comparativa🔗

CaracterísticaI²CSPI
Velocidade Máxima5 MHz (Ultra Fast-mode)50 MHz (em PICs avançados)
Pinos Necessários2 (SDA/SCL)4 (MOSI/MISO/SCK/CS)
Consumo3 mA (ativo)15 mA (full-duplex)
Complexidade de CódigoAlta (gerenciamento de barramento)Média (controle direto)
Custo de ImplementaçãoR$ 2,50 (pull-ups)R$ 5,00 (CI decodificador)

Otimização e Troubleshooting🔗

Técnicas Avançadas

1. Buffer Circular para SPI:

#define BUFFER_SIZE 64
volatile uint8_t spi_buffer[BUFFER_SIZE];
volatile uint8_t buffer_index = 0;
void SPI_ISR() {
    spi_buffer[buffer_index++] = SSPBUF;
    if(buffer_index >= BUFFER_SIZE) buffer_index = 0;
}

2. Timeout Hardware para I²C:

T1CON = 0x30;       // Timer1 com prescaler 1:8
TMR1H = 0xFF;       // Timeout após 65535 ciclos
TMR1L = 0xFF;
T1CONbits.TMR1ON = 1;
while(!SSPSTATbits.BF && !TMR1IF);

Checklist de Depuração

1. Verificar níveis de tensão com multímetro

2. Testar comunicação em baixa velocidade (10 kHz para I²C)

3. Usar analisador lógico para capturar transações

Recursos Adicionais🔗

Autor: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.

Referências🔗

Compartilhar artigo