尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于 ESP-IDF Extended VFS 的 SPI Master 简单示例:用 POSIX 接口驱动 SPI 主机

基于 ESP-IDF Extended VFS 的 SPI Master 简单示例:用 POSIX 接口驱动 SPI 主机 基于 ESP-IDF Extended VFS 的 SPI Master 简单示例用 POSIX 接口驱动 SPI 主机【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution导读spi_master_simple是 esp-iot-solution 仓库examples/extended_vfs/spi/目录下的官方示例演示了如何通过 POSIX 标准接口open / ioctl / close配置并驱动 SPI 主机Master从而降低应用对底层硬件与平台 API 的直接依赖。本文将围绕该示例的硬件连接、菜单配置、编译烧录与源码实现展开并结合extended_vfs组件的 SPI 底层实现ext_vfs_spi.c与配套的 SPI Slave Simple 示例讲解这套类文件系统操作外设方案背后的原理。读完本文你将能够独立搭建两块 ESP 开发板之间的 SPI 主从通信并掌握 Extended VFS 的扩展用法。Extended VFS 与 SPI 示例概述Extended VFS扩展虚拟文件系统是 esp-iot-solution 提供的一个组件其设计目标正如 组件 README 所述让应用通过 POSIX APIopen、close、read、write、ioctl 等读写和配置外设。目前该组件支持四类外设GPIO、I2C、LEDC 与 SPI。在本 SPI 示例中SPI 主机外设被注册为一个虚拟设备节点/dev/spi/2或/dev/spi/3应用只需像操作普通文件一样打开该节点再通过ioctl下发配置与传输命令即可完成一次 SPI 通信。这样做的好处是平台无关应用代码不再直接调用spi_bus_initialize、spi_bus_add_device等 ESP-IDF 驱动 API减少了对特定芯片和平台的耦合接口统一GPIO、I2C、SPI 等外设都以设备文件 ioctl 命令的形式暴露学习成本低、便于抽象与复用。在动手实验之前建议先阅读 extended_vfs 组件文档了解组件如何通过idf.py add-dependency espressif/extended_vfs*添加依赖、以及如何用idf.py create-project-from-example从示例模板创建工程。硬件准备与接线本示例需要两块开发板配合工作一块运行 SPI Master 示例另一块运行配套的 SPI Slave Simple 示例。所需硬件如下2 块基于乐鑫EspressifSoC 的开发板2 根 USB 线用于供电和程序烧录5 根杜邦线用于连接两块开发板之间的 SPI 引脚与 GND。其中 4 根信号线分别连接两块板子的 CS片选、SCLK时钟、MOSI主发从收、MISO主收从发引脚另 1 根为共地GND保证两块板子电平参考一致。SPI 属于同步串行接口通信完全由主机侧时钟驱动因此主从两端的引脚号不需要相同只要逻辑对应即可但两端必须使用相同的 SPI Mode本示例默认 Mode 0。工程配置menuconfig开始配置与编译前请先确认目标芯片型号执行idf.py set-target chip_name然后打开工程配置菜单idf.py menuconfig在Example Configuration菜单下按如下步骤配置选择 SPI 端口在Select SPI Device选项中挑选SPI2或SPI3。需要注意的是并非所有 SoC 都支持 SPI3请依据目标芯片的 SPI 外设数量选择设置 SPI 引脚号根据你的开发板实际接线依次设置SPI CS Pin Number片选引脚SPI SCLK Pin Number时钟引脚SPI MOSI Pin Number主机输出/从机输入引脚SPI MISO Pin Number主机输入/从机输出引脚设置传输次数在SPI Testing Count of Transmitting Data中配置发送数据的测试次数示例日志中会连续打印多次写入结果。这些选项定义在示例的 Kconfig.projbuild 中。从配置文件中可以看到引脚号默认值按芯片型号自动适配例如配置项ESP32 / ESP32S2ESP32C3ESP32S3SPI_CS_PIN_NUM141010SPI_SCLK_PIN_NUM15612SPI_MOSI_PIN_NUM12711SPI_MISO_PIN_NUM13213同时SPI_DEVICE是一个选择choice项默认选中SPI2。示例代码会根据该配置在编译期决定打开/dev/spi/2还是/dev/spi/3#ifdef CONFIG_SPI_DEVICE_SPI2 #define SPI_DEVICE /dev/spi/2 #elif defined(CONFIG_SPI_DEVICE_SPI3) #define SPI_DEVICE /dev/spi/3 #endif编译、烧录与运行完成配置后在工程目录下执行idf.py -p PORT flash monitor该命令会依次完成编译、烧录并打开串口监视器PORT替换为实际串口如/dev/ttyUSB0。如需退出串口监视器按Ctrl-]即可。由于 SPI 通信需要主机与从机同时工作建议先烧录并运行从机示例再运行主机示例或者让两块板子同时上电运行。注意SPI Slave Simple 与主机示例共用同一套Example Configuration菜单两端的Select SPI Device、SPI 引脚与 SPI Mode 必须保持一致。示例运行输出主机示例正常运行后串口会输出类似如下的日志I (0) cpu_start: Starting scheduler on APP CPU. I (345) ext_vfs: Extended VFS version: 0.3.0 Opening device /dev/spi/2 for writing OK, fd3. Write text total 32 bytes into device OK. Write text total 32 bytes into device OK. Write text total 32 bytes into device OK. ...从日志可以看出关键流程ext_vfs_init()打印组件版本号后open()成功打开/dev/spi/2并返回文件描述符fd3随后循环调用ioctl执行 32 字节的 SPI 传输。与之对应的从机侧日志会显示接收到的内容I (344) ext_vfs: Extended VFS version: 0.3.0 Opening device /dev/spi/2 for writing OK, fd3. Receive total 32 bytes from device: SPI Tx 0 Receive total 32 bytes from device: SPI Tx 1 ...从机打印的SPI Tx 0、SPI Tx 1正是主机侧通过snprintf拼装并发送的字符串说明主从数据链路已打通。源码解析从 POSIX 调用到 SPI 驱动1. 初始化与打开设备示例入口 spi_master_simple_main.c 中app_main首先调用ext_vfs_init();该函数在 ext_vfs.c 中实现会打印组件版本并根据CONFIG_EXTENDED_VFS_SPI等 Kconfig 开关逐个注册 GPIO / I2C / LEDC / SPI 的 VFS 驱动。SPI 的注册实现在 ext_vfs_spi.c 的ext_vfs_spi_init()中static const esp_vfs_t vfs { .flags ESP_VFS_FLAG_DEFAULT, .open spi_open, .ioctl spi_ioctl, .close spi_close, }; esp_err_t err esp_vfs_register(/dev/spi, vfs, NULL);可以看到组件把/dev/spi注册为基路径spi_open会把路径中/dev/spi/后面的数字解析为 SPI 端口号atoi(path 1)并校验其落在合法范围内。这也解释了示例中为什么设备名是/dev/spi/2——2即 SPI2 外设。2. ioctl 配置SPIIOCSCFGopen成功后示例构造spi_cfg_t配置结构体并通过ioctl(fd, SPIIOCSCFG, cfg)下发。配置内容定义在 esp_spi_ioctl.hcfg.flags SPI_MASTER | SPI_MODE_0; cfg.cs_pin SPI_DEVICE_CS_PIN; cfg.sclk_pin SPI_DEVICE_SCLK_PIN; cfg.mosi_pin SPI_DEVICE_MOSI_PIN; cfg.miso_pin SPI_DEVICE_MISO_PIN; cfg.master.clock SPI_DEVICE_CLOCK; // 1 MHz其中SPI_MASTER1 0使能主机模式SPI_MODE_0SPI 模式 0对应 (CPOL, CPHA) (0, 0)。头文件同时定义了SPI_MODE_1/2/3分别对应 (0,1)、(1,0)、(1,1)以及SPI_RX_LSB/SPI_TX_LSB用于切换最低有效位先传的位序cfg.master.clock主机时钟频率示例中为1000 * 1000即 1 MHz。在驱动层 ext_vfs_spi.c 的config_spi()中这些参数会被翻译成 ESP-IDF 的驱动配置spi_bus_initialize()初始化总线DMA 采用SPI_DMA_CH_AUTO最大传输长度SPI_TRANSFER_SZ为 512 字节队列深度SPI_QUEUE_NUM为 4随后spi_bus_add_device()添加设备并把mode、clock_speed_hz、spics_io_num以及 RX/TX 位序标志逐一带入spi_device_interface_config_t。ioctl处理函数还会做状态校验设备未配置configured为 0时才允许执行配置避免重复初始化。3. ioctl 传输SPIIOCEXCHANGE配置完成后示例进入循环构造spi_ex_msg_t消息结构体并通过ioctl(fd, SPIIOCEXCHANGE, msg)发起一次全双工传输spi_ex_msg_t msg; snprintf(text, text_size, SPI Tx %d, count); msg.rx_buffer NULL; // 主机示例只发送不接收 msg.tx_buffer text; msg.size text_size; // 32 字节 ioctl(fd, SPIIOCEXCHANGE, msg); usleep(100 * 1000); // 每次传输间隔 100msspi_ex_msg_t的字段含义见 esp_spi_ioctl.htx_buffer要发送的数据指针rx_buffer接收数据缓冲区指针size字节数。对主机而言是本次传输的长度对从机而言传输完成后会被更新为实际收到的字节数。底层spi_transfer()会根据该端口是主机还是从机分别调用spi_master_transfer()或spi_slave_transfer()。主机路径把size乘以 8 换算成比特长度填入spi_transaction_t然后调用spi_device_transmit()从机路径则调用spi_slave_transmit()并在成功后用t.trans_len / 8回写实际接收字节数——这就是从机日志中Receive total 32 bytes数据的来源。从机示例源码见 spi_slave_simple_main.c它同样使用SPIIOCSCFG配置但flags中不带SPI_MASTER表示从机模式并用 4 字节对齐的recv_buffer循环接收数据。4. 关闭设备示例在出错路径会调用close(fd)释放资源。对应驱动层的spi_close()会根据模式分别执行spi_bus_remove_device()spi_bus_free()主机或spi_slave_free()从机并复位configured状态保证下次open后可以重新配置。常见问题与排障建议主机提示Opening device ... failed多为端口号超出范围或 VFS 未注册成功请确认CONFIG_EXTENDED_VFS_SPI已开启并核对Select SPI Device的选择主机持续打印Write ... failed, errnoEIO通常是接线错误、两端 SPI Mode 不一致或从机未运行/未配置。请检查 5 根杜邦线含 GND 共地与两端引脚号从机收不到完整数据或数据错位确认两端SPI SCLK / MOSI / MISO / CS引脚号一一对应且波特率时钟频率在从机可接受范围内示例默认 1 MHz 属于保守速率便于排查问题更换芯片后默认引脚变化Kconfig 中引脚默认值按IDF_TARGET_*区分切换idf.py set-target后建议重新menuconfig核对引脚。总结通过spi_master_simple与配套的spi_slave_simple你可以用最少的硬件两块开发板 5 根杜邦线快速验证 Extended VFS 的 SPI 能力。示例展示了完整的 POSIX 化外设编程模型open设备节点 →ioctl(SPIIOCSCFG)配置 →ioctl(SPIIOCEXCHANGE)传输 →close释放。其底层实现ext_vfs_spi.c在保持 POSIX 接口抽象的同时完整映射了 ESP-IDF 的 SPI 主机/从机驱动能力适合作为学习文件系统式外设抽象以及后续扩展 GPIO、I2C、LEDC 等外设编程的起点。仓库中还有对应的 gpio_simple、i2c 示例 与 ledc_simple 可供对照学习。【免费下载链接】esp-iot-solutionEspressif IoT Library. IoT Device Drivers, Documentations and Solutions.项目地址: https://gitcode.com/GitHub_Trending/es/esp-iot-solution创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表