Raspberry Pi 5 IoT In C - SPI with GPIO 5 |
Written by Harry Fairhead | |||||
Sunday, 21 September 2025 | |||||
Page 2 of 4
The first function we need is something to initialize the SPI channel we are about to use: void spi_init(SPI spi, int32_t baudrate) { spi_set_baudrate(spi, baudrate); spi->BAUDR = SPIClock / baudrate; spi_enable(spi, false); // set CPOL and CHPA spi_set_format(spi, 8, SPI_CPOL_0, This is based on the Pico SDK function and it uses other functions to set the baud rate and format. It sets defaults of 8-bit data frames and mode 0. Notice that the SPI_MSB_FIRST is ignored in both the Pico and the Pi 5 and is included for compatibility. The Pi 5’s SPI implementation automatically controls the chip selects and it can either lower the select between each transmission or keep it asserted until the FIFO buffer is empty. The default is set to keep it asserted until the transfer is complete and a function to set this value is listed later. Each SPI controller has a different possible number of chip selects and which one is used depends on which bit is set in the SER register. The default is set to be CE0 but it is easy to change using a function given later. The function to set the baudrate is only complicated by the fact that the divisor has to be even: void spi_set_baudrate(SPI spi, int32_t baudrate) { int32_t div= SPIClock / baudrate; if(div%2!=0) div=div-1; spi_enable(spi, false); spi->BAUDR = div; spi_enable(spi, true); } The SPI clock is fixed at 200MHz and the register can only be changed when the SPI controller is not enabled. The set baud rate function can be used after the SPI controller has been initialized and a function to get the baud rate is useful for discovering what the clock speed actually is: int32_t spi_get_baudrate(SPI spi) { return SPIClock / (spi->BAUDR); } Most of the configuration is done by set_format and this can be called after the SPI channel has been initialized to change the defaults: void spi_set_format(SPI spi, uint32_t data_bits, Bits 16 to 20 set the number of databits used in a data frame and bits 6 and 7 control CPHA and CPOL. There are a number of utility functions that are simple enough to not need additional explanation: To enable or disable the SPI channel void spi_enable(SPI spi, bool enable) { if (enable) { spi->SSIENR = 0x1; }else{ spi->SSIENR = 0x0; } } Can you write to the SPI tx FIFO buffer bool spi_is_writable(SPI spi) { return (spi->SR) & 0x2; } This is the same as tx FIFO is not full. Is there data ready to be read in the Rx FIFO buffer. bool spi_is_readable(SPI spi) { return spi->SR & 0x8; } This is the same as Rx FIFO is not empty. Is the SPI channel busy bool spi_is_busy(SPI spi) { return spi->SR & 0x1; } Is the Rx FIFO full bool spi_rx_full(SPI spi) { return spi->SR & 0x10; } How many items in the Rx FIFO. int spi_rx_num(SPI spi) { return spi->RXFLR; } How many items in the Tx FIFO. int spi_tx_num(SPI spi) { return spi->TXFLR; } The status functions are needed to implement read/write functions and they are generally useful in user programs. |
|||||
Last Updated ( Wednesday, 24 September 2025 ) |