基于RISC-V CH32V103的鼠标键盘摇杆手柄Joystick学习开发板–实例Eg2_Mouse
3.2 实例Eg2_Mouse
本节我们目标是实现模拟鼠标的功能,枚举一个具有XY,左右中键以及滚轮上下的功能;
3.2.1硬件设计
同上一章节
3.2.2 软件设计
在上一章节的基础上,我们在USB_DevTransProcess中找到报告描述符的获取,并修改为如下内容
case USB_DESCR_TYP_REPORT:
if(((pSetupReqPak->wIndex)&0xff) == 0) //接口0报表描述符
{
pDescr = MouseRepDesc; //数据准备上传
len = sizeof(MouseRepDesc);
Ready = 1; //如果有更多接口,该标准位应该在最后一个接口配置完成后有效
}
else len = 0xff; //本程序只有2个接口,这句话正常不可能执行
break;
另外鼠标的报告描述符MouseRepDesc如下
const UINT8 MouseRepDesc[]=
{
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x38, // USAGE (Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
然后是报文数据的处理如下:
//处理并上报数据
void Gp_SendReport(void)
{
memset(Joystick_Buf,0,4);
Ytemp=ADC_ConvertedValue[0];
Xtemp=ADC_ConvertedValue[1];
if(Xtemp>Xmax)
Xtemp=Xmax;
if(Xtemp<Xmin)
Xtemp=Xmin;
if(Ytemp>=Ymax)
Ytemp=Ymax;
if(Ytemp<=Ymin)
Ytemp=Ymin;
printf("Xmax=%x,Xcen=%x,Xmin=%x\r\n",Xmax,Xtemp,Xmin);
printf("Ymax=%x,Ycen=%x,Ymin=%x\r\n",Ymax,Ytemp,Ymin);
//根据坐标极点确定坐标(两点直线方程)
X=((Xtemp-Xmin)*255)/(Xmax-Xmin);
Y=((Ytemp-Ymin)*255)/(Ymax-Ymin);
if(X>(X_BASE+20))
{
Joystick_Buf[1]=((X-X_BASE)>>DIV)+1;
}
if(X<(X_BASE-20))
{
Joystick_Buf[1]=(u8)-(((X_BASE-X)>>DIV)+1);
}
if(Y>(Y_BASE+20))
{
Joystick_Buf[2]=((Y-Y_BASE)>>DIV)+1;;;
}
if(Y<(Y_BASE-20))
{
Joystick_Buf[2]=(u8)-(((Y_BASE-Y)>>DIV)+1);
}
Key_Handle(Joystick_Buf);
Delay_Ms(5);
while( Endp1Busy )
{
; //如果忙(上一包数据没有传上去),则等待。
}
Endp1Busy = 1; //设置为忙状态
memcpy(pEP1_IN_DataBuf, Joystick_Buf, 4);
DevEP1_IN_Deal(4);
}
其中X_BASE为摇杆中点, if(X>(X_BASE+20))就是摇杆左摇动;故而((X-X_BASE)>>DIV)+1计算赋值给我们我们X+坐标;
其他方向同理,
另外Key_Handle的代码如下,主要是为了处理按键与滚轮值
void Key_Handle(uint8_t* kv)
{
if((LFKEY)==Bit_RESET)
{
kv[0]|=0x01;
}
if((RGKEY)==Bit_RESET)
{
kv[0]|=0x02;
}
if(SW1!=Bit_RESET)
{
kv[0]|=0x04;
}
if((UPKEY)==Bit_RESET)
{
if(c_tick++>5)
{
kv[3]=1;
c_tick=0;
}
}
if((DNKEY)==Bit_RESET)
{
if(c_tick++>5)
{
kv[3]=(u8)-1;
c_tick=0;
}
}
}
3.2.3 下载验证
我们把固件程序下载进去可以,打开“设备与打印机”可以看到USB设备枚举成了一个“LD Mouse”,如下图。
我们打开一个网页,摇动摇杆鼠标指针跟着动;右边上下左右键,左右代表鼠标左右键,上下代表滚轮;然后摇杆中键代表鼠标中键;