此工程在个人博客使用stm32配置自定义的HID设备基础上修改
每次当我们触摸时都会上报ID为4的数据,且松开的时候上报的数据内容第二个字节由0x83变为了0x82
也就是第二个字节的第一位1->0
那么我们只需要借鉴其HID描述符中id为4 的那一部分就可以了,也就是下面这一部分
同时,我们去掉中间那一部分没有用的,从触摸时上报的数据解析中看到的那个in Range 、confidence和contact identifier
我也不清楚这三个是干嘛的,直接用常量替换掉,同时需要注意的是,按键有效的只有第一位,那么需要构成一个字节,所以还需要补充7位常量,然后后面再跟上x,y的坐标值就好了,那么我们参考id为04的hid描述符,自己使用hid descriptor tool工具制作一个hid描述符如下所示
char ReportDescriptor[68] = {
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)
0x75, 0x07, // REPORT_SIZE (7)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x0f, // LOGICAL_MAXIMUM (4095)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x0f, // PHYSICAL_MAXIMUM (4095)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x31, // USAGE (Y)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x10, // REPORT_SIZE (16)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x0f, // LOGICAL_MAXIMUM (4095)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x0f, // PHYSICAL_MAXIMUM (4095)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
};
然后将生成的hid描述符替换掉以前的hid描述符,记得修改hid描述符数组的大小值
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
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)
0x75, 0x07, // REPORT_SIZE (7)
0x95, 0x01, // REPORT_COUNT (1)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x01, // REPORT_COUNT (1)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x0f, // LOGICAL_MAXIMUM (4095)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x0f, // PHYSICAL_MAXIMUM (4095)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x09, 0x31, // USAGE (Y)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x10, // REPORT_SIZE (16)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x0f, // LOGICAL_MAXIMUM (4095)
0x35, 0x00, // PHYSICAL_MINIMUM (0)
0x46, 0xff, 0x0f, // PHYSICAL_MAXIMUM (4095)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
0xc0 // END_COLLECTION
}
然后在主程序中调用上报数据的api函数就可以了,
上报的内容第一个字节是0x01或者0x00,0x01代表按键有效
上报数据的2-3字节书x坐标
上报数据的4-5字节书y坐标
记得每次上报完按键按下之后需要上报一次按键未按下作为结束
uint8_t usb_send_buf[5]={0x01,0xA8,0x0A,0x6B,0x0A};
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
usb_send_buf[0]=0x01;
for(i=0;i<64;i++)
{
usb_send_buf[1]=(((usb_send_buf[2]<<8)|usb_send_buf[1])-1)%256;
usb_send_buf[2]=(((usb_send_buf[2]<<8)|usb_send_buf[1])-1)/256;
USBD_HID_SendReport(&hUsbDeviceFS,usb_send_buf,sizeof(usb_send_buf));
HAL_Delay(7); //必须要有短暂的延时 1ms都行
}
usb_send_buf[0]=0x00;
USBD_HID_SendReport(&hUsbDeviceFS,usb_send_buf,sizeof(usb_send_buf));
usb_send_buf[1]=0xA8;
usb_send_buf[2]=0x0A;
HAL_Delay(1000);
}
/* USER CODE END 3 */
}
烧录程序,之后大家可以 打开福昕pdf,随便开一个pdf,然后使用pdf的注释里面的画笔功能,之后别动鼠标(动鼠标会干扰usb模拟鼠标),然后可以看到每隔1s,鼠标会自己画一条横线
6.至此,stm32制作的触摸屏在电脑上已经可以使用了,但是如果插到安卓设备上,大家会发现,安卓上会出现一个鼠标图标,这是因为安卓根据设备符认为这是一个鼠标设备,但是我们想做的是一个触摸设备,我通过尝试修改HID描述符将USAGE改成Finger
重新烧录,在电脑上依旧可以使用,插上安卓,发现鼠标图标没有了,有触摸效果,但是感觉它摸的不正常,这肯定是不行的,没办法,那就直接拷贝我手上成品触摸屏的id为4的那部分HID设备描述符吧,即下图中我选中的部分,注意的是由于我们这只有一个hid描述,不需要id,所以大家把id那个删掉就好了
修改过的HID描述符
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
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,
0x15 , 0x00 ,
0x25 , 0x01 ,
0x81 , 0x02 ,
0x09 , 0x51 ,
0x75 , 0x05,
0x95 , 0x01 ,
0x16 , 0x00 , 0x00,
0x26 , 0x10 , 0x00,
0x81 , 0x02,
0x09 , 0x47 ,
0x75 , 0x01,
0x95 , 0x01 ,
0x15 , 0x00,
0x25 , 0x01 ,
0x81 , 0x02 ,
0x05 , 0x01 ,
0x09 , 0x30 ,
0x75 , 0x10 ,
0x95 , 0x01 ,
0x55 , 0x0D,
0x65 , 0x33,
0x35 , 0x00,
0x46 , 0x60 , 0x17 ,
0x26 , 0xFF , 0x0F ,
0x81 , 0x02 ,
0x09 , 0x31 ,
0x75 , 0x10 ,
0x95 , 0x01 ,
0x55 , 0x0D ,
0x65 , 0x33 ,
0x35 , 0x00 ,
0x46 , 0x26 , 0x0E,
0x26 , 0xFF , 0x0F ,
0x81 , 0x02 ,
0x05 , 0x0D ,
0x09 , 0x55 ,
0x25 , 0x08 ,
0x75 , 0x08 ,
0x95 , 0x01 ,
0xB1 , 0x02 ,
0xC0 ,
0xC0 ,
// 0x75, 0x07, // REPORT_SIZE (7)
// 0x95, 0x01, // REPORT_COUNT (1)
// 0x81, 0x03, // INPUT (Cnst,Var,Abs)
// 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
// 0x09, 0x30, // USAGE (X)
// 0x75, 0x10, // REPORT_SIZE (16)
// 0x95, 0x01, // REPORT_COUNT (1)
// 0x15, 0x00, // LOGICAL_MINIMUM (0)
// 0x26, 0xff, 0x0f, // LOGICAL_MAXIMUM (4095)
// 0x35, 0x00, // PHYSICAL_MINIMUM (0)
// 0x46, 0xff, 0x0f, // PHYSICAL_MAXIMUM (4095)
// 0x81, 0x02, // INPUT (Data,Var,Abs)
// 0x09, 0x31, // USAGE (Y)
// 0x95, 0x01, // REPORT_COUNT (1)
// 0x75, 0x10, // REPORT_SIZE (16)
// 0x15, 0x00, // LOGICAL_MINIMUM (0)
// 0x26, 0xff, 0x0f, // LOGICAL_MAXIMUM (4095)
// 0x35, 0x00, // PHYSICAL_MINIMUM (0)
// 0x46, 0xff, 0x0f, // PHYSICAL_MAXIMUM (4095)
// 0x81, 0x02, // INPUT (Data,Var,Abs)
// 0xc0, // END_COLLECTION
// 0xc0 // END_COLLECTION
};
然后主函数依旧上报触摸数据,借鉴之前触摸板上报的,注意的是成品触摸板上报的时候,第一个字节是ID0x04,我们直接去掉这一个字符就好了,
usb_send_buf[0]=0x83;
usb_send_buf[1]=0xB0;usb_send_buf[2]=0x08;
usb_send_buf[3]=0x8c;usb_send_buf[4]=0x0B;
USBD_HID_SendReport(&hUsbDeviceFS,usb_send_buf,sizeof(usb_send_buf));
HAL_Delay(7);
usb_send_buf[0]=0x83;
usb_send_buf[1]=0xAB;usb_send_buf[2]=0x07;
usb_send_buf[3]=0x07;usb_send_buf[4]=0x07;
USBD_HID_SendReport(&hUsbDeviceFS,usb_send_buf,sizeof(usb_send_buf));
HAL_Delay(7);
usb_send_buf[0]=0x82;
usb_send_buf[1]=0xAB;usb_send_buf[2]=0x07;
usb_send_buf[3]=0x07;usb_send_buf[4]=0x07;
USBD_HID_SendReport(&hUsbDeviceFS,usb_send_buf,sizeof(usb_send_buf));
HAL_Delay(7);
HAL_Delay(1000);
下载测试,发现电脑和安卓上都都可以用了!
那么触摸的时候具体是触摸在哪一个位置呢?
根据设备描述符我们可以知道x的 最小值为0 最大值为4095,y的 最小值为0 最大值为4095
那么通过程序测试我们发现,(0,0)为电脑屏幕的左上角,(4095,4095)为屏幕的右下角
工程链接:工程链接