最近搞无人车控制,现成带摇杆的高亮高分平板大好几万,不划算,准备自己搞一套。硬件准备采用三防平板+3D打印摇杆手柄,先在某宝上搞一个游戏杆的stm32方案小板,然后搞一下上位机,以前没弄过,网上一搜大多数都是轮询方式实现,由一篇提到了消息机制,看了一下基本上就是照抄了learn.microsoft.com/上joySetCapture()函数的说明,语焉不详且有几处小坑,只能自己总结一下了。
使用游戏杆的方式有好几种,其他的网上多的是不,不说了,仅说一下使用消息的方式:
1、包含#include
2、连接库文件,可以用#pragma comment(lib,"Winmm.lib"),也可以在项目-属性-链接器-常规-输入-附加依赖项里加入Winmm.lib,一样
3、游戏杆消息宏定义
#define MM_JOY1MOVE 0x 3A 0 /* joystick */
#define MM_JOY2MOVE 0x 3A 1
#define MM_JOY1ZMOVE 0x 3A 2
#define MM_JOY2ZMOVE 0x 3A 3
#define MM_JOY1BUTTONDOWN 0x3B5
#define MM_JOY2BUTTONDOWN 0x3B6
#define MM_JOY1BUTTONUP 0x3B7
#define MM_JOY2BUTTONUP 0x3B8
以上知道宏名就行了,不要定义,这个在MMSystem.h里已定义
4、声明消息响应函数
放在消息映射部分,即DECLARE_MESSAGE_MAP()之前
protected:
HICON m_hIcon;
// 生成的消息映射函数
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg LRESULT OnJoystick1Move(WPARAM wParam,LPARAM lParam);//函数名自己定,这个是准备响应摇杆移动消息的
DECLARE_MESSAGE_MAP()
5、实现消息函数
LRESULT CtestDlg:: OnJoystick1Move(WPARAM wParam,LPARAM lParam)
{
static int i=0; //使用静态变量i记录总响应次数,测试用
m_edit1=i++;
m_edit2=wParam;
m_edit3=lParam;
UpdateData(FALSE);
return 0;
}
经实测,传回的参数wParam是按键值,lParam是摇杆值,高16位是Y,低16位是X
6、将消息映射到处理函数
BEGIN_MESSAGE_MAP(CtestDlg, CDialogEx)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDOK, &CtestDlg::OnBnClickedOk)
ON_MESSAGE(MM_JOY1MOVE,OnJoystick1Move) //摇杆移动消息
END_MESSAGE_MAP()
7、绑定游戏杆消息
joySetCapture 函数通过导致其消息发送到指定窗口来捕获游戏杆。具体参数上微软查
实现:
HWND hwnd;
hwnd=this->GetSafeHwnd();
joySetCapture(hwnd, JOYSTICKID1, 10,true);//10是10毫秒,true是值有变化才传递消息,如果是false,按键消息是按下才有,但摇杆是一直有,我理解是按键不按下值为0,但是摇杆中位值在32768左右,所以大于0它就一直有消息,而不像函数文档里说的变化了才发消息。
存在问题:
使用消息响应游戏杆,避免了一直对游戏杆的扫描,但是游戏杆只有摇杆和上下左右四个按钮分别响应MOVE 和BUTTONDOWN消息,其他功能键不发送消息,但在其他消息发送时键值可以传递过来。这个问题感觉也可以通过修改固件来搞,这样就可以完全使用消息来传键值了,反正下一步要搞硬件,正好固件也一起改了。
另外目前使用的是JOYSTICKID1,也就是第一个ID游戏杆,多个的时候怎么枚举还是个问题。
感觉还是使用消息比轮询程序结构化更好,鲁棒性更强。