SPI Slave Receiver Example
Note
This document is automatically translated using AI. Please excuse any detailed errors. The official English version is still in progress.
Example Description
This example demonstrates how to use the SPI slave driver in ESP-IDF to receive transactions initiated by the master, and return data to the master during the transaction.
Running Method
This example needs to be used in conjunction with the Sender Example, both of which are burned into two ESP32 series chips and the signal lines are correctly connected to achieve complete data exchange. The Receiver is configured as an SPI slave in the communication, passively waiting for the Sender (SPI master) to initiate transmission, and informs the master through a handshake signal that it is ready, thus ensuring the correctness and synchronization of data transmission. For an explanation of the SPI slave mode, refer to SPI Slave Driver.
The complete code of the example can be found at SPI Slave Receiver Example. For instructions on configuration before running, corresponding GPIO pins, build and burn process, see the README.md file in the spi_slave
directory.
For custom configuration items and viewing default values, refer to the Macro Definition Description section.
Header File Description
The header files used in this example cover basic modules such as FreeRTOS task management, log output, SPI driver, and GPIO control. They provide support for SPI slave initialization, data transmission, and task scheduling.
The header files are categorized by function as follows:
FreeRTOS Task Scheduling : Provides task creation and scheduling functions.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
System Tools : Provides standard input and output, data type definition, and log output functions.
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "esp_log.h"
SPI Slave Driver : Provides initialization, data sending and receiving functions for SPI slave mode.
#include "driver/spi_slave.h"
GPIO Control : Provides GPIO pin configuration and level control functions.
#include "driver/gpio.h"
Macro Definition Description
The macro definitions involved in this example are mainly used to configure the pins of the SPI peripheral, the controller selection, and the handshake signal pin, which is convenient for subsequent SPI data transmission and task scheduling.
The macro definitions are categorized by function as follows:
SPI Slave Configuration
Defines the host interface used by the SPI slave. In this example,
SPI2_HOST
, i.e., SPI2 peripheral, is used.#define RCV_HOST SPI2_HOST
Defines the key pins of SPI, including handshake, data input/output, clock, and chip select pins.
#define GPIO_HANDSHAKE 2 // Handshake signal #define GPIO_MOSI 12 // Master output, slave input #define GPIO_MISO 13 // Master input, slave output #define GPIO_SCLK 15 // SPI clock #define GPIO_CS 14 // Chip select signal
Note
The handshake pin is used for data synchronization control between the master and the slave, and the appropriate GPIO can be selected according to the hardware design.
The chip select pin is used to select the SPI slave to ensure correct communication of multiple slaves on the bus.
Task Function Description
This example defines two SPI slave callback functions to control the level of the handshake pin and achieve data synchronization between the master and the slave.
void my_post_setup_cb(spi_slave_transaction_t *trans);
void my_post_trans_cb(spi_slave_transaction_t *trans);
Input Parameter |
Parameter Function |
Parameter Description |
---|---|---|
|
Pointer to the SPI transaction structure, containing information about the buffer and length of this transmission. |
Pass in a valid pointer to access the information of this SPI transaction. |
Note
In this example, the passed parameters are not accessed or modified, they are only used to meet the function prototype requirements of the SPI slave callback function.
my_post_setup_cb()
: Called before the transaction starts, pulls up the level of the handshake pin to notify the master that the slave is ready.my_post_trans_cb()
: Called after the transaction is completed, pulls down the level of the handshake pin to notify the master that the data transmission has ended.
The above functions are executed by calling gpio_set_level()
, passing in 1 to pull up the level, and passing in 0 to pull down the level. For further introduction and parameter explanation, please refer to General GPIO API.
Main Function Description
This example demonstrates the process of SPI slave initialization, establishing communication with the master, and completing data transmission.
Define variables:
The variable
n
is defined to record the serial number of the current SPI transaction, which is convenient for distinguishing the data sent each time.The return value variable
ret
is defined to save the return status of the SPI peripheral related functions, to judge whether the operation is successful, and to handle errors or print prompt information according to the return value.
Configure the handshake signal GPIO: In the communication between the SPI slave and the master, in order to achieve reliable data transmission, a handshake signal (handshake line) is usually used to notify the master that the slave is ready to send or receive data.
Enable pull-up resistors on the signal line: Enable pull-up resistors for the key signal lines of the SPI bus to ensure that the line remains high when there is no master driving signal, avoiding floating or glitch signals.
Invoke
gpio_set_pull_mode()
to enable pull-up resistors on the signal line. For further introduction and parameter description, please refer to General GPIO API:
Pull-up on
GPIO_MOSI
to prevent mis-triggering or noise interference caused by line floating.Pull-up on
GPIO_SCLK
to ensure that the clock line remains high when not driven by the host, avoiding misrecognition of clock pulses by the slave.Pull-up on
GPIO_CS
to ensure that CS remains high when no host selects the slave, keeping the slave in an inactive state to prevent accidental communication.
Allocate DMA memory buffer: Allow SPI peripherals to directly access memory without going through the CPU, improving data transfer efficiency and reducing CPU usage, suitable for large data volume or high frequency transmission scenarios.
Define variable
sendbuf
as the send data buffer.Define variable
recvbuf
as the receive data buffer.After defining, call
spi_bus_dma_memory_alloc()
to allocate DMA-supported memory for the buffer, ensuring that SPI peripherals can efficiently and directly perform data transmission. For further introduction and parameter description, please refer to SPI Master Driver API.Terminate the program if allocation fails.
Initialize the buffer:
Initialize the receive data buffer
recvbuf
to0xA5
for debugging.Fill in data to the send buffer
sendbuf
, which includes the current transmission sequence number.Note
Initializing the receive buffer to a conspicuous placeholder value like
0xA5
can clearly distinguish between unreceived data and valid transmission data, making it easy to quickly detect transmission anomalies.
After the transaction is completed, the data sent by the host is saved in
recvbuf
, and the data insendbuf
is sent to the host.
Print received data: Output the data received by the slave to the console.