关于stm32USB HID触摸屏前面的内容大家可以参考我之前写的两个博客,是一步一步过渡过来的
使用stm32配置自定义的HID设备stm32 USB HID单点触摸屏上报安卓触摸信号
- 使用stm32的usb,配置成HID模式,并上报数据,模拟触摸,在实现完第一个手指的触摸之后实现第二个手指其实也很简单了,主要还是修改HID报告描述符,通过报告描述符告诉接收方你会上报几个手指,对应的该怎么去解析你上报的数据了,因此总结起来,只需要修改两处地方即可,1、修改HID报告描述符;2、修改数据通讯部分上报的数据内容
- 之前我们已经实现了单点触摸,(不会的同学可以看我之前的博客stm32 USB HID单点触摸屏上报安卓触摸信号),我们在此基础上修改,需要注意的是,多点触摸在win7系统上没有用,反正在我电脑上是没用的,需要插到安卓上才有用!
- 修改HID报告描述符
修改HID报告描述符需要根据HID报告描述符的语法格式来修改,并不是随意的修改,如果HID语法出错,下载完程序之后,使用usblyzer去抓数据,在上报完HID描述符之后,就出错了,后面上报的数据均不会响应,因此HID报告描述符必须符合对应的规则,那么具体规则是怎样的呢,我也没找到对应的详细参考,我是看别人的报告描述符,然后看的多了,大概也就懂需要有哪些注意事项了,比如一个COLLECTION必须与End Collection匹配,就像c语言里面的“{”和“}”一样等等,大家实在不懂就去看看别人的吧,看得多了也就大概会了,下面是HID报告描述符出错时usblyzer的情况 - HID描述符没有错误的话,上报数据在usblyzer可以看到
- 这里我就直接把正确的报告描述符丢出来供大家参考
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
//第一个触控点配置
//其实第一个点和第二个点配置基本差不多,主要是在上报数据的时候的第一字节需要注意
//上报数据的第一个字节
//bit7: confidence触摸是否可信 1可信 0不可信(对于安卓不起作用 电脑起作用)
//bit6-bit2: 触控identifice身份指明是哪一个手的触控 注意上报多点触控的时候要不一样!!!
//bit1: Range数据范围 一般为1
//bit0: 按键状态 1按下 0松开
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x04, // USAGE (Touch Screen)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x22, // USAGE (Finger)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x42, // USAGE (Tip Switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x32, // Usage (In Range)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x51, // Usage (Contact Identifier)
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x16, 0x00, 0x00, // Logical Minimum (0)
0x26, 0x10, 0x00, // Logical Maximum (16)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x47, // Usage (Confidence)
0x75, 0x01, // Report Size (1)
0x95, 0x01, // Report Count (1)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0x55, 0x0D, // Unit Exponent (-3)
0x65, 0x33, // Unit (Eng Lin: in^3)
0x35, 0x00, // Physical Minimum (0)
0x46, 0x60, 0x17, // Physical Maximum (5984)
0x26, 0xFF, 0x0F, // Logical Maximum (4095)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x31, // Usage (Y)
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0x55, 0x0D, // Unit Exponent (-3)
0x65, 0x33, // Unit (Eng Lin: in^3)
0x35, 0x00, // Physical Minimum (0)
0x46, 0x26, 0x0E, // Physical Maximum (3622)
0x26, 0xFF, 0x0F, // Logical Maximum (4095)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0xC0, // End Collection
//第二个触控点配置
0x05, 0x0d, // USAGE_PAGE (Digitizers)
0x09, 0x22, // USAGE (Finger)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x42, // USAGE (Tip Switch)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x32, // Usage (In Range)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x51, // Usage (Contact Identifier)
0x75, 0x05, // Report Size (5)
0x95, 0x01, // Report Count (1)
0x16, 0x00, 0x00, // Logical Minimum (0)
0x26, 0x10, 0x00, // Logical Maximum (16)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x47, // Usage (Confidence)
0x75, 0x01, // Report Size (1)
0x95, 0x01, // Report Count (1)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0x55, 0x0D, // Unit Exponent (-3)
0x65, 0x33, // Unit (Eng Lin: in^3)
0x35, 0x00, // Physical Minimum (0)
0x46, 0x60, 0x17, // Physical Maximum (5984)
0x26, 0xFF, 0x0F, // Logical Maximum (4095)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0x09, 0x31, // Usage (Y)
0x75, 0x10, // Report Size (16)
0x95, 0x01, // Report Count (1)
0x55, 0x0D, // Unit Exponent (-3)
0x65, 0x33, // Unit (Eng Lin: in^3)
0x35, 0x00, // Physical Minimum (0)
0x46, 0x26, 0x0E, // Physical Maximum (3622)
0x26, 0xFF, 0x0F, // Logical Maximum (4095)
0x81, 0x02, // Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
0xC0, // End Collection
0xC0, // End Collection
};
根据这个报告描述符上报对应的数据,如果想要让电脑或者安卓正确识别,那么上报的数据肯定是需要遵循HID报告描述符的内容的。
我们上述报告描述符对应的数据格式如下
第1字节:触摸1 标志字节(详见后面描述)
第2字节:触摸1 x坐标的低八位
第3字节:触摸1 x坐标的高八位
第4字节:触摸1 y坐标的低八位
第5字节:触摸1 y坐标的高八位
第6字节: 触摸2 标志字节(详见后面描述)
第7字节: 触摸2 x坐标的低八位
第8字节: 触摸2 x坐标的高八位
第9字节: 触摸2 y坐标的低八位
第10字节:触摸2 y坐标的高八位
标志字节组成:
bit7: confidence触摸是否可信 1可信 0不可信(对于安卓不起作用 电脑起作用)
bit6-bit2: 触控identifice身份指明是哪一个手的触控 注意上报多点触控的时候要不一样!!!
bit1: Range数据范围 一般为1
bit0: 按键状态 1按下 0松开
对应主函数如下
uint16_t x1=0,y1=0;
uint16_t x2=0,y2=0;
uint8_t usb_send_buf[10]={0x83,0xFF,0x03,0xFF,0x03,0x87,0xFF,0x06,0xFF,0x06};
while (1)
{
//计算中心点坐标
x1=4096*1/4-1;
y1=4096*1/4-1;
x2=4096*3/4-1;
y2=4096*3/4-1;
//计算起始坐标
x1=x1-200;
y1=y1-200;
x2=x2+200;
y2=y2+200;
//正方形手势
for(i=0;i<200;i++)
{
x1+=2;
usb_send_buf[0]=0x83;
usb_send_buf[1]=x1%256;
usb_send_buf[2]=x1/256;
usb_send_buf[3]=y1%256;
usb_send_buf[4]=y1/256;
x2-=2;
usb_send_buf[5]=0x87;
usb_send_buf[6]=x2%256;
usb_send_buf[7]=x2/256;
usb_send_buf[8]=y2%256;
usb_send_buf[9]=y2/256;
USBD_HID_SendReport(&hUsbDeviceFS,usb_send_buf,sizeof(usb_send_buf));
HAL_Delay(3);
}
for(i=0;i<200;i++)
{
y1+=2;
usb_send_buf[0]=0x83;
usb_send_buf[1]=x1%256;
usb_send_buf[2]=x1/256;
usb_send_buf[3]=y1%256;
usb_send_buf[4]=y1/256;
y2-=2;
usb_send_buf[5]=0x87;
usb_send_buf[6]=x2%256;
usb_send_buf[7]=x2/256;
usb_send_buf[8]=y2%256;
usb_send_buf[9]=y2/256;
USBD_HID_SendReport(&hUsbDeviceFS,usb_send_buf,sizeof(usb_send_buf));
HAL_Delay(3);
}
for(i=0;i<200;i++)
{
x1-=2;
usb_send_buf[0]=0x83;
usb_send_buf[1]=x1%256;
usb_send_buf[2]=x1/256;
usb_send_buf[3]=y1%256;
usb_send_buf[4]=y1/256;
x2+=2;
usb_send_buf[5]=0x87;
usb_send_buf[6]=x2%256;
usb_send_buf[7]=x2/256;
usb_send_buf[8]=y2%256;
usb_send_buf[9]=y2/256;
USBD_HID_SendReport(&hUsbDeviceFS,usb_send_buf,sizeof(usb_send_buf));
HAL_Delay(3);
}
for(i=0;i<200;i++)
{
y1-=2;
usb_send_buf[0]=0x83;
usb_send_buf[1]=x1%256;
usb_send_buf[2]=x1/256;
usb_send_buf[3]=y1%256;
usb_send_buf[4]=y1/256;
y2+=2;
usb_send_buf[5]=0x87;
usb_send_buf[6]=x2%256;
usb_send_buf[7]=x2/256;
usb_send_buf[8]=y2%256;
usb_send_buf[9]=y2/256;
USBD_HID_SendReport(&hUsbDeviceFS,usb_send_buf,sizeof(usb_send_buf));
HAL_Delay(3);
}
//松开按键
usb_send_buf[0]=0x82;
usb_send_buf[5]=0x86;
USBD_HID_SendReport(&hUsbDeviceFS,usb_send_buf,sizeof(usb_send_buf));
HAL_Delay(7);
}
}
安卓进行相应设置,打开开发者模式,然后打开触摸轨迹,编译下载对应的程序,将设备插在安卓上,可以在安卓上看到对应的触摸轨迹为两个矩形