SPI Master RGB Write
This document introduces three SPI communication samples. The samples demonstrate how SPI uses one data line to control an LED in three different modes: polling (sample1), interrupt (sample2), and DMA (sample3). In all three examples, the SPI is configured as a master, the clock is set to 10MHz, the direction is full-duplex, and the data frame size is 12 bits. The chip writes RGB data to the SPI slave to light up the LED.
Requirements
For hardware requirements, please refer to the Requirements.
Wiring
Connect P1_0 (SPI master MOSI) to the LED controller.
Configurations
The following macros can be configured to modify pin definitions.
#define PIN_SPI_MOSI P1_0
The entry function are as follows, call this function in
main()
to run this sample code. For more details, please refer to the Initialization.For sample 1, use the following entry function:
spi_rgb_polling_demo();
For sample 2, use the following entry function:
spi_rgb_interrupt_demo();
For sample 3, use the following entry function:
spi_rgb_dma_demo();
Building and Downloading
For building and downloading, please refer to the Building and Downloading.
Experimental Verification
Sample 1 Verification
Press the Reset button on the EVB, convert
rgb_data
intoSPI_WriteBuf
in preparation for sending.Send
SPI_WriteBuf
with a data length of 91 to LED controller.
Sample 2 Verification
Press the Reset button on the EVB, convert
rgb_data
intoSPI_WriteBuf
in preparation for sending.Send
SPI_WriteBuf
with a data length of 24 to LED controller. When the data length in TX FIFO is equal to or below its threshold value, trigger theSPI_INT_TXE
interrupt and prints log.spi_tx_handler: SPI TX FIFO Empty
Sample 3 Verification
Press the Reset button on the EVB, convert
rgb_data
intoSPI_WriteBuf
in preparation for sending.Send
SPI_WriteBuf
with a data length of 24 to LED controller. When completing the transmission, it enters the GDMA interrupt and prints log.spi_tx_dma_handler
Code Overview
Source Code Directory
For all three samples, please refer to the Source Code Directory for the project directory.
Sample 1 source code:
Source code directory:
sdk\src\sample\io_demo\spi\polling\spi_rgb_polling_demo.c
.
Sample 2 source code:
Source code directory:
sdk\src\sample\io_demo\spi\interrupt\spi_rgb_interrupt_demo.c
.
Sample 3 source code:
Source code directory:
sdk\src\sample\io_demo\gdma\spi_dma\spi_rgb_dma_demo.c
.
RGB Polling Initialization Flow
The initialization flow for peripherals can refer to Initialization Flow.
The SPI initialization flow can refer to SPI Initialization Flow Chart.
Call
Pad_Config()
andPinmux_Config()
to initialize the SPI MOSI pin.static void board_spi_init(void) { Pinmux_Config(PIN_SPI1_MOSI, SPI1_MO_MASTER); Pad_Config(PIN_SPI1_MOSI, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH); }
Call
RCC_PeriphClockCmd()
to enable the SPI clock and function.Initialize the SPI peripheral:
Define the
SPI_InitTypeDef
typeSPI_InitStructure
, and callSPI_StructInit()
to pre-fillSPI_InitStructure
with default values.Modify the
SPI_InitStructure
parameters as needed. The SPI initialization parameter configuration is shown in the table below.Call
SPI_Init()
to initialize the SPI peripheral.
SPI Initialization Parameters SPI Hardware Parameters
Setting in the
SPI_InitStructure
SPI
Direction
Device Role (SPI Master or SPI Slave)
Data Frame Size
Clock Polarity
Clock Phase
Clock Div
4
Frame Format
Call
SPI_Cmd()
to enable SPI.
RGB Interrupt Initialization Flow
The initialization flow for peripherals can refer to Initialization Flow.
The SPI initialization flow can refer to SPI Initialization Flow Chart.
Call
Pad_Config()
andPinmux_Config()
to initialize the pins.static void board_spi_init(void) { Pinmux_Config(PIN_SPI1_MOSI, SPI1_MO_MASTER); Pad_Config(PIN_SPI1_MOSI, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_HIGH); }
Call
RCC_PeriphClockCmd()
to enable the SPI clock and function.Initialize the SPI peripheral:
Define the
SPI_InitTypeDef
typeSPI_InitStructure
, and callSPI_StructInit()
to pre-fillSPI_InitStructure
with default values.Modify the
SPI_InitStructure
parameters as needed. The SPI initialization parameter configuration is shown in the table below.Call
SPI_Init()
to initialize the SPI peripheral.
SPI Initialization Parameters SPI Hardware Parameters
Setting in the
SPI_InitStructure
SPI
Direction
Device Role (SPI Master or SPI Slave)
Data Frame Size
Clock Polarity
Clock Phase
Clock Div
4
Frame Format
Transmit FIFO Threshold Level
0
Call
NVIC_Init()
to enable NVIC of SPI.Call
SPI_Cmd()
to enable SPI.
RGB DMA Initialization Flow
The SPI RGB DMA initialization flow requires first initializing the SPI peripheral, followed by TX DMA initialization. The SPI initialization flow can refer to SPI Initialization Flow Chart. The SPI TX DMA initialization flow can refer to SPI TX DMA Initialization Flow Chart.
Call
RCC_PeriphClockCmd()
to enable the GDMA clock and function.Call
GDMA_channel_request
to request a free GDMA channel and register the GDMA interrupt handler.Initialize the GDMA peripheral:
Define the
GDMA_InitTypeDef
typeGDMA_InitStruct
, and callGDMA_StructInit()
to pre-fillGDMA_InitStruct
with default values.Modify the
GDMA_InitStruct
parameters as needed. The GDMA initialization parameter configuration is shown in the table below.Call
GDMA_Init()
to initialize the GDMA peripheral.
GDMA Initialization Parameters GDMA Hardware Parameters
Setting in the
GDMA_InitStruct
GDMA
Channel Num
SPI_DMA_CHANNEL_NUM
Transfer Direction
Buffer Size
RGB_DATA_LEN
Source Address Increment or Decrement
Destination Address Increment or Decrement
Source Data Size
Destination Data Size
Source Burst Transaction Length
Destination Burst Transaction Length
Source Address
SPI_WriteBuf
Destination Address
SPI1->DR
Destination Handshake
GDMA_Handshake_SPI1_TX
Call
GDMA_INTConfig()
to enable GDMA transfer complete interruptGDMA_INT_Transfer
.Call
NVIC_Init()
to enable NVIC of GDMA.
Functional Implementation
Master Send RGB Data by Polling
Call
SPI_SendHalfWord()
to send the 12 bits data inSPI_WriteBuf
to the slave.Call
SPI_GetFlagState()
to checkSPI_FLAG_BUSY
flag state, and wait for the SPI data transfer to complete.
static void led_control_rgb_to_spi_buffer(uint32_t data)
{
for (uint32_t i = 0; i < RGB_DATA_LEN; i++)
{
if (data & BIT(RGB_DATA_LEN - i - 1)) //1bit
{
SPI_WriteBuf[i] = 0xFF8;
}
else
{
SPI_WriteBuf[i] = 0xE00;
}
}
}
uint32_t rgb_data = 0xa5a5a5; //24bits RGB sample
led_control_rgb_to_spi_buffer(rgb_data);
SPI_SendHalfWord(SPI1, SPI_WriteBuf, DATA_LEN);
while (SPI_GetFlagState(SPI1, SPI_FLAG_BUSY));
Master Send RGB Data by Interrupt
Call
SPI_SendHalfWord()
to send the 12 bits data inSPI_WriteBuf
to the slave.Call
SPI_INTConfig()
to enable TX FIFO empty interruptSPI_INT_TXE
.When the transmit buffer reaches or goes below the TX FIFO threshold level (
SPI_InitTypeDef::SPI_TxThresholdLevel
), TX FIFO empty interrupt will be triggered and enters the interrupt handler:Call
SPI_GetINTStatus()
to checkSPI_INT_TXE
interrupt status.Call
SPI_INTConfig()
to disableSPI_INT_TXE
.
static void spi_tx_handler(void)
{
if (SPI_GetINTStatus(SPI_MASTER, SPI_INT_TXE) == SET)
{
SPI_INTConfig(SPI_MASTER, SPI_INT_TXE, DISABLE);
IO_PRINT_INFO0("spi_tx_handler: SPI TX FIFO Empty");
}
}
Master Send RGB Data by DMA
Call
SPI_GDMACmd()
to disable and then enable SPI GDMA RX Function.Call
GDMA_Cmd()
enable DMA to send data inSPI_WriteBuf
to the slave.When GDMA transfer is completed, transfer complete interrupt is triggered:
Call
GDMA_INTConfig()
to disable GDMA transfer complete interruptGDMA_INT_Transfer
.Call
GDMA_ClearINTPendingBit()
to clearGDMA_INT_Transfer
interrupt.
static void spi_tx_dma_handler(void)
{
IO_PRINT_INFO0("spi_tx_dma_handler");
GDMA_INTConfig(SPI_DMA_CHANNEL_NUM, GDMA_INT_Transfer, DISABLE);
GDMA_ClearINTPendingBit(SPI_DMA_CHANNEL_NUM, GDMA_INT_Transfer);
}