本帖最后由 zoologist 于 2022-4-16 20:16 编辑  
 
参照Teensy的触摸【参考1】,在 ESP32 S2 上实现了触摸屏。最关键的步骤有2个: 1.     正确的 HID Descriptor,下面是一个10指触摸的触摸屏幕的描述符 
			
			
			- static const uint8_t report_descriptor[] = { // 8 TouchData
 -   0x05, 0x0D,
 -   0x09, 0x04,
 -   0xA1, 0x01,
 -   0x09, 0x22,
 -   0xA1, 0x02,
 -   0x09, 0x42,
 -   0x15, 0x00,
 -   0x25, 0x01,
 -   0x75, 0x01,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x09, 0x30,
 -   0x25, 0x7F,
 -   0x75, 0x07,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x09, 0x51,
 -   0x26, 0xFF, 0x00,
 -   0x75, 0x08,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x05, 0x01,
 -   0x09, 0x30,
 -   0x09, 0x31,
 -   0x26, 0xFF, 0x7F,
 -   0x65, 0x00,
 -   0x75, 0x10,
 -   0x95, 0x02,
 -   0x81, 0x02,
 -   0xC0,
 -   0x05, 0x0D,
 -   0x27, 0xFF, 0xFF, 0x00, 0x00,
 -   0x75, 0x10,
 -   0x95, 0x01,
 -   0x09, 0x56,
 -   0x81, 0x02,
 -   0x09, 0x54,
 -   0x25, 0x0A,
 -   0x75, 0x08,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x05, 0x0D,
 -   0x09, 0x55,
 -   0x25, 0x0A,
 -   0x75, 0x08,
 -   0x95, 0x01,
 -   0xB1, 0x02,
 -   0xC0,
 - };
 
  复制代码
  
对应发送的数据结构是: -     // touch report
 -     //  0: on/off + pressure
 -     //  1: contact id
 -     //  2: X lsb
 -     //  3: X msb
 -     //  4: Y lsb
 -     //  5: Y msb
 -     //  6: scan time lsb
 -     //  7: scan time msb
 - //  8: contact count
 
  复制代码
 其中 Byte0 Bit0 是按下标志,一直为1,Bit1-7 是按键压力;Byte1是按键编号,从 0-255,可以理解为手指编号,比如:右手食指按下,编号为0;右手中指按下,编号为1;右手抬起后再次按下,会重新分配一个编号。Byte2-3按键的X坐标;Byte4-5按键的Y坐标;Byte6-7是按压发生的事件,是以 100us为单位;Byte8是当前正在发生的按压事件中触摸点的数量。在【参考2】有一个例子:  
  
Table 7 Report Sequence for Two Contacts with Separated Lift(Two-Finger Hybrid)  
|    |  |     Report     |     1     |     2     |     3     |     4     |     5     |     6     |     7     |     8     |     9     |     10     |     11     |  |    Contact Count    |    2    |    2    |    2    |    2    |    2    |    2    |    1    |    1    |    1    |    1    |    1    |  |    Contact 1 Tip Switch    |    1    |    1    |    1    |    1    |    1    |    0    |    NR    |    NR    |    NR    |    NR    |    NR    |  |    Contact 1 X,Y    |    X₁,Y₁    |    X₂,Y₂    |    X₃,Y₃    |    X₄,Y₄    |    X₅,Y₅    |    X₅,Y₅    |    NR    |    NR    |    NR    |    NR    |    NR    |  |    Contact 2 Tip Switch    |    1    |    1    |    1    |    1    |    1    |    1    |    1    |    1    |    1    |    1    |    0    |  |    Contact 2 X,Y    |    X₁,Y₁    |    X₂,Y₂    |    X₃,Y₃    |    X₄,Y₄    |    X₅,Y₅    |    X₆,Y₆    |    X₇,Y₇    |    X₈,Y₈    |    X₉,Y₉    |    X₁₀,Y₁₀    |    X₁₀,Y₁₀    |  
  
  图中是2个手指 图中是2个手指进行触摸的例子,R1 会分别报告手指1和2移动的信息,同时 Byte8 的 Contract Count 会等于2;R6的时候,因为手指1已经抬起,所以Contract Count会变成1. .另外一个重要的,容易被忽视的要求:Get Report 的处理。即使上面的描述符正确报告,然后数据也正常发送到Windows中,你的触摸屏依然无法正常工作,原因就是缺少了对Get Report的处理。更糟糕的是:你无法使用 USBlyzer 这样的工具抓到 Teensy 中的数据。   
Teensy 例子中上位机发送 GET_REPORT 收到返回值0x0a 如果不在代码中特别处理,对于这个命令会 STALL  关于这个 COMMAND 的含义,目前没搞清楚【参考3】  
对于我们来说,只要有一个返回值就能让它工作正常。最终一个可以工作的代码如下: - #include "USB.h"
 - #include "USBHID.h"
 - USBHID HID;
 - 
 - static const uint8_t report_descriptor[] = { // 8 TouchData
 -   0x05, 0x0D,
 -   0x09, 0x04,
 -   0xA1, 0x01,
 -   0x09, 0x22,
 -   0xA1, 0x02,
 -   0x09, 0x42,
 -   0x15, 0x00,
 -   0x25, 0x01,
 -   0x75, 0x01,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x09, 0x30,
 -   0x25, 0x7F,
 -   0x75, 0x07,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x09, 0x51,
 -   0x26, 0xFF, 0x00,
 -   0x75, 0x08,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x05, 0x01,
 -   0x09, 0x30,
 -   0x09, 0x31,
 -   0x26, 0xFF, 0x7F,
 -   0x65, 0x00,
 -   0x75, 0x10,
 -   0x95, 0x02,
 -   0x81, 0x02,
 -   0xC0,
 -   0x05, 0x0D,
 -   0x27, 0xFF, 0xFF, 0x00, 0x00,
 -   0x75, 0x10,
 -   0x95, 0x01,
 -   0x09, 0x56,
 -   0x81, 0x02,
 -   0x09, 0x54,
 -   0x25, 0x0A,
 -   0x75, 0x08,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x05, 0x0D,
 -   0x09, 0x55,
 -   0x25, 0x0A,
 -   0x75, 0x08,
 -   0x95, 0x01,
 -   0xB1, 0x02,
 -   0xC0,
 - };
 - 
 - class CustomHIDDevice: public USBHIDDevice {
 -   public:
 -     CustomHIDDevice(void) {
 -       static bool initialized = false;
 -       if (!initialized) {
 -         initialized = true;
 -         HID.addDevice(this, sizeof(report_descriptor));
 -       }
 -     }
 -     uint16_t _onGetFeature(uint8_t report_id, uint8_t* buffer, uint16_t len)
 -       {
 -         buffer[0]=0x0A;
 -         return 0x01;
 -       }
 -     void begin(void) {
 -       HID.begin();
 -     }
 - 
 -     uint16_t _onGetDescriptor(uint8_t* buffer) {
 -       memcpy(buffer, report_descriptor, sizeof(report_descriptor));
 -       return sizeof(report_descriptor);
 -     }
 - 
 -     bool send(uint8_t * value) {
 -       return HID.SendReport(0, value, 9);
 -     }
 - };
 - 
 - CustomHIDDevice Device;
 - 
 - const int buttonPin = 0;
 - int previousButtonState = HIGH;
 - uint8_t TouchData[9];
 - 
 - void setup() {
 -   Serial.begin(115200);
 -   Serial.setDebugOutput(true);
 -   Device.begin();
 -   USB.begin();
 - }
 - 
 - void loop() {
 -   if (HID.ready()) {
 -     Serial.println("Finger");
 -     // touch report
 -     //  0: on/off + pressure
 -     //  1: contact id
 -     //  2: X lsb
 -     //  3: X msb
 -     //  4: Y lsb
 -     //  5: Y msb
 -     //  6: scan time lsb
 -     //  7: scan time msb
 -     //  8: contact count
 -     for (int i=0;i<200;i+=100) {
 -     TouchData[0] = 0x81; TouchData[1] = 0x08;
 -     TouchData[2] = (16000)&0xFF; TouchData[3] = ((16000)>>8)&0xFF;
 -     TouchData[4] = (4000+i)&0xFF; TouchData[5] = ((4000+i)>>8)&0xFF;
 -     TouchData[6] = (millis()*10)&0xFF; TouchData[7] = (millis()*10>>8)&0xFF;
 -     TouchData[8] = 0x01; 
 -     Device.send(TouchData);
 -     delay(10);
 -     TouchData[0] = 0x81; TouchData[1] = 0x08;
 -     TouchData[2] = (16000)&0xFF; TouchData[3] = ((16000)>>8)&0xFF;
 -     TouchData[4] = (4000+i)&0xFF; TouchData[5] = ((4000+i)>>8)&0xFF;
 -     TouchData[6] = (millis()*10)&0xFF; TouchData[7] = (millis()*10>>8)&0xFF;
 -     TouchData[8] = 0x01; 
 -     delay(10);
 -     }
 -     //每隔10秒
 -     delay(5000);
 -   }
 - }
 
  复制代码
  
 
再复杂一点,做一个画圆的:  
 - #include "USB.h"
 - #include "USBHID.h"
 - USBHID HID;
 - 
 - int STARTX=16000;
 - int STARTY=12000;
 - int STARTR=2000;
 - static const uint8_t report_descriptor[] = { // 8 TouchData
 -   0x05, 0x0D,
 -   0x09, 0x04,
 -   0xA1, 0x01,
 -   0x09, 0x22,
 -   0xA1, 0x02,
 -   0x09, 0x42,
 -   0x15, 0x00,
 -   0x25, 0x01,
 -   0x75, 0x01,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x09, 0x30,
 -   0x25, 0x7F,
 -   0x75, 0x07,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x09, 0x51,
 -   0x26, 0xFF, 0x00,
 -   0x75, 0x08,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x05, 0x01,
 -   0x09, 0x30,
 -   0x09, 0x31,
 -   0x26, 0xFF, 0x7F,
 -   0x65, 0x00,
 -   0x75, 0x10,
 -   0x95, 0x02,
 -   0x81, 0x02,
 -   0xC0,
 -   0x05, 0x0D,
 -   0x27, 0xFF, 0xFF, 0x00, 0x00,
 -   0x75, 0x10,
 -   0x95, 0x01,
 -   0x09, 0x56,
 -   0x81, 0x02,
 -   0x09, 0x54,
 -   0x25, 0x0A,
 -   0x75, 0x08,
 -   0x95, 0x01,
 -   0x81, 0x02,
 -   0x05, 0x0D,
 -   0x09, 0x55,
 -   0x25, 0x0A,
 -   0x75, 0x08,
 -   0x95, 0x01,
 -   0xB1, 0x02,
 -   0xC0,
 - };
 - 
 - class CustomHIDDevice: public USBHIDDevice {
 -   public:
 -     CustomHIDDevice(void) {
 -       static bool initialized = false;
 -       if (!initialized) {
 -         initialized = true;
 -         HID.addDevice(this, sizeof(report_descriptor));
 -       }
 -     }
 -     uint16_t _onGetFeature(uint8_t report_id, uint8_t* buffer, uint16_t len)
 -       {
 -         buffer[0]=0x0a;
 -         return 1;
 -       }
 -     void begin(void) {
 -       HID.begin();
 -     }
 - 
 -     uint16_t _onGetDescriptor(uint8_t* buffer) {
 -       memcpy(buffer, report_descriptor, sizeof(report_descriptor));
 -       return sizeof(report_descriptor);
 -     }
 - 
 -     bool send(uint8_t * value) {
 -       return HID.SendReport(0, value, 9);
 -     }
 - };
 - 
 - CustomHIDDevice Device;
 - 
 - const int buttonPin = 0;
 - int previousButtonState = HIGH;
 - uint8_t TouchData[9];
 - 
 - void setup() {
 -   Serial.begin(115200);
 -   Serial.setDebugOutput(true);
 -   Device.begin();
 -   USB.begin();
 - }
 - 
 - void loop() {
 -   if (HID.ready()) {
 -     Serial.println("Finger");
 -     // touch report
 -     //  0: on/off + pressure
 -     //  1: contact id
 -     //  2: X lsb
 -     //  3: X msb
 -     //  4: Y lsb
 -     //  5: Y msb
 -     //  6: scan time lsb
 -     //  7: scan time msb
 -     //  8: contact count
 -     for (int i=0;i<101;i++) {
 -     TouchData[0] = 0x81; TouchData[1] = 0x08;
 -     TouchData[2] = ((int)(STARTX+STARTR*sin(2*PI*i/100)))&0xFF; 
 -     TouchData[3] = ((int)(STARTX+STARTR*sin(2*PI*i/100)))>>8&0xFF;
 -     TouchData[4] = ((int)(STARTY+STARTR*cos(2*PI*i/100)))&0xFF; 
 -     TouchData[5] = ((int)(STARTY+STARTR*cos(2*PI*i/100)))>>8&0xFF;
 -     TouchData[6] = (millis()*10)&0xFF; TouchData[7] = (millis()*10>>8)&0xFF;
 -     TouchData[8] = 0x01; 
 -     Device.send(TouchData);
 -     delay(10);
 -     }
 -     //每隔10秒
 -     delay(5000);
 -     STARTX=STARTX+300;
 -     STARTY=STARTY+300;
 -     
 -   }
 - }
 
  复制代码
 测试结果:  
 视频: 就是这样,不要问这个能干啥, 还没想好。  
 参考:  
 |