十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ESP32-S3 多 SPI 设备并行在线:4 步让两条总线不打架

ESP32-S3 多 SPI 设备并行在线:4 步让两条总线不打架 ESP32-S3 多 SPI 设备并行在线4 步让两条总线不打架【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32屏幕刚亮起来画面就花了SD 卡里的日志文件直接变砖串口监视器吐出一屏 0xFF。ESP32-S3 上多 SPI一条时钟线共享、一主对多从的总线协议设备同时跑常见姿势就是屏幕和卡抢同一条时钟线。今天用 arduino-esp32 里现成的双总线机制把这事拆开做一遍——两条总线各带各的设备互不打架。引脚布局决定分线空间先看你板子上哪些脚是真正空闲的。30 秒自检你板子是不是真在打架如果你看到单跑都正常一起跑就出错大概率不是器件问题而是时序撞车同一条总线被两段代码同时驱动时钟沿被搅在一起。如果你看到屏幕撕裂、卡上读回一片 0xFF且恰好发生在一帧画面推送和文件写入重叠的时段这是共享总线的典型症状。多 SPI 总线冲突八成是引脚分配的问题先别急着怀疑器件。如果你看到两个模块用的引脚都指向 pins_arduino.h 里那组默认值S3 devkit 上是 SCK12、MOSI11、MISO13、SS10那代码再怎么调也救不回来得先把线切开。换板子时也先来这里核对引脚定义是排雷的第一现场。SPI 信号不从固定引脚出来而是经过 GPIO 矩阵——芯片里的一块交换台——接到任意 GPIO。所谓冲突本质是两台控制器抢同一组 GPIO。分步走从接线到加速 这一步起按接线、初始化、调度、加速四件事来每步先说做什么再说为什么最后给关键参数。第一步 接线把共用的线切开做什么给每个设备配一整组 SCK、MOSI、MISO、CS任何两根线都不被两个设备共享。为什么S3 上全局SPI对象默认占着 FSPIHSPI 完全空闲两者是互相独立的硬件控制器走线全靠 GPIO 矩阵没有必须走哪几个脚的硬约束——约束只有一条别重叠。关键参数SD 卡沿用 FSPI 默认引脚屏幕在 HSPI 上另起一组新脚避开 strap 脚0、3、45~47和 USB 脚19、20。设备总线SCKMOSIMISOCSSD 卡FSPI默认12111310TFT 屏HSPI33353734这组 ESP32-S3 SPI 引脚分配可以直接抄// 屏幕引脚与 SD 卡完全独立一条线都不共享 #define TFT_SCK 33 #define TFT_MOSI 35 #define TFT_MISO 37 #define TFT_CS 34第二步 初始化把第二条总线建出来做什么new SPIClass(HSPI)建一个专用实例begin()时显式传引脚。为什么全局SPI对象只占一条总线S3 上是 FSPIHSPI 没有默认引脚不指定就挂不上去这和初代 ESP32 差别最大。SPIClass的定义在 SPI.h官方示例 SPI_Multiple_Buses.ino 骨架一样。建立第二条总线并把片选管好SPIClass *tft new SPIClass(HSPI); // 第二条独立总线 tft-begin(TFT_SCK, TFT_MISO, TFT_MOSI, TFT_CS); // 参数顺序SCK, MISO, MOSI, CS // CS 不会自动配置得自己拉 pinMode(TFT_CS, OUTPUT); digitalWrite(TFT_CS, HIGH); // 空闲时保持高关键参数begin()的参数顺序是 SCK、MISO、MOSI、CSMISO/MOSI 传反了屏幕不亮而且很难看出问题在哪。官方示例的注释也明说Arduino 这套 API 不会自动把 CS 拉低。第三步 调度每帧用事务包起来做什么每次访问设备用beginTransaction/endTransaction包住一次完整操作进事务后再拉低 CS。为什么事务一对开始/结束把这条总线的频率和模式临时锁住里的锁是内核自带的互斥——SPI.cpp 的beginTransaction会拿 paramLock 锁多任务用同一条总线时频率和模式不会被对方改到一半。两条不同的总线各自拿各自的锁天然并行谁也不用等谁。推一帧画面整段包在事务里void pushFrame(uint8_t *buf, uint32_t len) { tft-beginTransaction(SPISettings(40e6, MSBFIRST, SPI_MODE0)); // 40MHz屏幕模式 digitalWrite(TFT_CS, LOW); // 传输前拉低片选 tft-transfer(buf, len); digitalWrite(TFT_CS, HIGH); // 传输完释放片选 tft-endTransaction(); }想省手动拉 CS 的麻烦可以setHwCs(true)让硬件自动接管但多设备场景里手动切换更直观示例用的也是手动。第四步 加速让 FIFO 干活做什么一帧画面用一次transfer/writePixels推完别把一帧拆成很多小事务。为什么看 esp32-hal-spi.c 的传输路径是64 字节一批写进硬件 FIFO先进先出的缓冲寄存器再忙等它搬完。开销集中在每次事务开头拿锁、设分频、写控制寄存器。S3 上这条 HAL 路径是 CPU 陪着搬加速空间就在少停多跑——少开几次事务多走几段 64 字节。想要 DMA让硬件自己搬数据CPU 不用死等级别的异步是 IDF 层驱动的事知道方向就行这里不展开。【免费下载链接】arduino-esp32Arduino core for the ESP32 family of SoCs项目地址: https://gitcode.com/GitHub_Trending/ar/arduino-esp32创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表