找回密码
 立即注册
查看: 231|回复: 0

USB-HID 手柄制作(二)

[复制链接]
  • TA的每日心情
    奋斗
    2024-5-5 08:35
  • 签到天数: 143 天

    [LV.7]常住居民III

    29

    主题

    558

    回帖

    2142

    积分

    荣誉版主

    积分
    2142
    发表于 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, 下载次数: 24

    回复 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-5-19 21:34 , Processed in 0.067229 second(s), 33 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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