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:
Campo | Tipo | Descrição |
---|---|---|
sck | pin_t | O pino de clock |
mosi | pin_t | O pino de dados MOSI (ou NO_PIN para desabilitar o MOSI) |
miso | pin_t | O pino de dados MISO (ou NO_PIN para desabilitar o MISO) |
mode | uint32_t | Modo SPI: 0 , 1 , 2 ou 3 (padrão: 0 ) |
done | callback | Chamado quando uma transação SPI termina (veja abaixo) |
user_data | void \* | 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()
.
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.