这次实验在 ESP32 S2 Saola 开发板上使用前面设计的Micro USB Host【参考1】。
首先遇到的问题是:ESP32 S2 的 SPI 在 Arduino 环境下工作不正常(对于这个问题的分析请参阅【参考2】)。为此,我们需要直接修改 位于 C:\Users\用户名\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.1\libraries\SPI\src\SPI.cpp 文件中的如下内容:
#if CONFIG_IDF_TARGET_ESP32
//LabZDebug_Start
#if CONFIG_IDF_TARGET_ESP32S2
SPIClass SPI(HSPI);
#else
SPIClass SPI(VSPI);
#endif
//LabZDebug_End
#else
SPIClass SPI(FSPI);
#endif
接下来修改 USB Host Shield 库文件:
- USB_Host_Shield_Library_2.0\usbhost.h 这个文件有下面3个地方需要修改:
- 1 这里给出用到的 SCK/MISO/MOSI/SS Pin的编号
#elif defined(ESP32)
//LABZDebug typedef SPi< P18, P23, P19, P5 > spi;
//LABZDebug_Start
//SCK MISO MOSI SS
typedef SPi< P10, P21, P19, P13 > spi;
//LABZDebug_End
#elif defined(ARDUINO_NRF52840_FEATHER)
1.2 给出SPI需要引脚编号才能正确的进行SPI初始化:
#elif defined(SPI_HAS_TRANSACTION)
static void init() {
//LABZDebug USB_SPI.begin(); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction()
//LABZDebug_Start
USB_SPI.begin(10,21,19,13); // The SPI library with transaction will take care of setting up the pins - settings is set in beginTransaction()
//LABZDebug_End
SPI_SS::SetDirWrite();
SPI_SS::Set();
}
#elif defined(STM32F4)
1.3 降低速度(Max3421e 最高支持26Mhz, 但是因为 ESP32 无法分频出26M,所以实际上SPI 会以是20M速度工作。但是因为这次实验都是排线,所以频率高了之后会出现通讯错误的问题,为此需要进行降频)到4Mhz。
将文件中
//LABZDebug USB_SPI.beginTransaction(SPISettings(26000000, MSBFIRST, SPI_MODE0)); // The MAX3421E can handle up to 26MHz, use MSB First and SPI mode 0
//LABZDebug_Start
USB_SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
//LABZDebug_End
2.USB_Host_Shield_Library_2.0\UsbCore.h 这里给出用到的SS 和 INT Pin编号
#elif defined(ESP32)
//LABZDebug typedef MAX3421e<P5, P17> MAX3421E; // ESP32 boards
//LABZDebug_Start
// SS INT
typedef MAX3421e<P13, P5> MAX3421E; // ESP32 boards
//LABZDebug_End
#elif (defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__))
typedef MAX3421e<Pb4, Pb3> MAX3421E; // Sanguino
3.USB_Host_Shield_Library_2.0\avrpins.h 这里主要是声明前面用到的PXX 的定义否则编译会出错
MAKE_PIN(P3, 3); // RX0
//LABZDebug_Start
MAKE_PIN(P4, 4); // INT
MAKE_PIN(P13, 13); // CLK
MAKE_PIN(P26, 26); // SS
//LABZDebug_End
MAKE_PIN(P21, 21); // SDA
之后使用 USBHIDBootMouse.ino 进行测试:
#include <hidboot.h>
#include <usbhub.h>
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
class MouseRptParser : public MouseReportParser
{
protected:
void OnMouseMove (MOUSEINFO *mi);
void OnLeftButtonUp (MOUSEINFO *mi);
void OnLeftButtonDown (MOUSEINFO *mi);
void OnRightButtonUp (MOUSEINFO *mi);
void OnRightButtonDown (MOUSEINFO *mi);
void OnMiddleButtonUp (MOUSEINFO *mi);
void OnMiddleButtonDown (MOUSEINFO *mi);
};
void MouseRptParser::OnMouseMove(MOUSEINFO *mi)
{
Serial.print("dx=");
Serial.print(mi->dX, DEC);
Serial.print(" dy=");
Serial.println(mi->dY, DEC);
};
void MouseRptParser::OnLeftButtonUp (MOUSEINFO *mi)
{
Serial.println("L Butt Up");
};
void MouseRptParser::OnLeftButtonDown (MOUSEINFO *mi)
{
Serial.println("L Butt Dn");
};
void MouseRptParser::OnRightButtonUp (MOUSEINFO *mi)
{
Serial.println("R Butt Up");
};
void MouseRptParser::OnRightButtonDown (MOUSEINFO *mi)
{
Serial.println("R Butt Dn");
};
void MouseRptParser::OnMiddleButtonUp (MOUSEINFO *mi)
{
Serial.println("M Butt Up");
};
void MouseRptParser::OnMiddleButtonDown (MOUSEINFO *mi)
{
Serial.println("M Butt Dn");
};
USB Usb;
USBHub Hub(&Usb);
HIDBoot<USB_HID_PROTOCOL_MOUSE> HidMouse(&Usb);
MouseRptParser Prs;
void setup()
{
Serial.begin( 115200 );
#if !defined(__MIPSEL__)
while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
Serial.println("Start");
if (Usb.Init() == -1)
Serial.println("OSC did not start.");
delay( 200 );
HidMouse.SetReportParser(0, &Prs);
}
void loop()
{
Usb.Task();
}
运行结果如下:
关于 USB Host Shield 调试建议如下:
- 首先跑 board_qc.ino 确定SPI 连接是否正确。如果一直有问题,那么是 SPI 不通,需要研究MOSI信号是否正常发送;如果 MOSI/SCLK 都正常但是没有 MOISO 回复,那么请检查 RESET 是否为高;
- 接下来跑USBHIDBootMouse.ino 代码测试,如果有问题,应该是 INT Pin 设置的错误;
- 如果有线鼠标无法使用,那么可以实验无线鼠标,因为前者要求的功耗比较高,可能你从开发板中拉出来的5V供电不足。
参考:
- https://mc.dfrobot.com.cn/thread-312057-1-1.html 做一个Micro USB Host
- https://www.arduino.cn/thread-106240-1-1.html ESP32 S2 的 SPI
2022年5月28日 更新
偶然发现了 ESP32 S2 默认的 SPI 引脚【https://www.arduino.cn/thread-106240-1-1.html】,于是尝试不修改库的情况下直接使用。
硬件连接:
名称 | ESP32 S2 | ESP32 S2 | 名称 | |
INT | IO17 | IO35 | MOSI | |
GND | GND | IO37 | MISO | |
MD- | USB 母头 D- | IO5 | SS | |
MD+ | USB 母头 D+ | IO36 | SCLK | |
VBCOMP | N/A | 3.3V | RESET | |
GND | GND | 3.3V | 3.3V |
运行例子是 USB_Host_Shield_Library_2.0\examples\HID\USBHIDBootMouse
未经修改的 USB Host Shield 库如下: