11. SPI Structures and Registers

1. SPI Registers

SPI_register_map

typedef struct
{
    __vo uint32_t CR1;
    __vo uint32_t CR2;
    __vo uint32_t SR;
    __vo uint32_t DR;
    __vo uint32_t CRCPR;
    __vo uint32_t RXCRCR;
    __vo uint32_t TXCRCR;
    __vo uint32_t I2SCFGR;
    __vo uint32_t I2SPR;
} SPI_RegDef_t;
  1. CR1 (Control Register 1):

    • This register contains most of the bits needed to configure the SPI's basic parameters, such as baud rate, master/slave selection, clock polarity (CPOL), clock phase (CPHA), data frame format (8-bit or 16-bit), and software slave management.
  2. CR2 (Control Register 2):

    • This register includes controls for interrupt and DMA management, along with additional features like SS output enable, and it often contains bits that control the NSS pin behavior and the Tx buffer empty interrupt enable, etc.
  3. SR (Status Register):

    • The status register provides flags indicating the SPI status, such as whether the transmit buffer is empty (TXE), the receive buffer is not empty (RXNE), whether a transmission is ongoing, and if any errors like overrun or CRC error have occurred.
  4. DR (Data Register):

    • The data register is used for data transmission and reception. When you write to the DR, you're placing data in the transmit buffer to be sent over SPI. When you read from the DR, you're reading data that has been received via SPI.
  5. CRCPR (CRC Polynomial Register):

    • This register is used to define the polynomial used for the CRC (Cyclic Redundancy Check) calculation. The CRC is used for error detection.
  6. RXCRCR (RX CRC Register):

    • This register contains the CRC value calculated from the received data.
  7. TXCRCR (TX CRC Register):

    • This register holds the CRC value calculated from the transmitted data.
  8. I2SCFGR (I2S Configuration Register):

    • This register is used to configure the I2S (Inter-IC Sound) mode of the SPI peripheral. The STM32 SPI can be used for both standard SPI communication or I2S for audio data transfer, and this register includes settings specific to I2S operation.
  9. I2SPR (I2S Prescaler Register):

    • In I2S mode, this register is used to set the prescaler value for the I2S clock. It's used to derive the correct audio sample rate from the peripheral clock.
// Define the base addresses
#define SPI2_BASEADDR (APB1PERIPH_BASEADDR + 0x3800)
#define SPI3_BASEADDR (APB1PERIPH_BASEADDR + 0x3C00)
#define SPI1_BASEADDR (APB2PERIPH_BASEADDR + 0x3000)

// Define the peripheral register definition structure
#define SPI1 ((SPI_RegDef_t *)SPI1_BASEADDR)
#define SPI2 ((SPI_RegDef_t *)SPI2_BASEADDR)
#define SPI3 ((SPI_RegDef_t *)SPI3_BASEADDR)

// Define the peripheral clock enable/disable macros
#define SPI1_PCLK_EN() (RCC->APB2ENR |= (1 << 12))
#define SPI2_PCLK_EN() (RCC->APB1ENR |= (1 << 14))
#define SPI3_PCLK_EN() (RCC->APB1ENR |= (1 << 15))
#define SPI4_PCLK_EN() (RCC->APB2ENR |= (1 << 13))

// Define the peripheral clock disable macros
#define SPI1_PCLK_DI() (RCC->APB2ENR &= ~(1 << 12))
#define SPI2_PCLK_DI() (RCC->APB1ENR &= ~(1 << 14))
#define SPI3_PCLK_DI() (RCC->APB1ENR &= ~(1 << 15))
#define SPI4_PCLK_DI() (RCC->APB2ENR &= ~(1 << 13))

2. SPI Structures

SPI_Config_t Structure

typedef struct
{
    uint8_t SPI_DeviceMode;
    uint8_t SPI_BusConfig;
    uint8_t SPI_SclkSpeed;
    uint8_t SPI_DFF;
    uint8_t SPI_CPOL;
    uint8_t SPI_CPHA;
    uint8_t SPI_SSM;
} SPI_Config_t;

This structure is intended to hold the configuration settings for an SPI peripheral.

  • SPI_DeviceMode: Specifies whether the SPI peripheral is configured as a master or a slave.
  • SPI_BusConfig: Defines the bus configuration, which could be full-duplex, half-duplex, or simplex communication.
  • SPI_SclkSpeed: Sets the speed of the SPI clock. This is usually a division factor of the MCU's peripheral clock.
  • SPI_DFF: Stands for Data Frame Format. This determines the format of the data (8-bit or 16-bit) that is to be used for the SPI communication.
  • SPI_CPOL: Clock Polarity. This can be set based on whether the clock idles at a high (1) or low (0) level.
  • SPI_CPHA: Clock Phase. This determines if the data should be sampled on the first edge or the second edge of the clock signal.
  • SPI_SSM: Slave Select Management. This indicates whether the hardware slave management is enabled or disabled. When disabled, software has to manage the slave selection signal.

SPI_Handle_t Structure

typedef struct
{
    SPI_RegDef_t *pSPIx;
    SPI_Config_t SPIConfig;
    uint8_t *pTxBuffer;
    uint8_t *pRxBuffer; /* !< To store the app. Rx buffer address > */
    uint32_t TxLen;     /* !< To store Tx len > */
    uint32_t RxLen;     /* !< To store Tx len > */
    uint8_t TxState;    /* !< To store Tx state > */
    uint8_t RxState;    /* !< To store Rx state > */
} SPI_Handle_t;

This structure is a handle for the SPI peripheral that includes pointers to the SPI registers, a configuration structure, and state and buffer information for SPI transactions.

  • pSPIx: A pointer to an instance of the SPI registers. SPI_RegDef_t would typically be a structure that contains all the register definitions for an SPI peripheral.
  • SPIConfig: An instance of SPI_Config_t that holds the configuration settings for this particular SPI peripheral.
  • pTxBuffer: A pointer to the application's transmission buffer where the data to be sent is stored.
  • pRxBuffer: A pointer to the application's reception buffer where the data to be received will be stored.
  • TxLen: The length of the data to be transmitted. It's used to keep track of the number of bytes that are yet to be sent.
  • RxLen: The length of the data to be received. Similar to TxLen, it's used to keep track of the number of bytes expected to be received.
  • TxState: This could be an indicator of the current transmission state, which can be used to determine if the SPI is busy in transmission.
  • RxState: This is analogous to TxState, but for the reception process. It indicates if the SPI is busy receiving data.