STM32模拟USB多点触控屏
开发准备
- STM32的USB官方例程库JoyStickMouse
- STM32F103RC
- Windows7
代码修改
1.usb_pwr.c
RESULT PowerOn(void)
{u16 wRegVal; //USB_Cable_Config(ENABLE);//这里由于硬件问题用不到,注释/*** CNTR_PWDN = 0 ***/wRegVal = CNTR_FRES;_SetCNTR(wRegVal); /*** CNTR_FRES = 0 ***/wInterrupt_Mask = 0;_SetCNTR(wInterrupt_Mask);/*** Clear pending interrupts ***/_SetISTR(0);/*** Set interrupt mask ***/wInterrupt_Mask = CNTR_RESETM | CNTR_SUSPM | CNTR_WKUPM;_SetCNTR(wInterrupt_Mask); return USB_SUCCESS;
}
2.usb_proc.c
void Joystick_Reset(void)
{/* Set Joystick_DEVICE as not configured */pInformation->Current_Configuration = 0;pInformation->Current_Interface = 0;/* the default Interface *//* Current Feature initialization */pInformation->Current_Feature = Joystick_ConfigDescriptor[7];SetBTABLE(BTABLE_ADDRESS);/* Initialize Endpoint 0 */SetEPType(ENDP0, EP_CONTROL);SetEPTxStatus(ENDP0, EP_TX_STALL);SetEPRxAddr(ENDP0, ENDP0_RXADDR);SetEPTxAddr(ENDP0, ENDP0_TXADDR);Clear_Status_Out(ENDP0);SetEPRxCount(ENDP0, Device_Property.MaxPacketSize);SetEPRxValid(ENDP0);/* Initialize Endpoint In 1 */SetEPType(ENDP1, EP_INTERRUPT); //初始化为中断端点类型SetEPTxAddr(ENDP1, ENDP1_TXADDR); //设置发送数据的地址SetEPTxCount(ENDP1, 14); //设置发送的长度,这里由于使用的两点触控的触控屏需要发送的数据为14Bytes一次SetEPTxStatus(ENDP1, EP_TX_NAK); //设置端点处于忙状态/* Initialize Endpoint Out 1 */SetEPRxAddr(ENDP1, ENDP1_RXADDR); //设置接收数据的地址SetEPRxCount(ENDP1, 2); //设置接收长度SetEPRxStatus(ENDP1, EP_RX_VALID); //设置端点有效,可以接收数据bDeviceState = ATTACHED;/* Set this device to response on default address */SetDeviceAddress(0);
}
由于需要枚举的是多点触控屏,需要处理Get_Report和Set_Report,虽然有些人说Set_Report不需要处理,但是我还是顺手处理掉了。
/*******************************************************************************
添加上获取HID描述符和报告描述符函数
*******************************************************************************/
ONE_DESCRIPTOR Test_Hid_Descriptor = {
(u8*)Joystick_ConfigDescriptor + Test_OFF_HID_DESC,
JOYSTICK_SIZ_HID_DESC };ONE_DESCRIPTOR Test_Report_Descriptor = {
(u8 *)TestReportDescriptor,
Test_ReportDescriptor_Size }; u8 *Test_GetHIDDescriptor(u16 Length)
{
return Standard_GetDescriptorData(Length, &Test_Hid_Descriptor);
}u8 *Test_GetReportDescriptor(u16 Length)
{
return Standard_GetDescriptorData(Length, &Test_Report_Descriptor);
}/*******************************************************************************
这里用来处理Get_Report Set_Report
*******************************************************************************/
u8 Report_Buffer[2] = {0x02, 0x02}; //Report_Buffer[0]为FeatureID,
//Report_Buffer[1]为最大触控点数u8 *Joystick_GetReport(u16 Length) //处理Get_Report
{
if(Length == 0)
{
pInformation->Ctrl_Info.Usb_wLength = 2;
return NULL;
}
return &Report_Buffer[pInformation->Ctrl_Info.Usb_wOffset];
}u8 *Joystick_SetReport(u16 Length)//处理Set_Report
{
if(Length == 0)
{
pInformation->Ctrl_Info.Usb_wLength = 2;
return NULL;
}
return &Report_Buffer[pInformation->Ctrl_Info.Usb_wOffset];
}RESULT Joystick_Data_Setup(u8 RequestNo)
{u8 *(*CopyRoutine)(u16);CopyRoutine = NULL;if ((RequestNo == GET_DESCRIPTOR)
&& (Type_Recipient == (STANDARD_REQUEST | INTERFACE_RECIPIENT))
&& (pInformation->USBwIndex0 < 3)){
if (pInformation->USBwValue1 == REPORT_DESCRIPTOR)
{
CopyRoutine = Test_GetReportDescriptor;
}
else if (pInformation->USBwValue1 == HID_DESCRIPTOR_TYPE)
{
CopyRoutine = Test_GetHIDDescriptor;
}} /* End of GET_DESCRIPTOR *//*** GET_PROTOCOL ***/else if ((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))
&& RequestNo == GET_PROTOCOL){
CopyRoutine = Joystick_GetProtocolValue;}/******************************************************************
Add Handle Get_Report and Set_Report CTL:
******************************************************************/else if((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT))){
switch(RequestNo)
{
case GET_REPORT:
CopyRoutine = Joystick_GetReport;
break; case SET_REPORT:
CopyRoutine = Joystick_SetReport;
break; default:
break;
}}if (CopyRoutine == NULL){
return USB_UNSUPPORT;}pInformation->Ctrl_Info.CopyData = CopyRoutine;pInformation->Ctrl_Info.Usb_wOffset = 0;(*CopyRoutine)(0);return USB_SUCCESS;
}
3.usb_conf.h
//地址为32位对其,位4的倍数,不能超过 bMaxPacketSize
/* EP0 */
/* rx/tx buffer base address */
#define ENDP0_RXADDR (0x40)
#define ENDP0_TXADDR (0x80)/* EP1 */
/* rx/tx buffer base address */
#define ENDP1_RXADDR (0xc0)
#define ENDP1_TXADDR (0x100)
4.usb_desc.h
#define JOYSTICK_SIZ_CONFIG_DESC 41 //配置描述符的大写改为41,即0x29
#define Test_ReportDescriptor_Size 202 //触控屏报表描述符长度
#define Test_OFF_HID_DESC 18 //触控屏HID描述符的偏移量extern const u8 TestReportDescriptor[Test_ReportDescriptor_Size];//extern一下
5.usb_desc.c
const u8 Joystick_ConfigDescriptor[JOYSTICK_SIZ_CONFIG_DESC] =
{
/***************配置描述符***********************/0x09, //bLength字段USB_CONFIGURATION_DESCRIPTOR_TYPE, //bDescriptorType字段JOYSTICK_SIZ_CONFIG_DESC&0xff, //wTotalLength字段(JOYSTICK_SIZ_CONFIG_DESC>>8)&0xff,0x01, //bNumInterfaces字段0x01, //bConfiguration字段0x00, //iConfigurationz字段0x80, //bmAttributes字段0x20, //bMaxPower字段
/* 9 *//*******************第一个接口描述符*********************/0x09, //bLength字段USB_INTERFACE_DESCRIPTOR_TYPE, //bDescriptorType字段0x00, //bInterfaceNumber字段0x00, //bAlternateSetting字段0x02, //bNumEndpoints字段0x03, //bInterfaceClass字段0x00, //bInterfaceSubClass字段0x00, //bInterfaceProtocol字段0x00, //iConfiguration字段
/* 18 *//******************HID描述符************************/
0x09, //bLength字段
0x21, //bDescriptorType字段
0x01, //bcdHID字段
0x01,
0x00, //bCountyCode字段
0x01, //bNumDescriptors字段
0x22, //bDescriptorType字段
Test_ReportDescriptor_Size&0xFF,
(Test_ReportDescriptor_Size>>8)&0xFF,
/* 27 *//**********************输入端点描述符***********************/0x07, //bLength字段USB_ENDPOINT_DESCRIPTOR_TYPE, //bDescriptorType字段0x81, //bEndpointAddress字段0x03, //bmAttributes字段0x10, //wMaxPacketSize字段0x00,0x0A, //bInterval字段
/* 34 *//**********************输出端点描述符***********************/0x07, //bLength字段USB_ENDPOINT_DESCRIPTOR_TYPE, //bDescriptorType字段0x01, //bEndpointAddress字段0x03, //bmAttributes字段0x10, //wMaxPacketSize字段0x00,0x0A, //bInterval字段
/* 41 */
const u8 TestReportDescriptor[Test_ReportDescriptor_Size] =
{/* 多点触控设备 */0x05, 0x0d,// USAGE_PAGE (Digitizers)0x09, 0x04,// USAGE (Touch Screen)0xa1, 0x01,// COLLECTION (Application)0x85, 0x01,//REPORTID_MTOUCH, // REPORT_ID (Touch)/* 8 *//* 第一点 */ /* 手指和z轴 */0x09, 0x22,// USAGE (Finger)0xa1, 0x02,// COLLECTION (Logical)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)0x81, 0x02,// INPUT (Data,Var,Abs)0x95, 0x06,// REPORT_COUNT (6)0x81, 0x01,// INPUT (Cnst,Ary,Abs)/* 32 *//* 手指ID */ 0x75, 0x08,// REPORT_SIZE (8)0x09, 0x51,// USAGE ( Contact Identifier)0x25, 0xFF,// LOGICAL_MAXIMUM (255)0x95, 0x01,// REPORT_COUNT (1)0x81, 0x02,// INPUT (Data,Var,Abs)/* 42 *//* X和Y */0x05, 0x01,// USAGE_PAGE (Generic Desk)0x16, 0x00,0x00,//HID_LogicalMinS (0)0x26, 0x56, 0x05,// LOGICAL_MAXIMUM (1366)0x75, 0x10,// REPORT_SIZE (16)0x55, 0x00,// UNIT_EXPONENT (0)0x65, 0x00,// UNIT (00)0x09, 0x30,// USAGE (X)0x36, 0x00,0x00,// PHYSICAL_MINIMUM (0)0x46, 0x56, 0x05,// PHYSICAL_MAXIMUM (1366)0x95, 0x01,// REPORT_COUNT (1)0x81, 0x02,// INPUT (Data,Var,Abs)0x26, 0x00, 0x03,// LOGICAL_MAXIMUM (4095)0x46, 0x00, 0x03,// PHYSICAL_MAXIMUM (4095)0x09, 0x31,// USAGE (Y)0x81, 0x02,// INPUT (Data,Var,Abs)0xc0, // END_COLLECTION/* 79 *//* 第二点 *//* 手指和z轴 */0x05, 0x0d,// USAGE_PAGE (Digitizers)0x09, 0x22,// USAGE (Finger)0xa1, 0x02,// COLLECTION (Logical)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)0x81, 0x02,// INPUT (Data,Var,Abs)0x95, 0x06,// REPORT_COUNT (6)0x81, 0x01,// INPUT (Cnst,Ary,Abs)/* 105 *//* 手指ID */0x75, 0x08,// REPORT_SIZE (8)0x09, 0x51,// USAGE ( Contact Identifier)0x95, 0x01,// REPORT_COUNT (1)0x25, 0xFF,// LOGICAL_MAXIMUM (255) 0x81, 0x02,// INPUT (Data,Var,Abs)/* 115 *//* X和Y */0x05, 0x01,// USAGE_PAGE (Generic Desk..0x26, 0x56, 0x05, // LOGICAL_MAXIMUM (1366)0x75, 0x10,// REPORT_SIZE (16)0x55, 0x00,// UNIT_EXPONENT (0)0x65, 0x00,// UNIT (0)0x09, 0x30,// USAGE (X)0x36, 0x00,0x00,// PHYSICAL_MINIMUM (0)0x46, 0x56, 0x05,// PHYSICAL_MAXIMUM (1366)0x81, 0x02,// INPUT (Data,Var,Abs)0x26, 0x00, 0x03,0x46, 0x00, 0x03,// PHYSICAL_MAXIMUM (0)0x09, 0x31,// USAGE (Y)0x81, 0x02,// INPUT (Data,Var,Abs)0xc0, //END_COLLECTION/* 147 *//* 实际点数 */0x05, 0x0d,// USAGE_PAGE (Digitizers)0x09, 0x54,// USAGE (Actual count)0x95, 0x01,// REPORT_COUNT (1)0x75, 0x08,// REPORT_SIZE (8)0x15, 0x00,// LOGICAL_MINIMUM (0)0x25, 0x08,// LOGICAL_MAXIMUM (8)0x81, 0x02,// INPUT (Data,Var,Abs)/* 161 *//* 硬件支持点数 */0x85, 0x02,// REPORT_ID (Feature)0x75, 0x08,// REPORT_SIZE (8)0x95, 0x01,// REPORT_COUNT (1)0x15, 0x01,// LOGICAL_MINIMUM (1)0x25, 0x08,// LOGICAL_MAXIMUM (8)0x09, 0x55,// USAGE(Maximum Count)0xB1, 0x02,// FEATURE (Data,Var,Abs)0xc0, // END_COLLECTION/* 176 *//* 上位机特性设定 */0x09, 0x0E,// USAGE (Device Configuration) 0xa1, 0x01,// COLLECTION (Application) 0x85, 0x04,// REPORT_ID (Configuration) 0x09, 0x23,// USAGE (Device Settings) 0xa1, 0x02,// COLLECTION (logical) 0x09, 0x52,// USAGE (Device Mode) 0x15, 0x00,// LOGICAL_MINIMUM (0) 0x25, 0x0a,// LOGICAL_MAXIMUM (10) 0x75, 0x08,// REPORT_SIZE (8) 0x09, 0x53,// USAGE (Device Identifier) 0x95, 0x01,// REPORT_COUNT (2) 0xb1, 0x02,// FEATURE (Data,Var,Abs 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION/* 202 */
};
效果
枚举成功就可以在系统设备中找到枚举的触控屏设备信息了,这里使用的是Usblyer。
如何测试
void Test_Send(uint8_t *buf, uint16_t len)
{// 对于本代码2点触控每个数据包由14个字节组成分别为// InReport[0] 设备ID 固定值为TOUCH_REPORT_ID// InReport[1] 第一点触摸情况 bit1:1有触摸 0没触摸 bit2: 1在范围内 0不在范围内// InReport[2] 第一点ID 每个点在抬起之前不能改变 0~255// InReport[3] 第一点X坐标低8位// InReport[4] 第一点X坐标高8位// InReport[5] 第一点Y坐标低8位// InReport[6] 第一点Y坐标高8位// InReport[7] 第二点触摸情况 bit1:1有触摸 0没触摸 bit2: 1在范围内 0不在范围内// InReport[8] 第二点ID 每个点在抬起之前不能改变 0~255// InReport[9] 第二点X坐标低8位// InReport[10] 第二点X坐标高8位// InReport[11] 第二点Y坐标低8位// InReport[12] 第二点Y坐标高8位// InReport[13] 此数据包中有效的点数static uint8_t i = 0;uint8_t Buffer[14];if(i > 0 && i < 20){Buffer[0] = 0x01;Buffer[1] = 0x07;Buffer[2] = 0x01;Buffer[3] = 0x88;Buffer[4] = 0x07;Buffer[5] = 0x85;Buffer[6] = 0x04;Buffer[7] = 0x00;Buffer[8] = 0x00;Buffer[9] = 0x00;Buffer[10] = 0x00;Buffer[11] = 0x00;Buffer[12] = 0x00; Buffer[13] = 0x01;}if(i < 40 && i > 20){Buffer[0] = 0x01;Buffer[1] = 0x06;Buffer[2] = 0x01;Buffer[3] = 0x88;Buffer[4] = 0x07;Buffer[5] = 0x85;Buffer[6] = 0x04;Buffer[7] = 0x00;Buffer[8] = 0x00;Buffer[9] = 0x00;Buffer[10] = 0x00;Buffer[11] = 0x00;Buffer[12] = 0x00; Buffer[13] = 0x01;}if(i > 40){Buffer[0] = 0x01;Buffer[1] = 0x00;Buffer[2] = 0x00;Buffer[3] = 0x00;Buffer[4] = 0x00;Buffer[5] = 0x00;Buffer[6] = 0x00;Buffer[7] = 0x00;Buffer[8] = 0x00;Buffer[9] = 0x00;Buffer[10] = 0x00;Buffer[11] = 0x00;Buffer[12] = 0x00; Buffer[13] = 0x00;}i++;if(i > 60){i = 0;}UserToPMABufferCopy(Buffer, GetEPTxAddr(ENDP1) , 14);SetEPTxValid(ENDP1);return;
}
这份东西还有很多不足的地方,报表那边的逻辑大小是需要对应触控屏的,触点是可以增加的,发送的数据坐标有些问题,目前还在调试中。。。