ESP32 S2 的 SPI-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2879|回复: 4

ESP32 S2 的 SPI

[复制链接]
发表于 2021-11-26 19:35 | 显示全部楼层 |阅读模式
本帖最后由 Zoologist 于 2021-12-2 21:03 编辑

ESP32 S2Arduino环境对于 SPI 的定义是有问题的。

打开ESP32-S2技术参考手册 (“esp32-s2_technical_reference_manual_cn”),可以看到下图:
spi1.png

对于 S2 这个芯片来说,有四个 SPI,其中“SPI0 SPI1 仅供内部使用,通过仲裁器共享SPI 信号总线”。因此,对于用户来说,只能使用 FSPIGP-SPI2)和SPI3GP-SPI3)。对比之前的 ESP32
spi2.png

同样的有4 SPI,其中“SPI0控制器作为 cache 访问外部存储单元接口使用 ,因此用户可以使用 SPI1-3,其中 SPI2 又称作 HSPI SPI3又称作 VPSI。其中的 HSPI VSPI 只是一个代号,并不表示 High Speed SPI 值了的。
对比二者,再次强调S2只有 FSPI SPI3。但是在\Arduino15\packages\esp32\hardware\esp32\2.0.1\cores\esp32\esp32-hal-spi.h中有如下定义:

  1. #if CONFIG_IDF_TARGET_ESP32C3

  2. #define FSPI  0

  3. #define HSPI  1

  4. #else

  5. #define FSPI  1 //SPI bus attached to the flash (can use the same data lines but different SS)

  6. #define HSPI  2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins

  7. #if CONFIG_IDF_TARGET_ESP32

  8. #define VSPI  3 //SPI bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins

  9. #endif

  10. #endif
复制代码

这样导致在你编写的 ESP32 S2 代码中 FSPI=1 HSPI=2, 换句话说 FSPI SPI1, HSPI 才是GP-SPI2。这会导致之前能够正常运行在ESP32的代码移植到 S2 之后SPI 无法工作(想确认这一点最简单的方法是示波器测量 SPI SCLK 信号)。
此外,SPI.cpp定义的 SPI实际上是 SPI1,这个在 S2 上根本无法工作。
  1. #if CONFIG_IDF_TARGET_ESP32

  2. SPIClass SPI(VSPI);

  3. #else

  4. SPIClass SPI(FSPI);

  5. #endif
复制代码


如果你的代码直接使用 SPI,那么无比将上面的代码修改为 SPIClass SPI(HSPI);。
第二个坑是关于 SPI 引脚分配的,同样在 SPI.cpp 中有如下定义,如果你没有给定 SPI 的引脚,那么默认分配的都是 -1 Pin:

  1.     if(sck == -1 && miso == -1 && mosi == -1 && ss == -1) {

  2. #if CONFIG_IDF_TARGET_ESP32S2

  3.         _sck = (_spi_num == FSPI) ? SCK : -1;

  4.         _miso = (_spi_num == FSPI) ? MISO : -1;

  5.         _mosi = (_spi_num == FSPI) ? MOSI : -1;

  6.         _ss = (_spi_num == FSPI) ? SS : -1;
复制代码


这个在代码中可以使用 Serial.print(hspi->pinSS()); 进行检查。最后是一个我这边测试过,ESP32 S2 工作正常的SPI 例子。使用 GP-SPI2 ,定义SCLK= 14, MISO = 12, MOSI = 13, SS = 15.


  1. #include <SPI.h>



  2. static const int spiClk = 40000000;



  3. SPIClass * hspi = NULL;



  4. void setup() {

  5.   Serial.begin(115200);

  6.   //initialise two instances of the SPIClass attached to VSPI and HSPI respectively

  7.   hspi = new SPIClass(HSPI);



  8.   //initialise hspi with default pins

  9.   //SCLK = 14, MISO = 12, MOSI = 13, SS = 15

  10.   hspi->begin(10,12,11,13);



  11.   //set up slave select pins as outputs as the Arduino API

  12.   //doesn't handle automatically pulling SS low

  13.   pinMode(hspi->pinSS(), OUTPUT); //HSPI SS



  14. }



  15. // the loop function runs over and over again until power down or reset

  16. void loop() {



  17.   spiCommand(hspi, 0b11001100);



  18.   Serial.print(MISO);Serial.print(" ");

  19.   Serial.print(MOSI);Serial.print(" ");

  20.   Serial.print(SCK);Serial.print(" ");

  21.   Serial.print(SS);Serial.print(" ");

  22.   Serial.print(HSPI);Serial.print(" ");

  23.   Serial.print(FSPI);Serial.print(" ");

  24.   Serial.print(hspi->pinSS());Serial.println(" ");



  25.   delay(2000);

  26. }



  27. void spiCommand(SPIClass *spi, byte data) {

  28.   //use it as you would the regular arduino SPI API

  29.   spi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));

  30.   digitalWrite(spi->pinSS(), LOW); //pull SS slow to prep other end for transfer

  31.   spi->transfer(data);

  32.   digitalWrite(spi->pinSS(), HIGH); //pull ss high to signify end of data transfer

  33.   spi->endTransaction();

  34. }
复制代码


发表于 2021-11-26 21:17 | 显示全部楼层
我最近也准备学下S2的使用
 楼主| 发表于 2021-11-27 18:57 | 显示全部楼层
奈何col 发表于 2021-11-26 21:17
我最近也准备学下S2的使用

S2 主要支持 USB 可玩性大大增强。
发表于 2022-1-10 10:07 | 显示全部楼层
楼主高手  帮了个很大的忙,赞!!
 楼主| 发表于 2022-5-10 16:54 | 显示全部楼层
补充一下,不做任何修改,完全使用默认配置,下面的代码将使用

IO34/35/37/36 分别作为 SS/MOSI/MISO/SCK

static const uint8_t SS    = 34;
static const uint8_t MOSI  = 35;
static const uint8_t MISO  = 37;
static const uint8_t SCK   = 36;

  1. #include <SPI.h>
  2. static const int spiClk = 40000000;
  3. void setup() {
  4.   Serial.begin(115200);
  5.   SPI.begin();
  6. }

  7. void loop() {
  8.   spiCommand(&SPI, 0b11001100);
  9.   Serial.print(MISO);Serial.print(" ");
  10.   Serial.print(MOSI);Serial.print(" ");
  11.   Serial.print(SCK);Serial.print(" ");
  12.   Serial.print(SS);Serial.print(" ");
  13.   Serial.print(HSPI);Serial.print(" ");
  14.   Serial.print(FSPI);Serial.println(" ");

  15.   delay(200);

  16. }



  17. void spiCommand(SPIClass *spi, byte data) {

  18.   //use it as you would the regular arduino SPI API

  19.   spi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));

  20.   digitalWrite(spi->pinSS(), LOW); //pull SS slow to prep other end for transfer

  21.   spi->transfer(data);

  22.   digitalWrite(spi->pinSS(), HIGH); //pull ss high to signify end of data transfer

  23.   spi->endTransaction();

  24. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 09:44 , Processed in 0.198650 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表