这里简单贴出来之前的部分嵌入式系统 SPI 通信的高级封装库实现,这个库提供了清晰的 API 接口、设备管理、错误处理和中断支持等特性,适用于大多数 ARM Cortex-M 系列微控制器。
/**
* @file spi_master.h
* @brief 嵌入式SPI总线高级封装库
* @author start_up_go
* @date 2025-06-29
*/
#ifndef SPI_MASTER_H
#define SPI_MASTER_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/** SPI总线设备句柄类型 */
typedef struct SpiDevice* SpiHandle;
/** SPI通信模式 */
typedef enum {
SPI_MODE0 = 0, // CPOL=0, CPHA=0
SPI_MODE1, // CPOL=0, CPHA=1
SPI_MODE2, // CPOL=1, CPHA=0
SPI_MODE3 // CPOL=1, CPHA=1
} SpiMode;
/** SPI数据位宽 */
typedef enum {
SPI_BITS_8 = 8,
SPI_BITS_16 = 16,
SPI_BITS_32 = 32
} SpiBits;
/** SPI传输速率 */
typedef enum {
SPI_SPEED_1MHz = 1000000,
SPI_SPEED_2MHz = 2000000,
SPI_SPEED_4MHz = 4000000,
SPI_SPEED_8MHz = 8000000,
SPI_SPEED_16MHz = 16000000
} SpiSpeed;
/** SPI传输方向 */
typedef enum {
SPI_DIR_BOTH = 0, // 全双工
SPI_DIR_TX_ONLY = 1, // 只发送
SPI_DIR_RX_ONLY = 2 // 只接收
} SpiDirection;
/** SPI错误码 */
typedef enum {
SPI_SUCCESS = 0, // 操作成功
SPI_ERROR_INIT = -1, // 初始化失败
SPI_ERROR_PARAM = -2, // 参数错误
SPI_ERROR_BUSY = -3, // 总线忙
SPI_ERROR_TRANSFER = -4, // 传输错误
SPI_ERROR_TIMEOUT = -5, // 超时错误
SPI_ERROR_NOMEM = -6 // 内存不足
} SpiError;
/** SPI传输完成回调函数类型 */
typedef void (*SpiCallback)(SpiHandle handle, int error, void* user_data);
/** SPI设备配置结构体 */
typedef struct {
uint8_t bus_id; // SPI总线ID
uint8_t cs_pin; // 片选引脚
bool cs_active_low; // 片选低电平有效
SpiMode mode; // SPI模式
SpiBits bits; // 数据位宽
SpiSpeed speed; // 传输速率
uint32_t timeout_ms; // 超时时间(毫秒)
SpiDirection direction; // 传输方向
SpiCallback callback; // 传输完成回调函数
void* user_data; // 用户数据
} SpiConfig;
/**
* @brief 初始化SPI总线驱动
* @param bus_id SPI总线ID
* @return 成功返回SPI_SUCCESS,失败返回错误码
*/
int spi_master_init(uint8_t bus_id);
/**
* @brief 反初始化SPI总线驱动
* @param bus_id SPI总线ID
* @return 成功返回SPI_SUCCESS,失败返回错误码
*/
int spi_master_deinit(uint8_t bus_id);
/**
* @brief 创建SPI设备实例
* @param config SPI设备配置
* @param[out] handle 输出的SPI设备句柄
* @return 成功返回SPI_SUCCESS,失败返回错误码
*/
int spi_device_create(const SpiConfig* config, SpiHandle* handle);
/**
* @brief 销毁SPI设备实例
* @param handle SPI设备句柄
* @return 成功返回SPI_SUCCESS,失败返回错误码
*/
int spi_device_destroy(SpiHandle handle);
/**
* @brief 同步SPI传输(阻塞模式)
* @param handle SPI设备句柄
* @param tx_data 发送数据缓冲区
* @param rx_data 接收数据缓冲区
* @param length 数据长度(字节)
* @return 成功返回实际传输的字节数,失败返回错误码
*/
int spi_device_transfer(SpiHandle handle, const void* tx_data, void* rx_data, size_t length);
/**
* @brief 异步SPI传输(非阻塞模式)
* @param handle SPI设备句柄
* @param tx_data 发送数据缓冲区
* @param rx_data 接收数据缓冲区
* @param length 数据长度(字节)
* @return 成功返回SPI_SUCCESS,失败返回错误码
*/
int spi_device_transfer_async(SpiHandle handle, const void* tx_data, void* rx_data, size_t length);
/**
* @brief 设置SPI设备参数
* @param handle SPI设备句柄
* @param config 新的SPI设备配置
* @return 成功返回SPI_SUCCESS,失败返回错误码
*/
int spi_device_configure(SpiHandle handle, const SpiConfig* config);
/**
* @brief 获取SPI设备状态
* @param handle SPI设备句柄
* @param[out] is_busy 输出设备是否繁忙
* @return 成功返回SPI_SUCCESS,失败返回错误码
*/
int spi_device_get_status(SpiHandle handle, bool* is_busy);
/**
* @brief 获取SPI错误信息
* @param error 错误码
* @return 错误信息字符串
*/
const char* spi_get_error_string(int error);
#ifdef __cplusplus
}
#endif
#endif // SPI_MASTER_H
/**
* @file spi_master.c
* @brief 嵌入式SPI总线高级封装库实现
* @author start_up_go
* @date 2025-06-29
*/
#include "spi_master.h"
#include <stdlib.h>
#include <string.h>
#include "driver/spi.h" // 假设这是底层SPI驱动
/** SPI设备结构体 */
struct SpiDevice {
uint8_t bus_id; // SPI总线ID
uint8_t cs_pin; // 片选引脚
bool cs_active_low; // 片选低电平有效
SpiMode mode; // SPI模式
SpiBits bits; // 数据位宽
SpiSpeed speed; // 传输速率
uint32_t timeout_ms; // 超时时间(毫秒)
SpiDirection direction; // 传输方向
SpiCallback callback; // 传输完成回调函数
void* user_data; // 用户数据
bool is_busy; // 设备忙标志
};
/** 错误信息表 */
static const char* error_strings[] = {
"Success",
"Initialization error",
"Parameter error",
"Busy",
"Transfer error",
"Timeout error",
"Memory allocation failed"
};
/**
* @brief SPI传输完成回调函数(底层驱动调用)
* @param bus_id SPI总线ID
* @param error 错误码
* @param user_data 用户数据
*/
static void spi_transfer_complete_callback(uint8_t bus_id, int error, void* user_data) {
SpiHandle handle = (SpiHandle)user_data;
if (handle) {
handle->is_busy = false;
if (handle->callback) {
handle->callback(handle, error, handle->user_data);
}
}
}
int spi_master_init(uint8_t bus_id) {
// 初始化底层SPI驱动
return spi_driver_init(bus_id);
}
int spi_master_deinit(uint8_t bus_id) {
// 反初始化底层SPI驱动
return spi_driver_deinit(bus_id);
}
int spi_device_create(const SpiConfig* config, SpiHandle* handle) {
if (!config || !handle) {
return SPI_ERROR_PARAM;
}
// 分配设备结构体内存
SpiHandle dev = (SpiHandle)malloc(sizeof(struct SpiDevice));
if (!dev) {
return SPI_ERROR_NOMEM;
}
// 复制配置参数
memcpy(dev, config, sizeof(struct SpiDevice));
dev->is_busy = false;
// 配置底层SPI驱动
int ret = spi_driver_configure(
dev->bus_id,
dev->mode,
dev->bits,
dev->speed,
dev->direction
);
if (ret != 0) {
free(dev);
return SPI_ERROR_INIT;
}
*handle = dev;
return SPI_SUCCESS;
}
int spi_device_destroy(SpiHandle handle) {
if (!handle) {
return SPI_ERROR_PARAM;
}
// 释放设备结构体内存
free(handle);
return SPI_SUCCESS;
}
int spi_device_transfer(SpiHandle handle, const void* tx_data, void* rx_data, size_t length) {
if (!handle || (!tx_data && !rx_data) || length == 0) {
return SPI_ERROR_PARAM;
}
if (handle->is_busy) {
return SPI_ERROR_BUSY;
}
handle->is_busy = true;
// 使能片选
gpio_set_level(handle->cs_pin, handle->cs_active_low ? 0 : 1);
// 执行SPI传输
int ret = spi_driver_transfer(
handle->bus_id,
tx_data,
rx_data,
length,
handle->timeout_ms
);
// 禁用片选
gpio_set_level(handle->cs_pin, handle->cs_active_low ? 1 : 0);
handle->is_busy = false;
return ret >= 0 ? ret : SPI_ERROR_TRANSFER;
}
int spi_device_transfer_async(SpiHandle handle, const void* tx_data, void* rx_data, size_t length) {
if (!handle || (!tx_data && !rx_data) || length == 0) {
return SPI_ERROR_PARAM;
}
if (handle->is_busy) {
return SPI_ERROR_BUSY;
}
handle->is_busy = true;
// 使能片选
gpio_set_level(handle->cs_pin, handle->cs_active_low ? 0 : 1);
// 执行异步SPI传输
int ret = spi_driver_transfer_async(
handle->bus_id,
tx_data,
rx_data,
length,
handle->timeout_ms,
spi_transfer_complete_callback,
handle
);
if (ret != 0) {
// 传输启动失败,禁用片选
gpio_set_level(handle->cs_pin, handle->cs_active_low ? 1 : 0);
handle->is_busy = false;
return SPI_ERROR_TRANSFER;
}
return SPI_SUCCESS;
}
int spi_device_configure(SpiHandle handle, const SpiConfig* config) {
if (!handle || !config) {
return SPI_ERROR_PARAM;
}
// 复制配置参数
memcpy(handle, config, sizeof(struct SpiDevice));
// 配置底层SPI驱动
return spi_driver_configure(
handle->bus_id,
handle->mode,
handle->bits,
handle->speed,
handle->direction
);
}
int spi_device_get_status(SpiHandle handle, bool* is_busy) {
if (!handle || !is_busy) {
return SPI_ERROR_PARAM;
}
*is_busy = handle->is_busy;
return SPI_SUCCESS;
}
const char* spi_get_error_string(int error) {
if (error >= SPI_SUCCESS && error <= SPI_ERROR_NOMEM) {
return error_strings[error * -1];
}
return "Unknown error";
}
这个 SPI 库提供了以下特性:
- 面向对象的 API 设计,使用句柄管理多个 SPI 设备
- 支持同步和异步两种传输模式
- 完整的错误处理和错误码系统
- 可配置的 SPI 参数,包括模式、位宽、速率等
- 支持多设备管理,可同时操作多个 SPI 从设备
- 清晰的设备状态管理
- 片选信号自动控制
使用时,你需要根据具体的硬件平台实现底层驱动接口 (spi_driver_*)。这个库设计为可移植的,适用于 STM32、ESP32 等多种嵌入式平台。
1183

被折叠的 条评论
为什么被折叠?



