【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        喜欢玩游戏的朋友,肯定对游戏手柄不陌生。特别是喜欢玩xbox、switch的朋友,很多的游戏都是需要游戏手柄的参与。但是除了游戏之外,有一些应用开发也是可以通过游戏手柄来完成的。比如说有一些嵌入式设备,按键还没有是配合好,这个时候就可以通过上位机读取游戏手柄的信息,借助于串口发给嵌入式手柄即可。

1、购买支持xbox的游戏手柄

        一般在电商网站输入xbox即可。

2、手柄+接收器

        本身游戏手柄是单独一个设备,而接收器是插在电脑上面的。如果两者配对没有问题,那么接收器就会被windows识别成一个hid设备。而hid设备是免驱的,这一点和cdc设备是一样的。也就是说,电脑插入接收器之后,我们在设备管理器-》人体学输入设备那边看到了新的节点,这个时候就默认驱动ok了。

        手柄和接收器的通信模式很多,一般选择2.4g模式即可,不用选其他方式。

3、编写代码

        编写代码的时候主要参考xinput这个库,使用的是XInputGetState这个函数。当然,不会写的话,可以通过ai来写,这也是可以的。

#include <Windows.h>
#include <Xinput.h>
#include <iostream>

#pragma comment(lib, "xinput.lib")

int main()
{
    while (true)
    {
        XINPUT_STATE state;
        ZeroMemory(&state, sizeof(XINPUT_STATE));

        DWORD result = XInputGetState(0, &state);

        if (result == ERROR_SUCCESS)
        {
            // stick

            SHORT lx = state.Gamepad.sThumbLX;
            SHORT ly = state.Gamepad.sThumbLY;

            SHORT rx = state.Gamepad.sThumbRX;
            SHORT ry = state.Gamepad.sThumbRY;

            // key

            WORD buttons = state.Gamepad.wButtons;

            std::cout << "LX:" << lx
                << " LY:" << ly
                << " RX:" << rx
                << " RY:" << ry
                << " Buttons:" << buttons
                << "\n";
        }
        else
        {
            std::cout << "No controller connected        \r";
        }

        Sleep(20);
    }

    return 0;
}

4、测试与验证

        通过代码可以看出来,这是一个循环读取的工作。编译成功之后就可以开始运。比如说,开始操作左边的摇杆、右边的摇杆,按下对应的按钮,看看有没有对应的输出。不管是摇杆,还是按键,将来这些输入信息都可以为我们所用的。

        另外部分手柄虽然是hid设备,但是不支持xinput库,这种情况下只能用hid来读取报文了。在linux上,也是用hid的方法来处理。

注1:

        这类设备本质上都是usb hid设备,所以如果mcu的usb有host功能,其实就可以借助于host+hid识别的能力,读取无线手柄的接收器数据,从而可以达到远程遥控的目的。这一点wch系列的mcu产品很有优势。

注2:

        市面上也有用NRF24L01+做的无线手柄,即手柄和接收器上面各一个NRF24L01+模块。手柄的话,基本找两个7号电池就可以,关键是接收器。我们这里用了8051单片机,即stc89c52rc来连接,之前板子的信号是这样的,

        这里为了串口输出,做了修改,主要是10和11换成了20和21。电压的话,选3.3v即可,IRQ不连接。

#define NRF24L01_GPIO_CE               P20
#define NRF24L01_GPIO_CSN              P21

#define NRF24L01_GPIO_SCLK             P12
#define NRF24L01_GPIO_MOSI             P13
#define NRF24L01_GPIO_MISO             P14

        剩下来的就是main.c做了修改,主要就是做了打印处理。这样带有四个按键和两个摇杆的无线手柄,就可以通过串口输出数据了,

#include <reg52.h>
#include <stdio.h>
#include "hu_m40.h"

unsigned int cnt = 0;
 
void delay_ms(unsigned int ms)
{
  unsigned int i, j;
  for (i = 0; i < ms; i++)
    for (j = 0; j < 125; j++);  // Approximately 1ms at 12MHz
}
 
void UART_Init(void)
{
  TMOD = 0x20;        // Timer1, mode 2 (8-bit auto-reload)
  TH1 = 0xFD;         // Baud rate 9600 (11.0592MHz crystal)
  TL1 = 0xFD;
  TR1 = 1;            // Start timer1
  SCON = 0x50;        // Serial mode 1 (8-bit UART), enable reception
  TI = 1;             // Set transmit flag to allow printf output
}

void main()   
{
  hu_m40_init();
  UART_Init();
  
  while(1)
  {
    if (hu_m40_read() == 1)
    {
      // get data
      uint8_t ly = hu_m40_analog(HU_LY);
      uint8_t lx = hu_m40_analog(HU_LX);
      uint8_t ry = hu_m40_analog(HU_RY);
      uint8_t rx = hu_m40_analog(HU_RX);
      
      if (hu_m40_button(HU_K1))  // K1
      {
         printf("111\n");
      }
      if (hu_m40_button(HU_K2))  // K2
      {
        printf("222\n");
      }
      if (hu_m40_button(HU_K3))  // K3
      {
        printf("333\n");
      }
      if (hu_m40_button(HU_K4))  // K4
      {
        printf("444\n");
      }
			
	  printf("lx = %u\n", (unsigned int)lx);
	  printf("ly = %u\n", (unsigned int)ly);
	  printf("rx = %u\n", (unsigned int)rx);
	  printf("ry = %u\n", (unsigned int)ry);
	  delay_ms(100);
    }
  }
}

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐