esp32开发与应用(题外话之无线手柄操控)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱: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);
}
}
}
更多推荐


所有评论(0)