找回密码
 立即注册
查看: 694|回复: 2

USB-HID 手柄制作(二)

[复制链接]
  • 打卡等级:以坛为家I
  • 打卡总天数:217
  • 最近打卡:2024-11-15 09:12:27

29

主题

722

回帖

2790

积分

荣誉版主

积分
2790
发表于 2023-9-5 07:58:24 | 显示全部楼层 |阅读模式
本帖最后由 gentleman 于 2023-9-5 09:09 编辑

测试视频链接  https://www.bilibili.com/video/B ... 81d40a80ca841a25329

注意本文使用了微软360手柄的PID VID ,仅供交流学习使用。


本文使用设备描述符 等信息均来自互联网



接上回  https://www.stcaimcu.com/forum.php?mod=viewthread&tid=4107




源码已上传附件

  新建 pad.c /.h 文件


新建全局变量手柄键码
  1. BYTE HPadCode = 0x00;
  2. BYTE LPadCode = 0x00;
  3. BYTE LTCode   = 0x00;
  4. BYTE RTCode   = 0x00;
  5. BYTE HLXCode  = 0xf0;
  6. BYTE LLXCode  = 0xf0;
  7. BYTE HLYCode  = 0xf0;
  8. BYTE LLYCode  = 0xf0;
  9. BYTE HRXCode  = 0xf0;
  10. BYTE LRXCode  = 0xf0;
  11. BYTE HRYCode  = 0xf0;
  12. BYTE LRYCode  = 0xf0;
复制代码


空闲状态键码数组 ,待发送键码数组 完整数据数组
  1. BYTE code PadCode_Idle[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff};
  2. BYTE PadCode_Down[12];
  3. BYTE keyPadData[20] = {0x00, 0x14,
  4.                        0x00, // 第一组按键  R  L   SE   ST   RI   LE   DO   UP
  5.                        0x00, // 第二组按键  Y  X   B    A    NOP  ME   RB   LB
  6.                        0x00, // LT
  7.                        0x00, // RT
  8.                        0x00, // LX   双字
  9.                        0xff, // LX2
  10.                        0x00, // LY
  11.                        0xff, // LY2
  12.                        0xff, // RX
  13.                        0xff, // RX2
  14.                        0x00, // RY
  15.                        0x00, // RY2
  16.                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
复制代码
判断按键按下时整理键码,与恢复空闲键码, 增加一个定时器,调用这个函数,此处省略
  1. /// @brief 配置发送的手柄数据
  2. /// @param
  3. void SendPadData(void)
  4. {
  5.     uint i = 0;
  6.     if (!padIdle) {
  7.         P6 = 0x0f;
  8.         PadCode_Down[0]  = HPadCode;
  9.         PadCode_Down[1]  = LPadCode;
  10.         PadCode_Down[2]  = LTCode;
  11.         PadCode_Down[3]  = RTCode;
  12.         PadCode_Down[4]  = HLXCode;
  13.         PadCode_Down[5]  = LLXCode;
  14.         PadCode_Down[6]  = HLYCode;
  15.         PadCode_Down[7]  = LLYCode;
  16.         PadCode_Down[8]  = HRXCode;
  17.         PadCode_Down[9]  = LRXCode;
  18.         PadCode_Down[10] = HRYCode;
  19.         PadCode_Down[11] = LRYCode;
  20.         for (i = 0; i < 12; i++) {
  21.             keyPadData[i + 2] = PadCode_Down[i];
  22.         }
  23.     } else {
  24.         if (SendCnt < 3) {
  25.             SendCnt++;
  26.         } else {
  27.             SendCnt  = 0;
  28.             P6       = 0x3f;
  29.             HPadCode = PadCode_Idle[0];
  30.             LPadCode = PadCode_Idle[1];
  31.             LTCode   = PadCode_Idle[2];
  32.             RTCode   = PadCode_Idle[3];
  33.             HLXCode  = PadCode_Idle[4];
  34.             LLXCode  = PadCode_Idle[5];
  35.             HLYCode  = PadCode_Idle[6];
  36.             LLYCode  = PadCode_Idle[7];
  37.             HRXCode  = PadCode_Idle[8];
  38.             LRXCode  = PadCode_Idle[9];
  39.             HRYCode  = PadCode_Idle[10];
  40.             LRYCode  = PadCode_Idle[11];
  41.             for (i = 0; i < 12; i++) {
  42.                 keyPadData[i + 2] = PadCode_Idle[i];
  43.             }
  44.         }
  45.     }
  46. }
复制代码


再次修改usb_class_in(), 修改矩阵键盘相应,分别对应 A  B  X  Y  与左轴的上下左右


注意摇杆是双字节有符号数  负方向移动需要使用补码  -65536 补码为  0x8000  最高位符号位为1
  1. void usb_class_in()
  2. {
  3.     if (DeviceState != DEVSTATE_CONFIGURED)
  4.         return;
  5.     if (!UsbInBusy && fKeyOK) {
  6.         fKeyOK = 0;
  7.         padIdle = 0;
  8.         switch (bKeyCode) {
  9.             case 0xfe:
  10.                 LPadCode |= ADOWN;
  11.                 break;
  12.             case 0xfd:
  13.                 LPadCode |= BDOWN;
  14.                 break;
  15.             case 0xfb:
  16.                 LPadCode |= XDOWN;
  17.                 break;
  18.             case 0xf7:
  19.                 LPadCode |= YDOWN;
  20.                 break;
  21.             case 0xef:
  22.                 HLXCode = 0x00;
  23.                 LLXCode = 0x80;
  24.                 break;
  25.             case 0xdf:
  26.                 HLXCode = 0xff;
  27.                 LLXCode = 0x7f;
  28.                 break;
  29.             case 0xbf:
  30.                 HLYCode = 0x00;
  31.                 LLYCode = 0x80;
  32.                 break;
  33.             case 0x7f:
  34.                 HLYCode = 0xff;
  35.                 LLYCode = 0x7f;
  36.                 // IAP_CONTR = 0x60;
  37.                 break;
  38.             case 0xff:
  39.                 padIdle = 1;
  40.                 break;
  41.         }
  42.     }
  43.     if (!UsbInBusy) {
  44.         UsbInBusy = 1;
  45.         IE2 &= ~0x80; // EUSB = 0;
  46.         usb_write_reg(INDEX, 1);
  47.         usb_write_fifo(FIFO1, keyPadData, 20);
  48.         usb_write_reg(INCSR1, INIPRDY);
  49.         IE2 |= 0x80; // EUSB = 1;
  50.     }
  51. }
复制代码


steam 测试手柄工具     测试结果
截图202309050736518009.jpg    截图202309050737138798.jpg 截图202309050737537060.jpg    截图202309050738181497.jpg



截图202309050738508202.jpg    截图202309050739154359.jpg


后面的计划是
      购买手柄需要的摇杆(电位器),增加adc 读取摇杆值,8个矩阵按键不够,可能会使用独立按键/AD按键
      
      现在的(精英)手柄一般都有背键,好像能自己设置。后面再研究一下是咋整的。








HID 手柄阶段2.7z

104.85 KB, 下载次数: 97

回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:521
  • 最近打卡:2025-05-02 09:38:13

109

主题

1900

回帖

5214

积分

论坛元老

积分
5214
发表于 2024-6-27 08:50:21 | 显示全部楼层
得下载来学习学习,感谢分享!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:447
  • 最近打卡:2025-04-30 11:36:47

7

主题

64

回帖

659

积分

高级会员

积分
659
发表于 2024-6-27 09:24:53 | 显示全部楼层
矩阵键盘可以支持组合按键吗?比如A+B,游戏里常常用到。
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-3 03:01 , Processed in 0.110821 second(s), 65 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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