SPI 代码¶
组件架构¶
driver/spi/CMakeLists.txt¶
set(src_dirs
.
)
set(include_dirs
include
)
set(requires
driver
)
idf_component_register(SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})
Note
注意,在驱动程序中,我们使用了 ESP-IDF 内置的 driver
库中的spi和gpio相关函数,因此,我们需要在 CMakeLists.txt
文件的 REQUIRES
字段中指明这个依赖关系。
spi.h¶
/**
* @file spi.h
* @author SHUAIWEN CUI (SHUAIWEN001@e.ntu.edu.sg)
* @brief
* @version 1.0
* @date 2024-11-18
* @ref Alientek SPI driver
* @copyright Copyright (c) 2024
*
*/
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
/* Dependencies */
#include <string.h>
#include "esp_log.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
/* GPIO Definitions */
#define SPI2_MOSI_GPIO_PIN GPIO_NUM_11 /* SPI2_MOSI */
#define SPI2_CLK_GPIO_PIN GPIO_NUM_12 /* SPI2_CLK */
#define SPI2_MISO_GPIO_PIN GPIO_NUM_13 /* SPI2_MISO */
/* SPI3 GPIO Definitions for ADXL355 */
#define SPI3_MOSI_GPIO_PIN GPIO_NUM_5 /* SPI3_MOSI */
#define SPI3_CLK_GPIO_PIN GPIO_NUM_7 /* SPI3_SCLK */
#define SPI3_MISO_GPIO_PIN GPIO_NUM_6 /* SPI3_MISO */
/* Global SPI device handles */
/* Function Prototypes */
/**
* @brief Initialize SPI2
* @param None
* @retval None
*/
void spi2_init(void);
/**
* @brief Initialize SPI3 for ADXL355
* @param None
* @retval None
*/
void spi3_init(void);
/**
* @brief Send command via SPI2
* @param handle : SPI handle
* @param cmd : Command to send
* @retval None
*/
void spi2_write_cmd(spi_device_handle_t handle, uint8_t cmd);
/**
* @brief Send command via SPI3
* @param handle : SPI handle
* @param cmd : Command to send
* @retval None
*/
void spi3_write_cmd(spi_device_handle_t handle, uint8_t cmd);
/**
* @brief Send data via SPI2
* @param handle : SPI handle
* @param data : Data to send
* @param len : Length of data to send
* @retval None
*/
void spi2_write_data(spi_device_handle_t handle, const uint8_t *data, int len);
/**
* @brief Send data via SPI3
* @param handle : SPI handle
* @param data : Data to send
* @param len : Length of data to send
* @retval None
*/
void spi3_write_data(spi_device_handle_t handle, const uint8_t *data, int len);
/**
* @brief Process data via SPI2
* @param handle : SPI handle
* @param data : Data to send
* @retval t.rx_data[0] : Received data
*/
uint8_t spi2_transfer_byte(spi_device_handle_t handle, uint8_t byte);
/**
* @brief Process data via SPI3
* @param handle : SPI handle
* @param data : Data to send
* @retval t.rx_data[0] : Received data
*/
uint8_t spi3_transfer_byte(spi_device_handle_t handle, uint8_t byte);
/**
* @brief Read data via SPI2
* @param handle : SPI handle
* @param data : Buffer to store received data
* @param len : Length of data to read
* @retval None
*/
void spi2_read_data(spi_device_handle_t handle, uint8_t *data, int len);
/**
* @brief Read data via SPI3
* @param handle : SPI handle
* @param data : Buffer to store received data
* @param len : Length of data to read
* @retval None
*/
void spi3_read_data(spi_device_handle_t handle, uint8_t *data, int len);
/**
* @brief Read single byte via SPI2
* @param handle : SPI handle
* @retval Received byte
*/
uint8_t spi2_read_byte(spi_device_handle_t handle);
/**
* @brief Read single byte via SPI3
* @param handle : SPI handle
* @retval Received byte
*/
uint8_t spi3_read_byte(spi_device_handle_t handle);
#ifdef __cplusplus
}
#endif
spi.c¶
/**
* @file spi.c
* @author
* @brief
* @version 1.0
* @date 2024-11-18
* @ref Alientek SPI driver
*
*/
#include "spi.h"
#ifdef __cplusplus
extern "C"
{
#endif
/* Global SPI device handles */
// spi_device_handle_t spi3_device_handle = NULL; // Removed, now returned via function parameter
//==============================================================================
// SPI2 FUNCTIONS
//==============================================================================
/**
* @brief Initialize SPI2
* @param None
* @retval None
*/
void spi2_init(void)
{
esp_err_t ret = 0;
spi_bus_config_t spi_bus_conf = {0};
/* SPI bus configuration */
spi_bus_conf.miso_io_num = SPI2_MISO_GPIO_PIN; /* SPI_MISO pin */
spi_bus_conf.mosi_io_num = SPI2_MOSI_GPIO_PIN; /* SPI_MOSI pin */
spi_bus_conf.sclk_io_num = SPI2_CLK_GPIO_PIN; /* SPI_SCLK pin */
spi_bus_conf.quadwp_io_num = -1; /* SPI write protection signal pin, not enabled */
spi_bus_conf.quadhd_io_num = -1; /* SPI hold signal pin, not enabled */
spi_bus_conf.max_transfer_sz = 160 * 80 * 2; /* Configure maximum transfer size in bytes */
/* Initialize SPI bus */
ret = spi_bus_initialize(SPI2_HOST, &spi_bus_conf, SPI_DMA_CH_AUTO); /* SPI bus initialization */
ESP_ERROR_CHECK(ret); /* Check parameter values */
}
/**
* @brief Send command via SPI2
* @param handle : SPI handle
* @param cmd : Command to send
* @retval None
*/
void spi2_write_cmd(spi_device_handle_t handle, uint8_t cmd)
{
esp_err_t ret;
spi_transaction_t t = {0};
t.length = 8; /* Number of bits to transmit (1 byte = 8 bits) */
t.tx_buffer = &cmd; /* Fill the command */
ret = spi_device_polling_transmit(handle, &t); /* Start transmission */
ESP_ERROR_CHECK(ret); /* Usually no issues */
}
/**
* @brief Send data via SPI2
* @param handle : SPI handle
* @param data : Data to send
* @param len : Length of data to send
* @retval None
*/
void spi2_write_data(spi_device_handle_t handle, const uint8_t *data, int len)
{
esp_err_t ret;
spi_transaction_t t = {0};
if (len == 0)
{
return; /* No data to transmit if length is 0 */
}
t.length = len * 8; /* Number of bits to transmit (1 byte = 8 bits) */
t.tx_buffer = data; /* Fill the data */
ret = spi_device_polling_transmit(handle, &t); /* Start transmission */
ESP_ERROR_CHECK(ret); /* Usually no issues */
}
/**
* @brief Process data via SPI2
* @param handle : SPI handle
* @param data : Data to send
* @retval t.rx_data[0] : Received data
*/
uint8_t spi2_transfer_byte(spi_device_handle_t handle, uint8_t data)
{
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.length = 8;
t.tx_data[0] = data;
spi_device_transmit(handle, &t);
return t.rx_data[0];
}
/**
* @brief Read data via SPI2
* @param handle : SPI handle
* @param data : Buffer to store received data
* @param len : Length of data to read
* @retval None
*/
void spi2_read_data(spi_device_handle_t handle, uint8_t *data, int len)
{
esp_err_t ret;
spi_transaction_t t = {0};
if (len == 0)
{
return; /* No data to read if length is 0 */
}
t.length = len * 8; /* Number of bits to receive (1 byte = 8 bits) */
t.rx_buffer = data; /* Buffer to store received data */
t.tx_buffer = NULL; /* No actual data to transmit */
t.flags = 0; /* Clear all flags */
/* Use polling transmit for better control */
ret = spi_device_polling_transmit(handle, &t);
ESP_ERROR_CHECK(ret); /* Check for errors */
}
/**
* @brief Read single byte via SPI2
* @param handle : SPI handle
* @retval Received byte
*/
uint8_t spi2_read_byte(spi_device_handle_t handle)
{
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.flags = SPI_TRANS_USE_RXDATA;
t.length = 8;
spi_device_transmit(handle, &t);
return t.rx_data[0];
}
//==============================================================================
// SPI3 FUNCTIONS
//==============================================================================
/**
* @brief Initialize SPI3 for ADXL355
* @param None
* @retval None
*/
void spi3_init(void)
{
esp_err_t ret;
spi_bus_config_t spi_bus_conf = {0};
/* Step 1: Configure SPI bus parameters */
spi_bus_conf.miso_io_num = SPI3_MISO_GPIO_PIN; // MISO pin
spi_bus_conf.mosi_io_num = SPI3_MOSI_GPIO_PIN; // MOSI pin
spi_bus_conf.sclk_io_num = SPI3_CLK_GPIO_PIN; // SCLK pin
spi_bus_conf.quadwp_io_num = -1; // Not used
spi_bus_conf.quadhd_io_num = -1; // Not used
spi_bus_conf.max_transfer_sz = 1024; // Maximum transfer size
/* Step 2: Initialize SPI bus (DMA disabled) */
ret = spi_bus_initialize(SPI3_HOST, &spi_bus_conf, SPI_DMA_DISABLED);
if (ret != ESP_OK) {
ESP_LOGE("SPI3", "SPI bus initialization failed: %s", esp_err_to_name(ret));
ESP_ERROR_CHECK(ret);
}
ESP_LOGI("SPI3", "SPI3 bus initialized successfully");
}
/**
* @brief Send command via SPI3
* @param handle : SPI handle
* @param cmd : Command to send
* @retval None
*/
void spi3_write_cmd(spi_device_handle_t handle, uint8_t cmd)
{
esp_err_t ret;
spi_transaction_t t = {0};
t.length = 8; /* Number of bits to transmit (1 byte = 8 bits) */
t.tx_buffer = &cmd; /* Fill the command */
ret = spi_device_polling_transmit(handle, &t); /* Start transmission */
ESP_ERROR_CHECK(ret); /* Usually no issues */
}
/**
* @brief Send data via SPI3
* @param handle : SPI handle
* @param data : Data to send
* @param len : Length of data to send
* @retval None
*/
void spi3_write_data(spi_device_handle_t handle, const uint8_t *data, int len)
{
esp_err_t ret;
spi_transaction_t t = {0};
if (len == 0)
{
ESP_LOGW("SPI3", "Write length is 0, skipping");
return;
}
ESP_LOGD("SPI3", "Writing %d bytes to SPI3", len);
/* Configure transaction like plasmapper for write */
t.cmd = 0; /* No command bits */
t.addr = data[0]; /* First byte as address */
t.length = (len - 1) * 8; /* Remaining bytes as data */
t.tx_buffer = &data[1]; /* Data to write (excluding address) */
t.rx_buffer = NULL; /* No read data */
t.flags = 0; /* Use default flags */
ret = spi_device_polling_transmit(handle, &t);
if (ret != ESP_OK) {
ESP_LOGE("SPI3", "SPI3 write failed: %s", esp_err_to_name(ret));
}
ESP_ERROR_CHECK(ret);
ESP_LOGD("SPI3", "Wrote %d bytes successfully", len);
}
/**
* @brief Process data via SPI3
* @param handle : SPI handle
* @param data : Data to send
* @retval t.rx_data[0] : Received data
*/
uint8_t spi3_transfer_byte(spi_device_handle_t handle, uint8_t data)
{
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
t.length = 8;
t.tx_data[0] = data;
spi_device_transmit(handle, &t);
return t.rx_data[0];
}
/**
* @brief Read data via SPI3
* @param handle : SPI handle
* @param data : Buffer to store received data
* @param len : Length of data to read
* @retval None
*/
void spi3_read_data(spi_device_handle_t handle, uint8_t *data, int len)
{
esp_err_t ret;
spi_transaction_t t = {0};
if (len == 0)
{
ESP_LOGW("SPI3", "Read length is 0, skipping");
return; /* No data to read if length is 0 */
}
ESP_LOGD("SPI3", "Reading %d bytes from SPI3", len);
/* For ADXL355, we need to send a dummy byte to generate clock while reading */
/* Configure transaction for read operation with dummy transmit */
t.length = len * 8; /* Number of bits to receive (1 byte = 8 bits) */
t.rx_buffer = data; /* Buffer to store received data */
t.tx_buffer = NULL; /* No actual data to transmit */
t.flags = 0; /* Clear all flags */
/* Use polling transmit for better control */
ret = spi_device_polling_transmit(handle, &t);
if (ret != ESP_OK) {
ESP_LOGE("SPI3", "SPI3 read failed: %s", esp_err_to_name(ret));
}
ESP_ERROR_CHECK(ret); /* Check for errors */
ESP_LOGD("SPI3", "Read %d bytes successfully", len);
}
/**
* @brief Read single byte via SPI3
* @param handle : SPI handle
* @retval Received byte
*/
uint8_t spi3_read_byte(spi_device_handle_t handle)
{
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.flags = SPI_TRANS_USE_RXDATA;
t.length = 8;
spi_device_transmit(handle, &t);
return t.rx_data[0];
}
#ifdef __cplusplus
}
#endif