论文部分内容阅读
【摘要】在上位机中,通过人机交互界面,利用Windows提供的API函数,实现应用程序对HID设备的访问。指出调用API函数的过程和方法,并提供了实现方法的具体实例。
【关键词】上位机;USB_HID;Visual C++;人机接口设备
1.引言
USB全称为Universal Serial Bus(通用串行总线),是一种快速、灵活的总线接口。在USB出现之前,计算机接口在传输速度方面都存在速度偏低,容易产生I/O冲突,中断不够用等缺点。
人机接口设备(HID)主要是指一些人与计算机进行交互的设备,如键盘、鼠标、游戏杆等;但是HID设备不一定非要是这些人机交互设备,只要符合HID设备定义规范要求的都可以认为是HID设备。HID设备有以下主要特点:
(1)交换的数据存储在报告的结构内,设备必须支持HID报告格式。
(2)每笔事务可以携带小量或中量的数据。低速设备每笔事务最大为8字节,全速设备每笔最大为64字节,高速设备最大为1024字节;
(3)有最大传输速度的限制。低速设备最快10ms一笔事务,最高速度为800B/s;全速设备最快1ms一笔事务,最高速度为64KB/s;高速设备最快125μs一笔事务,最高速度为24.576MB/s。
如何在应用程序中对HID类设备进行访问呢?在Windows环境下,不允许用户在应用程序中直接访问硬件设备,应用程序必须通过一个中间桥梁才能访问硬件设备,这个中间桥梁就是设备驱动程序。从Windows98操作系统开始,为HID类设备提供了通用的驱动程序,所以只要按照HID设备类的规范编写设备的固件程序,就能够让Windows系统自动识别设备,省去了复杂的驱动程序编写过程。
2.Visual C++介绍
应用基于MFC AppWizard的应用程序。MFC(Microsoft Foundation Class Library)中的各种类结合起来构成了一个应用程序框架,它的目的就是在此基础上来建立Windows下的应用程序,这是一种相对SDK来说更为简单的方法。因为总体上,MFC框架定义了应用程序的轮廓,并提供了用户接口的标准实现方法,要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。Microsoft Visual C++提供了相应的工具来完成这个工作:AppWizard可以用来生成初步的框架文件(代码和资源等);资源编辑器用于帮助直观地设计用户接口;ClassWizard用来协助添加代码到框架文件;最后,编译,则通过类库实现了应用程序特定的逻辑。
3.与HID有关的Windows API函数
Windows为应用程序访问HID设备提供了强大的支持,有一整套对HID设备进行访问的API,包含在hid.dll、setupapi.dll、kernel32.dll3个dll文档中,分别起到与HID设备通信、寻找与识别设备、交换数据的作用。hid.dll与setupapi.dll文档内的API函数用法可以在DDK的帮助找到。kernal32.dll文档内的API函数则是在MSDN library内。
4.应用程序设计实现
应用程序要访问设备就必须先枚举到设备,枚举成功后根据返回的设备句柄,就可以用ReadFile和WriteFile来读写设备的数据了。这里采用异步方式来读写数据,这样不会发生读写时阻塞,提高了程序的效率。
在实现HID的访问之前,首先要查找指定(根据设备的厂商ID、产品ID和产品序列号)的HID。查找指定设备的过程如下:
调用函数HidD_GetHidGuid获得USB设备的GUID;
调用函数SetupDiGetClassDevs,获得一个包含全部HID信息的结构数组的指针,下面根据此数组逐项查找指定的HID;
调用函数SetupDiEnumDeviceInterfaces,填写SP_DEVICE_INTERFACE_DATA结构的数据项,该结构用于识别一个HID设备接口;
调用函数etupDiGetDeviceInterfaceDetail,获得一个指向该设备的路径名;
调用函数CreateFile,获得设备句柄;
调用函数HidD_GetAttributes,填写HIDD_ATTRIBUTES结构的数据项,该结构包含设备的厂商ID、产品ID和产品序列号,比照这些数值确定该设备是否是查找的设备。
查找HID的流程如图1。
下面介绍VC实现的查找过程。
(1)获得GUID
应用程序要与HID设备通信之前,必须先获得HID类别的GUID(Globally Unique Indentifer)。GUID是一个128位的数值,每个对象都有惟一的GUID。HID类别的GUID包含在winnt.h文档内,可以接引用,或是使用HidD_GetHidGuid函数来取得HID类别的GUID。
GUID guidHID;
HidD_GetHidGuid(&guidHID);
(1)获得HID的结构数组
得到GUID后调用SetupDiGetCl
assDevs函数传回所有已经连接并且检测过的HID包含其信息的结构数组的地址。
HDEVINFO hDevInfo=SetupDiGetClassDevs(&guidHID,NULL,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
(2)识别HID接口
接下来调用:SetupDiEnumDe
viceInterfaces,填写SP_DEVICE
_INTERFACE_DATA结构的数据项,该结构用于识别一个HID设备接口。
BOOL bSuccess=SetupDiEnumDeviceInterfaces(hDevInfo,NULL,&guidHID,0,
strtInterfaceData);
(3)获得设备路径
下面通过调用SetupDiGetDev
iceInterfaceDetail函数用来获得另外一个结构:
SP_DEVICE_INTERFACE_DETAIL_DATA。此结构与前一个函数SetupDiEnumDeviceInterfaces所识别的设备接口有关。结构的DevicePath成员是一个设备路径,应用程序可以用此路径来实现与该设备的通信。
BOOL bResult =SetupDiGetDeviceInterfaceDetail(hDevInfo,strtInterfaceData,NULL,0,&requiredLength,NULL);
(4)获得设备句柄
取得设备的路径以后,就可以准备开始与设备通信。使用CreateFile来打开一个HID设备,并且取得此设备的句柄,使用设备的句柄来与设备交换数据。当不再需要访问此设备时,应该调用CIoseHandle函数来关闭设备并释放系统资源。
hCom=CreateFile(m_strPath,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
(5)获得设备的厂商ID、产品ID和产品序列号
要识别一个设备是否是所要的设备,只要比较此设备的厂商与产品ID即可。HidD_GetAttributes函数用来取得一个包含厂商与产品ID以及产品的版本号码的结构。
HidD_GetAttributes(hCom,&strtAttrib)
(6)关闭通信
当应用程序结束与HID的通信后,必须释放所有之前保留的资源。所涉及的几个AP I函数如下:
BOOL HidD-Free PreparsedData(IN PHIDP-PR EPARSED-DA TA Prepar sedData);
其作用是释放由HidD-Get PreparsedData函数传回的PreparsedData缓冲区。
函数Set upDiDestroyDevice InfoList的定义如下:
BOOL SetupDiDest royDevice InfoList
(HDEVINFO Device InfoSet);
其作用是释放由SetupDiGetClassDevs函数传回的hDevInfo数组。最后还要使用CloseHandle函数来关闭通信,释放所有之前保留的资源。
5.第三方测试
程序代码编译完成之后,可以用第三方USB_HID软件进行测试。Report ID设置为01,测试报文为103协议,发送报文:68 00 0f 68 28 00 15 81 2a 00 fe f1 00 01 00 06 00 00 0a 28 23 16(如图2)。测试结果可做为VC代码编写正确与否的参考。
6.小结
利用VC编程,控制对计算机底层硬件的操作,利用驱动程序这个“翻译”,把VC++程序中的数组代码转换成USB设备可以识别的数据传输到单片机中,对USB设备进行控制。在VC环境下利用MFC应用程序框架,开发人机交互界面,与USB收发消息,并显示在相应的编辑框中。完成主机与设备之间的交互。
Windows提供的用来与HID设备通信的API函数,可以被应用程序通过任何的计算机语言来调用。在Windows环境下开发USB应用程序可以归结如下:在应用程序可以开始与HID交换数据前,应用程序必须先识别该设备并且读取它的报表信息,这些动作需要调用一堆API函数。应用程序首先需要寻找连接到系统上的是哪些HID设备,然后检验每个信息直到找到所需的属性。
参考文献
[1]邱罡,王伟.用VC++编写USB人机接口类通信程序[J].平顶山学院学报,2005,20(5):76-78.
[2]薛园园.赵建领.USB应用开发宝典[M].北京:人民邮电出版社,2011.
[3]胡晓军,等.USB接口开发技术[M].西安:西安电子科技大学出版社,2005.
[4]萧世文,宋延清.USB2.0硬件设计[M].北京:清华大学出版社,2006.
[5](美)Jan.Axelson.USB开发大全(第4版)[M].李鸿鹏,等,译.北京:人民邮电出版社,2011.
[6]孙鑫,余安萍.VC++深入详解[M].北京:电子工业出版社,2006.
[7]钱能.C++程序设计教程[M].北京:清华大学出版社,1999.
作者简介:
王紫军(1981—),男,2005年毕业于哈尔滨师范大学计算机科学与技术专业,阿城继电器股份有限公司哈尔滨研发中心设计员,主要从事电力系统监控软件开发及应用工作。
孙楚平(1990—),男,现就读于华北电力大学可再生能源学院。
【关键词】上位机;USB_HID;Visual C++;人机接口设备
1.引言
USB全称为Universal Serial Bus(通用串行总线),是一种快速、灵活的总线接口。在USB出现之前,计算机接口在传输速度方面都存在速度偏低,容易产生I/O冲突,中断不够用等缺点。
人机接口设备(HID)主要是指一些人与计算机进行交互的设备,如键盘、鼠标、游戏杆等;但是HID设备不一定非要是这些人机交互设备,只要符合HID设备定义规范要求的都可以认为是HID设备。HID设备有以下主要特点:
(1)交换的数据存储在报告的结构内,设备必须支持HID报告格式。
(2)每笔事务可以携带小量或中量的数据。低速设备每笔事务最大为8字节,全速设备每笔最大为64字节,高速设备最大为1024字节;
(3)有最大传输速度的限制。低速设备最快10ms一笔事务,最高速度为800B/s;全速设备最快1ms一笔事务,最高速度为64KB/s;高速设备最快125μs一笔事务,最高速度为24.576MB/s。
如何在应用程序中对HID类设备进行访问呢?在Windows环境下,不允许用户在应用程序中直接访问硬件设备,应用程序必须通过一个中间桥梁才能访问硬件设备,这个中间桥梁就是设备驱动程序。从Windows98操作系统开始,为HID类设备提供了通用的驱动程序,所以只要按照HID设备类的规范编写设备的固件程序,就能够让Windows系统自动识别设备,省去了复杂的驱动程序编写过程。
2.Visual C++介绍
应用基于MFC AppWizard的应用程序。MFC(Microsoft Foundation Class Library)中的各种类结合起来构成了一个应用程序框架,它的目的就是在此基础上来建立Windows下的应用程序,这是一种相对SDK来说更为简单的方法。因为总体上,MFC框架定义了应用程序的轮廓,并提供了用户接口的标准实现方法,要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓。Microsoft Visual C++提供了相应的工具来完成这个工作:AppWizard可以用来生成初步的框架文件(代码和资源等);资源编辑器用于帮助直观地设计用户接口;ClassWizard用来协助添加代码到框架文件;最后,编译,则通过类库实现了应用程序特定的逻辑。
3.与HID有关的Windows API函数
Windows为应用程序访问HID设备提供了强大的支持,有一整套对HID设备进行访问的API,包含在hid.dll、setupapi.dll、kernel32.dll3个dll文档中,分别起到与HID设备通信、寻找与识别设备、交换数据的作用。hid.dll与setupapi.dll文档内的API函数用法可以在DDK的帮助找到。kernal32.dll文档内的API函数则是在MSDN library内。
4.应用程序设计实现
应用程序要访问设备就必须先枚举到设备,枚举成功后根据返回的设备句柄,就可以用ReadFile和WriteFile来读写设备的数据了。这里采用异步方式来读写数据,这样不会发生读写时阻塞,提高了程序的效率。
在实现HID的访问之前,首先要查找指定(根据设备的厂商ID、产品ID和产品序列号)的HID。查找指定设备的过程如下:
调用函数HidD_GetHidGuid获得USB设备的GUID;
调用函数SetupDiGetClassDevs,获得一个包含全部HID信息的结构数组的指针,下面根据此数组逐项查找指定的HID;
调用函数SetupDiEnumDeviceInterfaces,填写SP_DEVICE_INTERFACE_DATA结构的数据项,该结构用于识别一个HID设备接口;
调用函数etupDiGetDeviceInterfaceDetail,获得一个指向该设备的路径名;
调用函数CreateFile,获得设备句柄;
调用函数HidD_GetAttributes,填写HIDD_ATTRIBUTES结构的数据项,该结构包含设备的厂商ID、产品ID和产品序列号,比照这些数值确定该设备是否是查找的设备。
查找HID的流程如图1。
下面介绍VC实现的查找过程。
(1)获得GUID
应用程序要与HID设备通信之前,必须先获得HID类别的GUID(Globally Unique Indentifer)。GUID是一个128位的数值,每个对象都有惟一的GUID。HID类别的GUID包含在winnt.h文档内,可以接引用,或是使用HidD_GetHidGuid函数来取得HID类别的GUID。
GUID guidHID;
HidD_GetHidGuid(&guidHID);
(1)获得HID的结构数组
得到GUID后调用SetupDiGetCl
assDevs函数传回所有已经连接并且检测过的HID包含其信息的结构数组的地址。
HDEVINFO hDevInfo=SetupDiGetClassDevs(&guidHID,NULL,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
(2)识别HID接口
接下来调用:SetupDiEnumDe
viceInterfaces,填写SP_DEVICE
_INTERFACE_DATA结构的数据项,该结构用于识别一个HID设备接口。
BOOL bSuccess=SetupDiEnumDeviceInterfaces(hDevInfo,NULL,&guidHID,0,
strtInterfaceData);
(3)获得设备路径
下面通过调用SetupDiGetDev
iceInterfaceDetail函数用来获得另外一个结构:
SP_DEVICE_INTERFACE_DETAIL_DATA。此结构与前一个函数SetupDiEnumDeviceInterfaces所识别的设备接口有关。结构的DevicePath成员是一个设备路径,应用程序可以用此路径来实现与该设备的通信。
BOOL bResult =SetupDiGetDeviceInterfaceDetail(hDevInfo,strtInterfaceData,NULL,0,&requiredLength,NULL);
(4)获得设备句柄
取得设备的路径以后,就可以准备开始与设备通信。使用CreateFile来打开一个HID设备,并且取得此设备的句柄,使用设备的句柄来与设备交换数据。当不再需要访问此设备时,应该调用CIoseHandle函数来关闭设备并释放系统资源。
hCom=CreateFile(m_strPath,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
(5)获得设备的厂商ID、产品ID和产品序列号
要识别一个设备是否是所要的设备,只要比较此设备的厂商与产品ID即可。HidD_GetAttributes函数用来取得一个包含厂商与产品ID以及产品的版本号码的结构。
HidD_GetAttributes(hCom,&strtAttrib)
(6)关闭通信
当应用程序结束与HID的通信后,必须释放所有之前保留的资源。所涉及的几个AP I函数如下:
BOOL HidD-Free PreparsedData(IN PHIDP-PR EPARSED-DA TA Prepar sedData);
其作用是释放由HidD-Get PreparsedData函数传回的PreparsedData缓冲区。
函数Set upDiDestroyDevice InfoList的定义如下:
BOOL SetupDiDest royDevice InfoList
(HDEVINFO Device InfoSet);
其作用是释放由SetupDiGetClassDevs函数传回的hDevInfo数组。最后还要使用CloseHandle函数来关闭通信,释放所有之前保留的资源。
5.第三方测试
程序代码编译完成之后,可以用第三方USB_HID软件进行测试。Report ID设置为01,测试报文为103协议,发送报文:68 00 0f 68 28 00 15 81 2a 00 fe f1 00 01 00 06 00 00 0a 28 23 16(如图2)。测试结果可做为VC代码编写正确与否的参考。
6.小结
利用VC编程,控制对计算机底层硬件的操作,利用驱动程序这个“翻译”,把VC++程序中的数组代码转换成USB设备可以识别的数据传输到单片机中,对USB设备进行控制。在VC环境下利用MFC应用程序框架,开发人机交互界面,与USB收发消息,并显示在相应的编辑框中。完成主机与设备之间的交互。
Windows提供的用来与HID设备通信的API函数,可以被应用程序通过任何的计算机语言来调用。在Windows环境下开发USB应用程序可以归结如下:在应用程序可以开始与HID交换数据前,应用程序必须先识别该设备并且读取它的报表信息,这些动作需要调用一堆API函数。应用程序首先需要寻找连接到系统上的是哪些HID设备,然后检验每个信息直到找到所需的属性。
参考文献
[1]邱罡,王伟.用VC++编写USB人机接口类通信程序[J].平顶山学院学报,2005,20(5):76-78.
[2]薛园园.赵建领.USB应用开发宝典[M].北京:人民邮电出版社,2011.
[3]胡晓军,等.USB接口开发技术[M].西安:西安电子科技大学出版社,2005.
[4]萧世文,宋延清.USB2.0硬件设计[M].北京:清华大学出版社,2006.
[5](美)Jan.Axelson.USB开发大全(第4版)[M].李鸿鹏,等,译.北京:人民邮电出版社,2011.
[6]孙鑫,余安萍.VC++深入详解[M].北京:电子工业出版社,2006.
[7]钱能.C++程序设计教程[M].北京:清华大学出版社,1999.
作者简介:
王紫军(1981—),男,2005年毕业于哈尔滨师范大学计算机科学与技术专业,阿城继电器股份有限公司哈尔滨研发中心设计员,主要从事电力系统监控软件开发及应用工作。
孙楚平(1990—),男,现就读于华北电力大学可再生能源学院。