描述
<p><strong>在报名阶段填写 ↓</strong></p>
<p> </p>
<p><strong>* 1</strong><strong>、项目功能介绍</strong></p>
<div align="center"><hr align="center" width="100%"></div>
<p> 相比电脑游戏,手机手机更加灵活,对于设备的要求也会更小,加之现在通讯技术发达,随时对地都能进行游戏,因此,手机游戏日益火爆。</p>
<p>这次制作的就是一个将键盘鼠标转化为USB触摸进行游戏的设备。能够将键盘的 WASD 模拟为手指按键控制方向,然后鼠标移动映射为视角的变化,鼠标左键是开火,右键是打开瞄准镜。</p>
<p> </p>
<p><strong>*2</strong><strong>、项目属性</strong></p>
<div align="center"><hr align="center" width="100%"></div>
<p>原创,首次公开</p>
<p> </p>
<p><strong>* 3</strong><strong>、开源协议</strong></p>
<div align="center"><hr align="center" width="100%"></div>
<p><strong>LGPL</strong></p>
<p> </p>
<p> </p>
<p><strong>请在竞赛阶段填写 ↓</strong></p>
<p> </p>
<p><strong>*4</strong><strong>、硬件部分</strong></p>
<div align="center"><hr align="center" width="100%"></div>
<p>1. WCH 的 CH9350 芯片,这是一款能够接收并且解析USB HID 设备数据,然后转为串口输出的芯片。具有使用简单,兼容性强,外围元件简单的特点。它在设个项目中负责转出两个 USB Host 接口,分别连接键盘和鼠标,获得数据会从串口输出;</p>
<p>2. ESP32 S3 芯片,这款芯片自身带有 USB Device,我们通过编程的方式让它模拟为一个USB触摸屏,连接到手机之后,通过模拟触摸动作来实现我们需要的操作。</p>
<p> </p>
<p><strong>*5</strong><strong>、软件部分</strong></p>
<div align="center"><hr align="center" width="100%"></div>
<p>代码使用 Arduino 开发。基本的数据结构是:设计一个环形队列用于存放触摸操作。比如,当有 w 按键时,分析串口数据后会将一个手指的按键信息放入这个队列中。然后每隔50ms会进行队列检测,如果有按键信息,那么就按照要求发送触摸信息给手机。</p>
<p> </p>
<p>1.首先使用如下的描述符即可将 ESP32 S3 模拟为 USB 触摸屏</p>
<p> </p>
<p>static const uint8_t report_descriptor[] = { // 8 TouchData<br> 0x05, 0x0D, // Usage Page (Digitizer)<br> 0x09, 0x04, // Usage (Touch Screen)<br> 0xA1, 0x01, // Collection (Application)<br> 0x09, 0x22, // Usage (Finger)<br> 0xA1, 0x02, // Collection (Logical)<br> 0x09, 0x42, // Usage (Tip Switch)<br> 0x15, 0x00, // Logical Minimum (0)<br> 0x25, 0x01, // Logical Maximum (1)<br> 0x75, 0x01, // Report Size (1)<br> 0x95, 0x01, // Report Count (1)<br> 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)<br> 0x09, 0x30, // Usage (Tip Pressure)<br> 0x25, 0x7F, // Logical Maximum (127)<br> 0x75, 0x07, // Report Size (7)<br> 0x95, 0x01, // Report Count (1)<br> 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)<br> 0x09, 0x51, // Usage (0x51)<br> 0x26, 0xFF, 0x00, // Logical Maximum (255)<br> 0x75, 0x08, // Report Size (8)<br> 0x95, 0x01, // Report Count (1)<br> 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)<br> 0x05, 0x01, // Usage Page (Generic Desktop Ctrls)<br> 0x16, 0x00, 0x00, //HID_LogicalMinS (0)<br> 0x26, 0xB0, 0x04,// LOGICAL_MAXIMUM (1366)<br> 0x46, 0xB0, 0x04,// PHYSICAL_MAXIMUM (1366)<br> 0x75, 0x10,// REPORT_SIZE (16)<br> 0x55, 0x00,// UNIT_EXPONENT (0)<br> 0x65, 0x00,// UNIT (00)<br> 0x09, 0x30,// USAGE (X)<br> 0x36, 0x00, 0x00, // PHYSICAL_MINIMUM (0)<br> 0x46, 0x56, 0x05,// PHYSICAL_MAXIMUM (1366)<br> 0x95, 0x01,// REPORT_COUNT (1)<br> 0x81, 0x02,// INPUT (Data,Var,Abs)<br> 0x26, 0x68, 0x0A,// LOGICAL_MAXIMUM (2664)<br> 0x46, 0x68, 0x0A,// PHYSICAL_MAXIMUM (2664)<br> 0x09, 0x31,// USAGE (Y)<br> 0x81, 0x02,// INPUT (Data,Var,Abs)<br> 0xC0, // End Collection<br> 0x05, 0x0D, // Usage Page (Digitizer)<br> 0x27, 0xFF, 0xFF, 0x00, 0x00, // Logical Maximum (65534)<br> 0x75, 0x10, // Report Size (16)<br> 0x95, 0x01, // Report Count (1)<br> 0x09, 0x56, // Usage (0x56)<br> 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)<br> 0x09, 0x54, // Usage (0x54)<br> 0x25, 0x0A, // Logical Maximum (10)<br> 0x75, 0x08, // Report Size (8)<br> 0x95, 0x01, // Report Count (1)<br> 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)<br> 0x05, 0x0D, // Usage Page (Digitizer)<br> 0x09, 0x55, // Usage (0x55)<br> 0x25, 0x0A, // Logical Maximum (10)<br> 0x75, 0x08, // Report Size (8)<br> 0x95, 0x01, // Report Count (1)<br> 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)<br> 0xC0, // End Collection<br> // 99 bytes<br>};</p>
<p> </p>
<p>2.定义一个存放触摸数据的队列:</p>
<p> </p>
<p>typedef struct {<br> uint8_t pressure;<br> uint8_t finger;<br> uint16_t x;<br> uint16_t y;<br>} TouchScreen;</p>
<p>#define CQLENTH 200<br>TouchScreen TouchQC[CQLENTH];</p>
<p> </p>
<p>3.处理键盘按键,比如,按下 W 键,那么就对触摸数据队列插入一个按键信息。</p>
<p> </p>
<p> if (((KeyPressFlag & KEY_W) != 0) && ((LastKeyPressFlag & KEY_W) == 0)) { //当前按下 W 键<br> ts = { 0x81, FINGER0, FINGER0_ORG_X + 170, FINGER0_ORG_Y};<br> SetToCircularQueue(ts);<br> }</p>
<p> </p>
<p>4.循环处理触摸队列,根据队列发送按下或者抬起的动作</p>
<p> </p>
<p> // 每隔50ms处理一次,如果间隔太低游戏不会响应<br> if (millis() - Elsp > 50) {<br> int tsIndex = GetToCircularQueue();<br> if (tsIndex != 0xFF) {<br> Serial.print("Send Data, Index:");<br> Serial.println(tsIndex);</p>
<p> //如果当前是按压事件<br> if (TouchQC[tsIndex].pressure == 0x81) {</p>
<p> if ((FingerFlag & (1 << TouchQC[tsIndex].finger)) == 0) {<br> PressedFingerNumber++;<br> }<br> FingerFlag = FingerFlag | (1 << TouchQC[tsIndex].finger);<br> } else {<br> // 抬起事件<br> PressedFingerNumber--;<br> FingerFlag = FingerFlag & (~(1 << TouchQC[tsIndex].finger));<br> }<br> if (HID.ready()) {<br> TouchData[0] = TouchQC[tsIndex].pressure;<br> TouchData[1] = TouchQC[tsIndex].finger;<br> TouchData[2] = TouchQC[tsIndex].x & 0xFF;<br> TouchData[3] = (TouchQC[tsIndex].x) >> 8 & 0xFF;<br> TouchData[4] = TouchQC[tsIndex].y & 0xFF;<br> TouchData[5] = (TouchQC[tsIndex].y) >> 8 & 0xFF;<br> TouchData[6] = millis() & 0xFF; TouchData[7] = (millis() >> 8) & 0xFF;<br> TouchData[8] = PressedFingerNumber;<br> Device.send(TouchData);<br> }<br> ShowBuffer((char *)TouchData, 9);<br> Elsp = millis();<br> }</p>
<p><strong>*6</strong><strong>、BOM</strong><strong>清单</strong></p>
<div align="center"><hr align="center" width="100%"></div>
<p>请输入内容…</p>
<p> </p>
<p>注:项目涉及的BOM清单。在<u><a href="https://lceda.cn/editor" target="_blank">嘉立创EDA</a> </u>生成/上传设计文件后,BOM将自动生成至项目详情;建议包括型号、品牌、名称、封装、采购渠道、用途等内容。具体内容和形式应以表达清楚项目构成为准。</p>
<p> </p>
<p><strong>*7</strong><strong>、大赛LOGO</strong><strong>验证</strong></p>
<div align="center"><hr align="center" width="100%"></div>
<p> </p>
<p><img src="//image.lceda.cn/pullimage/YdG3r25cmnRkWJuzbHAPY9qtoAYrt5DedRBGTxCA.png" alt="" width="573" height="600"></p>
<p> </p>
<p><strong>* 8</strong><strong>、演示您的项目并录制成视频上传</strong></p>
<div align="center"><hr align="center" width="100%"></div>
<p> </p>
<p>视频要求:请横屏拍摄,分辨率不低于1280×720,格式Mp4/Mov,单个视频大小限100M内;</p>
<p>视频标题:立创电赛:{项目名称}-{视频模块名称};如立创电赛:《自动驾驶》-团队介绍。</p>
<p> </p>
<p><a href="/posts/de460543d4cf4dacb5f0326612455578" target="_blank">前往查看更多详情 ></a></p>
<p> </p>
<p> </p>
评论(1)