用VC++编写USB接口通讯程序

摘要:详细介绍Visual C++ 6.0环境下利用Windows API(Application Program Interface)函数来实现与符合HID设备类的USB接口通讯,并给出了通信程序的部分代码。

关键词:通用串行总线 人际接口设备 API VisualC++

1 引言

在USB出现之前,计算机的典型接口有并行口(打印口)、串行口、鼠标口、键盘口、显示器口、游戏口及各种卡式接口(如声卡、网卡)等,与这些接口对应的有各种不同的电缆。在传输速度方面,这些接口都存在速度偏低的问题;在技术方面,这种设计容易产生I/O冲突。中断(IRQ)不够用,以及对于每一种新的外设都必须设计新的接口卡等缺点。当今的计算机外部设备,都在追求高速度和高通用型。USB接口适应了这种要求,并以其速度快,使用方便,成本低等优点,迅速得到了众多PC厂商和半导体厂商的大力支持,外设向USB过渡称为必然的趋势。

但如果主机PC不知道如何与USB外设通信,那么这个USB外设一点用处都没有,人机接口设备(HID)类是Windows完全支持的第一批USB设备类型中的一种。在运行Windows98或更高版本的PC机上,应用程序可以使用操作系统内置的驱动与HID通信,但与HID通信不像打开一个端口,设定几个参数,然后就可以读写数据那么简单。在应用程序能与HID交换数据之前,它先要找到设备,获取有关它的报告信息,为做到这些,应用程序必须通过访问通信API函数,使位于上层的应用程序与位于下层的设备驱动程序进行数据交换。应用程序可以使用任何能访问API函数的编程语言,C++是一种能访问API函数的功能强大的语言,本文将在VisualC++6.0环境下编写与USB设备通信的Windows程序。

2 USB简介

USB是由Intel,Compaq,Digital,IBM,Microsoft,NEC,Northern Telecom等七家世界著名的计算机和通信公司共同推出的新一代接口标准,全称为Universal Serial Bus(通用串行总线)。它是为了解决日益增加的PC外设与有限的主板插槽和端口之间的矛盾而制定的一种串行通信标准,尤其当传输速率高达480Mbit/s的USB2.0规范面世后,USB应用更加广泛,它具有下属优点:

(1)适用于多种外设,使它不需要为不同的外设准备不同的接口和协议;

(2)Windows能自动检测到USB设备的热插拔,并自动配置;

(3)PC机上的IRQ线非常紧缺,而USB设备并不需要设置端口和IRQ,故无论从用户使用的方便性,或从对资源的占用方面看,USB都很有优秀;

(4)当接入一个USB设备时,全速USB接口可达12Mbit/s,考虑到状态,控制和出错信息,最大理论速度仍可达9.6Mbit/s,这是其他串行接口协议所不能比拟的,且USB也支持1.5Mbit/s的低速传输;、

但是USB同样有缺点,诸如:协议复杂,编写设备驱动程序要考虑很多细节,以保证USB某些特性的透明性,但通过调用Win32的API函数与设备通信,或者说与内置的驱动程序通信,便没有必要去逐条理解复杂的协议。

3 VC++实现与USB接口通信的实例

Windows下,与USB外设的任何通信需通过设备驱动,该驱动知道如何与系统的USB驱动和访问设备的应用程序通信,Windows包含应用程序与HID通信需要的各种信息,不需要再安装设备驱动。Win32的应用程序接口(API)函数,使得设备驱动能与应用程序之间相互通信,应用程序也不需要为了和USB设备通信去了解复杂的USB协议。

下面用VisualC++编写应用程序调用API函数,从而简化了与硬件通信的过程。

3.1 建立工程

操作步骤如下:

(1)在VC++6.0工作平台中打开File 菜单,选择New菜单命令,在对话框中选择Project选项,在左边列表框选择MFC AppWizard(exe),在Project name 文本编辑框中输入项目名USBPort,在Location文本编辑框中输入项目路径,单击OK按钮,进入MFC AppWizard。

(2)在MFC AppWizard-Step1窗口中,选择Dialog based选项,不该变其他选项的缺省值

(3)在MFC AppWizard-Step2 of 4窗口中,选择About box和3D controls复选框

(4)在MFC AppWizard-Step3 of 4到Step4 of 4不改变各个选项的缺省设置

(5)进入New Project Information窗口,如果检查完全正确后,单击OK按钮即生成应用程序所需要的全部文件。

通过上述操作便生成了基于对话框的工程USBPort。

3.2 查找USB设备

在应用程序能与HID交换数据之前,它先要找到设备,获取有关它的报告信息。首先找到连接到系统的HID是什么,然后检索信息,知道满足要求的属性。

(1)添加成员函数。单击ClassView标签,选定CUSBPortDlg类,右击添加OnSearch消息响应函数,并增加私有类型成员变量,即字符串型变量strPath和strLog以及布尔类型变量bFoundDevice。

(2)OnSearch函数调用API函数,HID类设备是通过GUID类型值作标识的,调用函数HidD_GetHidGuid颗获得HID设备的标识:Hidd_GetHidGuid(&guidHID);

其中guidHID是指向GUID类型的指针,当函数返回后,它指向的内容就是HID类的GUID标识,GUID是16字节大小的结构,用来标识通信接口及类对象,它的定义为:

typedef struct _GUID

{

DWORD Data1;

WORD  Data2;

WORD  Data3;

BYTE   Data4[8];

}GUID;

调用函数HidD_GetHidGuid获得特定的HID设备属性

BOOL HidD_GetAttributes(hCom,&strAttrib);

其中hCom是对应与选定设备的句柄,根据这个句柄定所关心的设备,strAttrib则是指向HIDD_ATTRIBUTES类型的指针,当函数返回时即得到了指定设备的属性。

HIDD_ATTRIBUTES结构定义为:

typedef struct _HIDD_ATTRIBUTES

{

ULONG size;//这个HIDD_ATTRIBUTES变量大小,以字节为单位

USHORT vendorID;//致命HID设备的供应商标识

USHORT ProductID;//致命HID设备的产品标识

USHORT VersionNumber;//HID设备的版本号

}HIDD_ATTRIBUTES,*PHIDD_ATTRIBUTES;

OnSearch函数中还调用了其他与硬件相关的API函数,这些函数都在Setupapi.h中定义。调用SetupDiGetClassDevs函数用来获得一类硬件设备的信息:

HDEVINFO hDevInfo = SetupDiGetClassDevs(

&guidHID,//这类设备配置或接口类GUID

NULL,//特定的字符串,用来选择符合条件的设备

0,//与获得信息相关的顶层窗体(Top_Level Window)句柄

DIGCF_PRESENT | DIGCF_DEVICEINTERFACE//给出了设置信息集的方式

);

调用SetupDiEnumDeviceInterfaces函数得到一个设备接口信息反复调用得到所有设备接口信息。若要找到特定设备,可在循环语句内调用该函数,直到找到预期设备或函数返回FALSE值。

定义该函数:

BOOL bSuccess = SetupDiEnumDeviceInterface(

hDevInfo,//感兴趣的接口句柄

NULL,//指向SP_DEVINFO_DATA类型结构的指针,该结构限定了特定接口

&gudiHID,//确定了接口的GUID标识

0,//所关心的索引号,以0为起点

&strInterfaceData,//指向SP_DEVINFO_INTERFACE_DATA类型的指针,

它所指向的内容就是调用函数的目的所在,当函数返回时,strInterfaceData

指向的结构就存在相关接口的信息。

);

其中结构SP_DEVINFO_DATA定义为:

typedef struct _SP_DEVINFO_DATA{

DWORD cbsize;//指定结构的大小

GUID classGuid;//设备的GUID标识

DWORD DevInst;//用来访问设备的句柄

ULONG_PTR Reserved;
}SP_DEVINFO_DATA,*PSP_DEVINFO_DATA;

结构SP_DEVICE_INTERFACE_DATA定义为

typedef struct _SP_DEVICE_INTERFACE_DATA{

DOWRD cbsize;//是SP_DEVICE_INTERFACE_DATA结构的大小

GUID InterfaceClassGuid;//指定了接口的GUID标识

DWORD Flags;//接口所处状态

ULONG_PTR Reserved;

}SP_DEVICE_INTERFACE_DATA,*PSP_DEVICE_INTERFACE_DATA;

3.3 与USB设备交换数据

在Windows中,读写端口与读写文件都是调用同样的API函数,打开或创建端口用CreateFile从端口读数据用ReadFile,向端口数据用WriteFile。

(1)设备的打开和关闭,用API函数CreateFile来打开或创建设备:

HANDLE hCom = CreateFile(

m_strPath,//指定打开设备名

GENERIC_READ | GENERIC_WEITE,//允许读写

0,//独占方式

NULL,//安全模式

OPEN_EXISTING,//打开

FILE_ATTRIBUTE_NORMAL,//文件属性

NULL //临时文件的句柄

);

如果调用成功,该函数返回文件的句柄;如果调用失败,则返回INVALID_HANDLE_VALUE,在打开通信设备时,应该以独占方式打开。

不再使用设备句柄时,应该调用CloseHandle(hCom)函数关闭它。

(2)设备的读写操作,读写通信设备可用同步方式执行,也可用异步方式执行,这由CreateFile函数中是否指定FILE_FLAG_OVERLAPPED来决定;指定为异步方式,未指定则为同步方式,函数ReadFile和WriteFile的参数和返回值类型,下面是调用ReadFile函数的实例。

HANDLE hCom;

void *pBuffer;

DWORD iLength;

DWORD pReadFact;

BOOL ReadFile( hCom, pBuffer, iLength, &pReadFact, NULL );

读到的数据放在内存pBuffer里,pBuffer要先申请内存空间,iLength为需要读的数据长度,pReadFact存放实际读的数据长度。需要注意的是在读写设备之前,应先调用ClearCommError函数清除错误标志,此函数负责报告指定的错误的设备的当前状态,调用PrugeComm函数可以更改正在进行的读写操作方式。

4 结论

以上是调用Win32的API通信函数用VC++编写的USB设备通信程序,它实现了查找符合HID类的USB设备并与之进行数据交换的基本功能。这种独立与通信子系统之外实现的应用程序,可以实现可靠的高速数据传输。对自定义设备,应用程序需要设备的特定供应商和产品ID,或设备的特定类型,读者只需要对上述程序作一定修改即可,在MFC环境下,编写32位串口通信程序还可采用ActiveX的MSComm控件,但使用API通信函数,具有更大灵活性,可定制性也更强,在设置通信配置和发送错误敏感,无时间限制的数据时,该接口尤其有用。

VC++编写USB接口通讯程序相关推荐

  1. VC封装USB接口的智能卡读写(应用层)

    VC封装USB接口的智能卡读写(应用层) 编译时需要包含头文件"Winscard.h"和库文件winscard.1ib. 第一步要通过初始化连接函数获得设备的连接句柄: SCARD ...

  2. Java编程练习·编写USB接口模拟计算机启动与关闭

    题目 题干:编写一个USB接口程序,模拟计算机启动过程和关闭过程启动过程中要加载鼠标.键盘.麦克风等USB设备,具体要求如下: (1)定义一个接口USB,包含两个抽象方法turnOn()he turn ...

  3. Java编写USB接口,模拟计算机启动过程和关闭过程

    编写一个USB接口程序,模拟计算机启动过程和关闭过程启动过程中要加载鼠标.键盘.麦克风等USB设备,具体要求如下: (1)定义一个接口USB,包含两个抽象方法turnOn()he turnOff(), ...

  4. 用VC++实现USB接口读写数据的程序

    使用一个GUIDguidHID_1查找并打开一个USB设备 extern "C" int PASCAL SearchUSBDevice() {HANDLE hUsb;int nCo ...

  5. vc编写魔兽争霸显血程序

          现在魔兽已经更新到1.24了,可以自动显血了,想当年在1.20版本时还要开外挂来显血时的痛苦可以少了很多,其实编写魔兽的显血程序非常简单的,废话不多说,看代码: #include < ...

  6. 【2】迈德威视工业相机USB接口ROS程序 — 图片topic发布、硬件触发、GPS时间同步、图片保存、曝光时间获取等功能

    一.相机连接 去其官网 二.相机驱动程序 1.程序下载连接  https://www.aliyundrive.com/s/usGLB5NLnZe 2.程序运行 mkdir  MVSDK_camera_ ...

  7. Windows下usb接口驱动技术(二)

    八.        Windows驱动程序模型 Windows环境下驱动程序共有三类,一类是VxD( Virtual Device Driver,虚拟设备驱动程序),起源于Windows 3.1 时代 ...

  8. Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析

    前面学习了SDIO接口的WiFi驱动,现在我们来学习一下USB接口的WiFi驱动,二者的区别在于接口不同.而USB接口的设备驱动,我们前面也有学习,比如USB摄像头驱动.USB鼠标驱动,同样都符合Li ...

  9. linux wifi设置端口号,Linux 下wifi 驱动开发(四)—— USB接口WiFi驱动浅析

    前面学习了SDIO接口的WiFi驱动,现在我们来学习一下USB接口的WiFi驱动,二者的区别在于接口不同.而USB接口的设备驱动,我们前面也有学习,比如USB摄像头驱动.USB鼠标驱动,同样都符合Li ...

最新文章

  1. 无数学不华为?人工智能时代的数学家还将走得更远
  2. Java程序员从笨鸟到菜鸟之(五)java开发常用类(包装,数字处理集合等)(下)
  3. VTK:图表之BoostBreadthFirstSearchTree
  4. java消息分发_Kafka教程设计思想之消息分发策略
  5. Change code to ensure that OPA5 work also in WebIDE
  6. 一秒点击手机屏幕次数_手机电池不耐用,都怪这些充电坏毛病
  7. 企业需求的Java程序员是什么样子的
  8. IDEA编译运行Springboot+vue项目卡死,一直building和copying resources
  9. 快来!前端君喊你加入快驾网智囊团
  10. php软件开发--tp5
  11. php正则式去掉问号后所有,正则表达式如何过滤问号
  12. data:image/png;base64
  13. Java中Spring Cloud Ribbon
  14. android之添加raw文件
  15. ARP欺骗-教程详解
  16. 在谷歌Android都有哪些组,谷歌Android阵营引领了哪些主流技术?
  17. 智能电视硬件架构设计——整机研发
  18. sql存储过程完全教程
  19. 计算机没有音频驱动程序,电脑有驱动却没有高清晰音频管理器华硕主板应该装什么声卡驱动...
  20. 精选6个超实用的Word技巧,每一个大有用处!

热门文章

  1. 通信、电子保研经验贴,北京理工大学+中国科学院大学空天所
  2. excel提取身份证出生日期_EXCEL教学:通过身份证号码提取所有信息
  3. 要么好好地活着,要么就死得其所
  4. linux教程 课件,《Linux实用教程》PPT课件
  5. STM32C8T6编码器电机测速与arduino光电模块测速
  6. ch552开发环境配置
  7. Linux 内存管理篇(1)内存寻址
  8. 什么是分布式数据存储
  9. JS-打开新窗口(window.open)/关闭窗口(window.close)
  10. 初学JavaScript:BOM(浏览器对象模型)介绍