Ir para o conteúdo principal

API do dispositivo SPI

Para criar um dispositivo SPI, primeiro chame spi_init, passando uma estrutura spi_config_t. Essa estrutura define o relógio e os pinos MOSI/MISO, o modo SPI e o callback done.

spi_dev_t spi_init(spi_config_t *config)

Inicializa uma interface de dispositivo SPI. O argumento config define os pinos, modo e callbacks para o dispositivo SPI. Contém os seguintes campos:

CampoTipoDescrição
sckpin_tO pino de clock
mosipin_tO pino de dados MOSI (ou NO_PIN para desabilitar o MOSI)
misopin_tO pino de dados MISO (ou NO_PIN para desabilitar o MISO)
modeuint32_tModo SPI: 0, 1, 2 ou 3 (padrão: 0)
donecallbackChamado quando uma transação SPI termina (veja abaixo)
user_datavoid \*Dados que serão passados no primeiro argumento do callback done

A API não suporta um pino CS/SS: cabe ao usuário selecionar/desmarcar a interface SPI chamando spi_start() e spi_stop().

AVISO

Nota: spi_init só pode ser chamado de chip_init(). Não ligue mais tarde.

Exemplo:

const spi_config_t spi1 {
.sck = pin_init("SCK", INPUT),
.mosi = pin_init("MOSI", INPUT),
.miso = pin_init("MISO", INPUT),
.mode = 0,
.write_done = chip_spi_done, // Veja o exemplo abaixo
.user_data = chip,
};

void spi_start(spi_dev_t spi, uint8_t *buffer, uint32_t count)

Inicia uma transação SPI, enviando e recebendo bytes count de/para o buffer fornecido.

Normalmente, você escutará o pino CS (seleção de chip) com pin_watch. Chame spi_start() quando o pino CS for baixo, e spi_stop() quando o pino CS for alto.

Ao criar um dispositivo que transfere grandes quantidades de dados (por exemplo, uma tela LCD), é recomendável usar um tamanho de buffer grande (alguns kilobytes). O simulador pode usar o buffer maior para otimizar a transferência SPI controlada por DMA e acelerar a simulação.

Para dispositivos simples que transferem pequenas quantidades de dados, você pode usar um buffer de byte único e processar cada byte à medida que chega no callback done.

void spi_stop(spi_dev_t spi)

Pára a interface SPI. Normalmente, você chamaria esse método quando o pino CS fosse alto.

O callback done

A assinatura para o callback done é a seguinte:

static void chip_spi_done(void *user_data, uint8_t *buffer, uint32_t count) {
// 1. processa os dados recebidos (opcional)
// 2. se o pino CS ainda estiver baixo, agende a próxima transação SPI usando `spi_start`
}

O retorno de chamada done é executado quando uma transação SPI termina: quando o buffer fornecido para spi_start está cheio ou quando spi_stop foi chamado. O buffer contém os dados recebidos (é o mesmo buffer dado para spi_start), e count é o número de bytes que foram transferidos (ou 0 se spi_stop foi chamado antes de um byte completo ter sido foi transferido).

Seu retorno de chamada done deve verificar o status do pino CS e, se ainda estiver baixo, deve chamar spi_start() novamente para receber o próximo bloco de dados do microcontrolador.

Exemplos no simulator