LoopBack
This sample demonstrates communication between an SPI master and slave device using an interrupt method.
During the communication process, the master and slave devices exchange data to communicate, and data reception is handled via interrupts.
When the data received by the master or slave device reaches a set threshold, an SPI_INT_RXF
interrupt is triggered for data reception.
In this sample, SPI1 is configured as the master device, and SPI0 is configured as the slave device.
Requirements
For requirements, please refer to the Requirements.
Wiring
On the EVB, connect P2_4(Master SCK) to P3_0(Slave SCK), P2_5(Master MOSI) to P3_1(Slave MOSI), P2_6(Master MISO) to P3_2(Slave MISO), and P2_7(Master CS) to P3_3(Slave CS).
Configurations
The following macro can be configured to modify the pin definitions.
/* SPI1 MASTER pin define*/ #define SPI_MASTER_SCK_PIN P2_4 #define SPI_MASTER_MOSI_PIN P2_5 #define SPI_MASTER_MISO_PIN P2_6 #define SPI_MASTER_CS_PIN P2_7 /* SPI0 SLAVE pin define*/ #define SPI_SLAVE_SCK_PIN P3_0 #define SPI_SLAVE_MOSI_PIN P3_1 #define SPI_SLAVE_MISO_PIN P3_2 #define SPI_SLAVE_CS_PIN P3_3
Building and Downloading
For building and downloading, please refer to the Building and Downloading.
Experimental Verification
When the EVB starts, observe the following log within the Debug Analyzer.
Start spi loopback test!
The master device sends data {0, 1, …, 0x14} to the slave device. The Slave receives the data from the Master, enters the interrupt, prints the length of the data received by the Slave, and prints the data received by the Slave and the data sent by the Master.
SPI SLAVE receieves 20 data. slave_rx_buf[0] = 0x00000001, master_tx_buf[0] = 0x00000001 slave_rx_buf[1] = 0x00000002, master_tx_buf[1] = 0x00000002 ... slave_rx_buf[19] = 0x00000014, master_tx_buf[19] = 0x00000014
The slave device sends data {0x10, 0x11, …, 0x23} to the master device. The Master receives the information sent by the Slave, enters an interrupt, prints the length of the data received by the Master, and prints the data received by the Master and the data sent by the Slave.
SPI MASTER receieves 20 data master_rx_buf[0] = 0x00000010, slave_tx_buf[0] = 0x00000010 master_rx_buf[1] = 0x00000011, slave_tx_buf[1] = 0x00000011 ... master_rx_buf[19] = 0x00000023, slave_tx_buf[19] = 0x00000023
Code Overview
This section introduces the code and process description for initialization and corresponding function implementation in the sample.
Source Code Directory
The directory for project file and source code are as follows:
Project directory:
sdk\samples\peripheral\spi\loopback\proj
Source code directory:
sdk\samples\peripheral\spi\loopback\src
Initialization
The initialization flow for peripherals can refer to Initialization Flow in General Introduction.
Call
Pad_Config()
andPinmux_Config()
to configure the PAD and PINMUX of the corresponding pins. Set the PINMUX of SPI1-related pins to the master device function, and set the PINMUX of SPI0-related pins to the slave device function.void board_spi_master_init(void) { Pad_Config(SPI_MASTER_SCK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_MASTER_MOSI_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_MASTER_MISO_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_MASTER_CS_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pinmux_Deinit(SPI_MASTER_SCK_PIN); Pinmux_Deinit(SPI_MASTER_MOSI_PIN); Pinmux_Deinit(SPI_MASTER_MISO_PIN); Pinmux_Deinit(SPI_MASTER_CS_PIN); Pinmux_Config(SPI_MASTER_SCK_PIN, SPI1_CLK_MASTER); Pinmux_Config(SPI_MASTER_MOSI_PIN, SPI1_MO_MASTER); Pinmux_Config(SPI_MASTER_MISO_PIN, SPI1_MI_MASTER); Pinmux_Config(SPI_MASTER_CS_PIN, SPI1_CSN_0_MASTER); } void board_spi_slave_init(void) { Pad_Config(SPI_SLAVE_SCK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_SLAVE_MOSI_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_SLAVE_MISO_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_SLAVE_CS_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); /* Must deinit P4_0~P4_3 before use SPI SLAVE!!! */ Pinmux_Deinit(P4_0); Pinmux_Deinit(P4_1); Pinmux_Deinit(P4_2); Pinmux_Deinit(P4_3); Pinmux_Deinit(SPI_SLAVE_SCK_PIN); Pinmux_Deinit(SPI_SLAVE_MOSI_PIN); Pinmux_Deinit(SPI_SLAVE_MISO_PIN); Pinmux_Deinit(SPI_SLAVE_CS_PIN); Pinmux_Config(SPI_SLAVE_SCK_PIN, SPI0_CLK_SLAVE); Pinmux_Config(SPI_SLAVE_MOSI_PIN, SPI0_SI_SLAVE); Pinmux_Config(SPI_SLAVE_MISO_PIN, SPI0_SO_SLAVE); Pinmux_Config(SPI_SLAVE_CS_PIN, SPI0_CSN_0_SLAVE); }
Call
RCC_PeriphClockCmd()
to enable the SPI clock.Initialize the SPI peripheral:
Define the
SPI_InitTypeDef
typeSPI_InitStruct
, and callSPI_StructInit()
to pre-fillSPI_InitStruct
with default values.Modify the
SPI_InitStruct
parameters as needed. The SPI0 and SPI1 initialization parameter configuration is shown in the table below.Call
SPI_Init()
to initialize the SPI peripheral.
SPI Hardware Parameters |
Setting in the |
SPI1 |
SPI0_SLAVE |
---|---|---|---|
SPI Transfer Mode |
|||
SPI Data Size |
|||
Clock Mode - CPOL |
|||
Clock Mode - CPHA |
|||
Clock Prescaler |
100 |
100 |
|
Frame Format |
|||
RX Threshold |
|
|
Call
SPI_Cmd()
to enable SPI peripheral.
Functional Implementation
Before the master device calls
SPI_SendBuffer()
to send data, the slave device must first callSPI_SendBuffer()
to preload data into the FIFO. Once the master device starts sending data back, it initiates the clock signal, and the slave device follows by transmitting the data.The master device receives data sent by the slave device, and upon reaching the threshold, it triggers the
SPI_INT_RXF
interrupt. Similarly, the slave device triggers the interrupt upon receiving data. Within the interrupt function, callSPI_GetRxFIFOLen()
andSPI_ReceiveData()
to receive the data.void SPI_Handler_MASTER(void) { if (SPI_GetINTStatus(SPI_MASTER, SPI_INT_RXF)) { SPI_INTConfig(SPI_MASTER, SPI_INT_RXF, DISABLE); SPI_ClearINTPendingBit(SPI_MASTER, SPI_INT_RXF); uint32_t master_rx_len = SPI_GetRxFIFOLen(SPI_MASTER); ... SPI_INTConfig(SPI_MASTER, SPI_INT_RXF, ENABLE); } } void SPI_Handler_SLAVE(void) { if (SPI_GetINTStatus(SPI_SLAVE, SPI_INT_RXF)) { SPI_INTConfig(SPI_SLAVE, SPI_INT_RXF, DISABLE); SPI_ClearINTPendingBit(SPI_SLAVE, SPI_INT_RXF); uint32_t slave_rx_len = SPI_GetRxFIFOLen(SPI_SLAVE); ... SPI_INTConfig(SPI_SLAVE, SPI_INT_RXF, ENABLE); } }