用VC++实现USB接口读写数据的程序
用VC++实现USB接口读写数据的程序
用VC++实现USB接口读写数据的程序用VC++实现USB接口读写数据的程序使用一个GUIDguidHID_1查找并打开一个USB设备extern "C" int PASCAL SearchUSBDevice(){HANDLE hUsb;int nCount, i, j;//标记同一设备个数HDEVINFO hDevInfoSet;BOOL bResult;PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail =NULL;memset(m_sysversion, 0, 20);GetSysVersion(m_sysversion);// 检索相关GUID的USB设备总设备个数if (!GetUSBList()){return 0;}// 取得一个该GUID相关的设备信息集句柄hDevInfoSet = ::SetupDiGetClassDevs((LPGUID)&guidHID_1,//GUID_CLASS_USB_DEVICE, // class GUIDNULL, // 无关键字NULL, // 不指定父窗口句柄DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备// 失败...if (hDevInfoSet == INVALID_HANDLE_VALUE){return NULL;}// 申请设备接口数据空间nCount = 0;bResult = TRUE;for (i=0; i< 34; i++){bDeviceOpen = FALSE;memset(m_DeviceDesc, 0, 256);}SP_DEVICE_INTERFACE_DATA ifdata;// 设备序号=0,1,2... 逐一测试设备接口,到失败为止while (bResult){ifdata.cbSize = sizeof(ifdata);// 枚举符合该GUID的设备接口bResult = ::SetupDiEnumDeviceInterfaces(hDevInfoSet, // 设备信息集句柄NULL, // 不需额外的设备描述(LPGUID)&guidHID_1,//GUID_CLASS_USB_DEVICE, // GUID(ULONG)nCount, // 设备信息集里的设备序号&ifdata); // 设备接口信息if (bResult){ULONG predictedLength = 0;ULONG requiredLength = 0;// 取得该设备接口的细节(设备路径)bResult = SetupDiGetInterfaceDeviceDetail(hDevInfoSet, // 设备信息集句柄&ifdata, // 设备接口信息NULL, // 设备接口细节(设备路径)0, // 输出缓冲区大小&requiredLength, // 不需计算输出缓冲区大小(直接用设定值)NULL); // 不需额外的设备描述// 取得该设备接口的细节(设备路径)predictedLength=requiredLength;// if(pDetail)// {// pDetail =NULL;// }pDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, predictedLength);pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);bResult = SetupDiGetInterfaceDeviceDetail(hDevInfoSet, // 设备信息集句柄&ifdata, // 设备接口信息pDetail, // 设备接口细节(设备路径)predictedLength, // 输出缓冲区大小&requiredLength, // 不需计算输出缓冲区大小(直接用设定值)NULL); // 不需额外的设备描述if (bResult){// 复制设备路径到输出缓冲区//::strcpy(pszDevicePath[nCount], pDetail->DevicePath);if (strcmp(m_sysversion, "winnt")==0){char ch[18];for(i=0;i<17;i++){ch=*(pDetail->DevicePath+8+i);}ch[17]='\0';if (strcmp(ch,"vid_0471&pid_0666")==0)//比较版本号,防止意外出错{memset( &READ_OS, 0, sizeof( OVERLAPPED ) ) ;memset( &WRITE_OS, 0, sizeof( OVERLAPPED ) ) ;READ_OS.hEvent = CreateEvent( NULL, // no securityTRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (READ_OS.hEvent == NULL){break;}WRITE_OS.hEvent = CreateEvent( NULL, // no securityTRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (NULL == WRITE_OS.hEvent){CloseHandle( READ_OS.hEvent );break;}hUsb=CreateFile(pDetail->DevicePath,//&guidHID_1,//GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL/*|FILE_FLAG_OVERLAPPED*/,NULL);if (hUsb != NULL){// 比较定位找到的USB在哪个USB PORT上char id[30];memset(id, 0, 30);i=0;do{id=*(pDetail->DevicePath+26+i);i++;}while(id!='#');id = '\0';for (j=0; j<34; j++){if(strcmp(id, m_USBList[j])==0){sprintf(m_DeviceDesc[j+1], "%s", pDetail->DevicePath); m_USBPositionMap[nCount] = j+1;break;}}CloseHandle(hUsb);nCount++;// break;}}// 比较驱动版本}// 比较操作系统版本else{memset( &READ_OS, 0, sizeof( OVERLAPPED ) ) ;memset( &WRITE_OS, 0, sizeof( OVERLAPPED ) ) ;READ_OS.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (READ_OS.hEvent == NULL){break;}WRITE_OS.hEvent = CreateEvent( NULL, // no securityTRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (NULL == WRITE_OS.hEvent){CloseHandle( READ_OS.hEvent );break;}hUsb=CreateFile(pDetail->DevicePath,//&guidHID_1,// GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL/*|FILE_FLAG_OVERLAPPED*/,NULL);if (hUsb != NULL){if(strcmp(pDetail->DevicePath, m_USBList[j])==0){sprintf(m_DeviceDesc[j+1], "%s", pDetail->DevicePath); m_USBPositionMap[nCount] = j+1;break;}CloseHandle(hUsb);nCount++;// break;}}}}}// 释放设备接口数据空间::GlobalFree(pDetail);// 关闭设备信息集句柄::SetupDiDestroyDeviceInfoList(hDevInfoSet); iDeviceCount = nCount;return nCount;}// 写BOOL Writestr(char *buf,int buflen, int index){BOOL fWriteStat;DWORD dwErrorFlags;DWORD dwError;COMSTAT ComStat;char szError[ 10 ] ;DWORD ret;int len, i, j, packet;div_t div_result;BYTE sendpacket[65];BYTE xorcode="0x00";if (m_gphdCom[index] == NULL) // no usb device(jk100c) {return -1;}div_result = div(buflen, 58);if (div_result.rem == 0){packet = div_result.quot;}else{packet = div_result.quot+1;}for (i=0; i<packet; i++){memset(sendpacket, 0, 65);if(i==packet-1){// end packetif (div_result.rem == 0){len = 58;}else{len = div_result.rem;}}else{len = 58;}sendpacket[0] = 0x13;sendpacket[1] = 3+len;sendpacket[2] = 0x01;sendpacket[3] = packet*16+i+1;memcpy(sendpacket+4, buf+(i*58), len);for(j=0;j<len+3;j++){xorcode^=sendpacket[j+1];}sendpacket[len+4] = (char)xorcode;sendpacket[len+5] = 0x23;PurgeComm(m_gphdCom[index],PURGE_RXCLEAR|PURGE_TXCLEAR);// Sleep(10);fWriteStat = WriteFile(m_gphdCom[index], sendpacket, len+6,&ret, NULL); if (!fWriteStat){if(GetLastError() == ERROR_IO_PENDING){dwError = GetLastError();// an error occurred, try to recoverwsprintf( szError, "\n\r <CE-%u>", dwError ) ;OutputDebugString(szError);ClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;if (dwErrorFlags >0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ; OutputDebugString(szError);}}else{// some other error occurredClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;if (dwErrorFlags > 0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ; OutputDebugString(szError);}return FALSE;}}if (i != packet-1){// should be receive ackif (ReceivePacketAnswer(index) != 0){return FALSE;}}}return TRUE;}// 读int Readstr(char *buf,int nMaxLength, int index){BOOL fReadStat ;COMSTAT ComStat;DWORD dwErrorFlags;DWORD dwLength;DWORD dwError;char szError[ 10 ];if (fCOMMOpened==0){return FALSE; //串口未打开}// only try to read number of bytes in queueClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat) ;//dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;dwLength=nMaxLength;if (dwLength > 0){if (olap==TRUE){fReadStat = ReadFile(m_gphdCom[index],buf, dwLength, &dwLength,&READ_OS) ; if (!fReadStat){if (GetLastError() == ERROR_IO_PENDING){OutputDebugString("\n\rIO Pending");while(!GetOverlappedResult(m_gphdCom[index], &READ_OS,&dwLength, TRUE )){dwError = GetLastError();if(dwError == ERROR_IO_INCOMPLETE) continue;else{// an error occurred, try to recoverClearCommError(m_gphdCom[index],&dwErrorFlags, &ComStat ) ;break;}}}else // end-----if (GetLastError() == ERROR_IO_PENDING){// some other error occurreddwLength = 0 ;ClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;if (dwErrorFlags >0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ;OutputDebugString(szError);}}} // end-----if (!fReadStat)} // end-----if (olap==TRUE)else{fReadStat = ReadFile( m_gphdCom[index],buf, dwLength, &dwLength, NULL ) ; if (!fReadStat){dwError = GetLastError();ClearCommError(m_gphdCom[index],&dwErrorFlags, &ComStat ) ;if (dwErrorFlags >0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ;OutputDebugString(szError);}}PurgeComm(m_gphdCom[index],PURGE_RXCLEAR|PURGE_TXCLEAR);}}return dwLength;。
用VC++编写USB接口通讯程序
用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(通用串行总线)。
编写在USB接口读写数据的C++程序
memset(m_sysversion, 0, 20); GetSysVersion(m_sysversion);
// 检索相关 GUID 的 USB 设备总设备个数 if (!GetUSBList()) { return 0; } // 取得一个该 GUID 相关的设备信息集句柄 hDevInfoSet = ::SetupDiGetClassDevs((LPGUID)&guidHID_1,//GUID_CLASS_USB_DEVICE, // class GUI D NULL, // 无关键字 NULL, // 不指定父窗口句柄 DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备
if (bResult) { ULONG predictedLength = 0; ULONG requiredLength = 0; // 取得该设备接口的细节(设备路径) bResult = SetupDiGetInterfaceDeviceDetail( hDevInfoSet, // 设备信息集句柄 &ifdata, // 设备接口信息 NULL, // 设备接口细节(设备路径) 0, // 输出缓冲区大小 &requiredLength, // 不需计算输出缓冲区大小(直接用设定值) NULL); // 不需额外的设备描述 // 取得该设备接口的细节(设备路径) predictedLength=requiredLength;
WRITE_OS.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset req FALSE, // initial event reset NULL ) ; // no name if (NULL == WRITE_OS.hEvent) { CloseHandle( READ_OS.hEvent ); break; }
如何实现VC应用程序与PLC的数据交换
如何实现VC应用程序与PLC的数据交换当今,随着工业自动化的广泛应用,越来越多的工业企业开始采用可编程逻辑控制器(PLC)来控制和管理生产过程。
而随着信息技术的不断发展,将计算机技术与工业控制相结合,实现VC应用程序与PLC的数据交换,已经成为很多企业提高生产效率、提升产品质量的一种重要手段。
本文将从硬件和软件两个角度来介绍如何实现VC应用程序与PLC的数据交换。
硬件层面:在实现VC应用程序与PLC的数据交换之前,首先需要确保计算机和PLC之间能够进行可靠的通信。
一般而言,可以通过以下几种方式来实现计算机和PLC之间的连接和通信。
1.串口通信:串口通信是最常见的一种方式,通过串口线将计算机的串口与PLC的COM口相连接。
在VC应用程序中,通过编程方式来读写串口数据,从而实现与PLC的数据交互。
2.以太网通信:在以太网通信方式下,计算机和PLC通过以太网进行连接。
可以使用TCP/IP协议来实现数据的传输。
在VC应用程序中,可以使用套接字编程来实现与PLC的通信。
B通信:有些PLC具备USB接口,可以通过USB线将计算机和PLC进行连接。
在VC应用程序中,可以通过USB编程来与PLC进行数据交互。
软件层面:在硬件连接完成之后,下一步就是通过软件来实现VC应用程序与PLC的数据交换。
以下是一些常用的软件开发工具和编程语言,可以帮助我们实现这个目标。
1.Visual Studio:Visual Studio是一个功能强大的集成开发环境,可以用于开发各种类型的应用程序,包括VC应用程序。
在VC应用程序中,可以通过编写相应的代码来与PLC进行数据交换。
2.C#编程语言:C#是一种简单、现代化的编程语言,广泛应用于Windows平台的应用程序开发。
在VC应用程序中,可以使用C#编写代码来实现与PLC的数据交互。
3.编程库:PLC通常配备有相关的编程库,包括DLL、API等,可以用于编写与PLC通信的代码。
在VC应用程序中,可以引用这些编程库,从而实现与PLC的数据交换。
用VC实现与USB驱动程序的通信
3.W.Richard Stevens,范建华胥光辉张涛等译.TCP/IP 详解,卷1:协议[M】.机械工业出版社,2000
4.A.Jones J.Ohlund,京京工作室译.windows网络编程 技术.机械工业出版社,2000
(收稿日期:2002年11月15日)
(上接第57页) 报告。在实现时,只要把相应的编辑框重新赋值为空即可。
mjtrLog+=J{”准备读取数据时分配内存失败.\r\n“): SetDIgltemTe×t(IDC_EDIT_j{EPORT,m—strLog):
) if(hDevice==INVALlD_j—ANDLE—yALUE)
retUm: eIse
{ Read刚e{hDevice,b uf,n,&nRead,NULL)://读取数据函数
CString p:
//p暂时存放buf中的数据以便输出
p=buf:
mjtrLog+=J(”写入设备的数据是:\n”+p+”\r\n”):
SetDIgItemText(IDC_EDIT—REPORT,m—strLog):
}
if(buf)
//释放缓冲区
deIete【]buf:
buf=NULL:
)
3.读数据 从设备读数据时,也要分配一片相应大小的内存空间,暂
(7)如果不再需要,应用程序调用DelStream方法删除一 个流。
C#实现USB接口的程序代码
C#实现USB接口的程序代码姑苏行namespace ConsoleApplication1{class Program{static void Main(string[] args){USB usb;usb = new UDisk();//插入U盘usb.OutputFile();//从U盘读出文件usb.InputFile();//往U盘写入文件usb.Dispose();//拔出U盘Console.WriteLine("");usb = new MDisk();//插入移动硬盘usb.OutputFile();//从移动硬盘读出文件usb.InputFile();//往移动硬盘写入文件usb.Dispose();//拔出移动硬盘Console.WriteLine("");usb = new MP4();//插入MP4usb.OutputFile();//从MP4读出文件usb.InputFile();//往MP4写入文件usb.Dispose();//拔出MP4Console.ReadKey();}//USB接口public interface USB : IDisposable{void OutputFile();//读出文件void InputFile();//写入文件}//U盘public class UDisk : USB{public UDisk(){Console.WriteLine("U盘准备就绪...");}public void OutputFile(){Console.WriteLine("从U盘读出文件");}public void InputFile(){Console.WriteLine("往U盘写入文件");}public void Dispose(){Console.WriteLine("U盘已被拔出");}}//移动硬盘public class MDisk : USB{public MDisk(){Console.WriteLine("移动硬盘准备就绪...");}public void OutputFile()Console.WriteLine("从移动硬盘读出文件");}public void InputFile(){Console.WriteLine("往移动硬盘写入文件");}public void Dispose(){Console.WriteLine("移动硬盘已被拔出");}}//MP4public class MP4 : USB{public MP4(){Console.WriteLine("MP4准备就绪...");}public void OutputFile()Console.WriteLine("从MP4读出文件");}public void InputFile(){Console.WriteLine("往MP4写入文件");}public void Dispose(){Console.WriteLine("MP4已被拔出");}}}}。
C实现USBHID设备读写代码
USB HID设备读写代码实现c++ 收藏源代码如下:(生成.dll .lib)1.MCDInterface.h/**MCDInterface.h*author:*data:*/#ifndef MCDBOX_H_INCLUDED#define MCDBOX_H_INCLUDED#pragma once#define MCD_IOCTRL_OPEN_SIG 0x1001#define MCD_IOCTRL_CLOSE_SIG 0x1002#define MCD_IOCTRL_FIND_SIG 0x1003#define MCD_IOCTRL_READY 0x1003#define MCD_IOCTRL_UNREADY 0x1004#define KEY_0 0x3A#define KEY_1 0x3B#define KEY_2 0x3C#define KEY_3 0x3D#define KEY_4 0x3E#define KEY_5 0x3F#define KEY_6 0x40#define KEY_7 0x41#define KEY_8 0x42#define KEY_9 0x43#define KEY_STAR 0x44#define KEY_POUND 0x45#define MSG_HOOKOFF 0x16#define MSG_HOOKON 0x12#define MSG_RINGING 0x15#define HID_DEVICE_REMOVE 0x76 //硬件被移走#define CLIENT_READY_WRITE_SIG 0x92 //通知设备软件正在运行,每隔一段时间向缓冲区写该数据#define DLL_EXPORT __declspec(dllexport)#define DLL_IMPORT __declspec(dllimport)//定义用于回调的枚举消息enum{MCD_CALLBACK_MSG_VERSION,//not usedMCD_CALLBACK_MSG_SERIALNO,//not usedMCD_CALLBACK_DEVICE_FOUND,MCD_CALLBACK_DEVICE_NOT_FOUND,MCD_CALLBACK_DEVICE_REMOVE,MCD_CALLBACK_KEYDOWN,MCD_CALLBACK_KEYBUFFER_CHANGED,MCD_CALLBACK_HOOKOFF,MCD_CALLBACK_HOOKON,MCD_CALLBACK_RINGING,MCD_CALLBACK_MSG_WARNING = -2,MCD_CALLBACK_MSG_ERROR = -1,};DLL_EXPORT unsigned long MCD_DeviceIoControl(unsigned long dwIoControlCode,void* lpInBuffer = 0, unsigned long nInBufferSize = 0,void* lpOutBuffer = 0, unsigned long nOutBufferSize = 0);//定义设备状态返回信息enum{MCD_RETURN_SUCCESS = 0,MCD_RETURN_FOUND_HID,MCD_RETURN_NO_FOUND_HID,MCD_RETURN_HID_IS_OPENED,//?MCD_RETURN_HID_NO_OPEN,//?};#endif // MCDBOX_H_INCLUDED2.mcdHid.h#ifndef MCDHID_H_INCLUDED#define MCDHID_H_INCLUDEDextern "C"{#include "setupapi.h"#include "hidsdi.h"#include "dbt.h"}typedef struct _HID_DEVICE {PCHAR DevicePath;HANDLE HidDevice; // A file handle to the hid device.HIDP_CAPS Caps; // The Capabilities of this hid device.HIDD_ATTRIBUTES Attributes;} HID_DEVICE, *PHID_DEVICE;class MCDHid{public:static MCDHid & getInstance(){static MCDHid mcdHid;return mcdHid;}MCDHid(MCDHid & mcdHid);MCDHid & operator=(MCDHid &mcdHid);~MCDHid();unsigned long openMCDHid();void closeMCDHid();void startComm(void * pParam);int writeToHid();int readFromHid();char * getHidDeviceName(){return _hidDeviceName;}bool findMCDHid();HID_DEVICE* getHidDevice(){return & _hidDevice;}bool getUsbCommRunning(){return _fUsbCommRunning;}bool getOffHookSignal(){return _offHookSignal;}unsigned long getDataWaitProcess(){return _dataWaitProcess;}void setUsbCommRunning(bool usbCommRunning) {_fUsbCommRunning = usbCommRunning;}unsigned char _inputReportBuffer[9];unsigned char _outputReportBuffer[2];private:MCDHid();void copy(MCDHid & mcdHid);char *_hidDeviceName;HANDLE _hEventObject;OVERLAPPED _hIDOverlapped;HID_DEVICE _hidDevice;bool _fUsbCommRunning;bool _offHookSignal;unsigned long _dataWaitProcess;unsigned long _inputReportByteLength;unsigned long _outputReportByteLength;};#endif // MCDHID_H_INCLUDED3.mcdHid.cpp/*mcdhid.cppfunction: open HID device ,close HID device ,read data from HID device , write data to HID deviceauthor:date:version:*/#include <stdlib.h>#include <windows.h>#include <stdio.h>#include "mcdhid.h"#include "MCDInterface.h"#include "mcdbox.h"#include "pthread.h"void *getDataThread(void *pParam);#define VENDOR_ID 0x1241//test device vendorId#define PRODUCT_ID 0xe001//test device productId#define CLIENT_RUNNING_MSGMCDHid::MCDHid(){_hidDeviceName = "MCD Human Interface Device";_fUsbCommRunning = false;_offHookSignal = false;_dataWaitProcess = 1;memset(_inputReportBuffer,0,sizeof(_inputReportBuffer));memset(_outputReportBuffer,0,sizeof(_outputReportBuffer));}MCDHid::MCDHid(MCDHid & mcdHid){copy(mcdHid);}MCDHid & MCDHid::operator=(MCDHid & mcdHid){copy(mcdHid);return *this;}void MCDHid::copy(MCDHid & mcdHid){_hidDeviceName = mcdHid._hidDeviceName;_hEventObject = mcdHid._hEventObject;_hIDOverlapped = mcdHid._hIDOverlapped;_hidDevice = mcdHid._hidDevice;_fUsbCommRunning = mcdHid._fUsbCommRunning;_offHookSignal = mcdHid._offHookSignal;_dataWaitProcess = mcdHid._dataWaitProcess;_inputReportByteLength = mcdHid._inputReportByteLength;_outputReportByteLength = mcdHid._outputReportByteLength; for(int i = 0; i<s izeof(_inputReportBuffer); i++){_inputReportBuffer[i] = mcdHid._inputReportBuffer[i];}for(int i = 0; i<s izeof(_outputReportBuffer); i++){_inputReportBuffer[i] = mcdHid._outputReportBuffer[i];}}MCDHid::~MCDHid(){}unsigned long MCDHid::openMCDHid(){if(findMCDHid()){//采用重叠传输方式//if( _hEventObject == 0)// {_hEventObject = CreateEvent(NULL,true,true,"");_hIDOverlapped.hEvent = _hEventObject;_hIDOverlapped.Offset = 0;_hIDOverlapped.OffsetHigh =0;// }return MCD_RETURN_SUCCESS;}elsereturn MCD_RETURN_NO_FOUND_HID;}void MCDHid::closeMCDHid(){CloseHandle(_hidDevice.HidDevice);_hidDevice.HidDevice = INVALID_HANDLE_VALUE;}void MCDHid::startComm(void *pParam){int thr_id;pthread_t m_processT;if((thr_id=pthread_create(&m_processT, NULL, getDataThread, pParam) != 0)){//printf("pthread_create error:%s\n", strerror(thr_id));return;}}bool MCDHid::findMCDHid(){int vendorID = VENDOR_ID;int productID = PRODUCT_ID;DWORD required;GUID hidGuid;HDEVINFO hDevInfo;SP_DEVICE_INTERFACE_DATA devInfoData;int memberIndex = 0;LONG result;bool lastDevice = false;DWORD length;PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;bool deviceDetected = false;HidD_GetHidGuid(&hidGuid);hDevInfo = SetupDiGetClassDevs(&hidGuid,NULL,NULL,DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);//当应用程序不再需要使用SetupDiGetClassDevs函数的传回值hDevInfo所指的数组时,应该调用SetupDiDeStroyDeviceInfoList函数来释放资源if(hDevInfo == INVALID_HANDLE_VALUE){//printf("Failed to open device handle!");return false;}devInfoData.cbSize = sizeof(devInfoData);do{result = SetupDiEnumDeviceInterfaces(hDevInfo,0,&hidGuid,memberIndex,&devInfoData);if (result != 0){result = SetupDiGetDeviceInterfaceDetail(hDevInfo,&devInfoData,NULL,0,&length,NULL);detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(length);if(!detailData){//printf("Device information allacation failed!");return false;}detailData -> cbSize =sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);result = SetupDiGetDeviceInterfaceDetail(hDevInfo,&devInfoData,detailData,length,&required,NULL);if(!result){//printf("Device information reallocation failed!");return false;}_hidDevice.HidDevice = CreateFile(detailData->DevicePath,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,(LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,NULL);_hidDevice.Attributes.Size = sizeof(HIDD_ATTRIBUTES);result = HidD_GetAttributes(_hidDevice.HidDevice,&_hidDevice.Attributes);if ((_hidDevice.Attributes.VendorID == vendorID) &&(_hidDevice.Attributes.ProductID == productID)){int status;PHIDP_PREPARSED_DATA PreparsedData ;deviceDetected = true;//获取USB设备的预解析数据result =HidD_GetPreparsedData(_hidDevice.HidDevice,&PreparsedData);if(!result){//printf("无法获取USB设备的预解析数据!");return false;}status= HidP_GetCaps(PreparsedData, &_hidDevice.Caps); _fUsbCommRunning = true;HidD_FreePreparsedData(PreparsedData);PreparsedData = NULL;}else//printf("没有找到设备!");closeMCDHid();}free(detailData);detailData = NULL;}else{lastDevice = true;}memberIndex = memberIndex + 1;}while((lastDevice == false)&&(deviceDetected == false));SetupDiDestroyDeviceInfoList(hDevInfo);return deviceDetected;}/**写入数据为MCD设备状态通知,把标识位放在第1位*/int MCDHid::writeToHid(){return 0;}int MCDHid::readFromHid()//int readFromHid(){if(_hidDevice.HidDevice != INVALID_HANDLE_VALUE){int result = 0;DWORD numberOfBytesRead;result = ReadFile(_hidDevice.HidDevice,&_inputReportBuffer,_hidDevice.Caps.InputReportByteLength,&numberOfBytesRead,(LPOVERLAPPED)&_hIDOverlapped);_inputReportByteLength = _hidDevice.Caps.InputReportByteLength; }int waitResult = 0;waitResult = WaitForSingleObject(_hEventObject,10);switch(waitResult)case WAIT_OBJECT_0: break;case WAIT_TIMEOUT:{CancelIo(_hidDevice.HidDevice);break;}default:{break;}}ResetEvent(_hEventObject);return 0;}/************************************************************* **************启动一个读取数据线程,读取数据为拨打电话号码*启动一个写入数据线程, 写入数据为MCD设备状态通知,现在还没有写数据************************************************************** *************/void *getDataThread(void *pParam){MCDBox *ht = (MCDBox *)pParam;MCDHid *hr = &(MCDHid::getInstance());while(hr->getUsbCommRunning())//USB设备running,并且有摘机信号{hr->readFromHid();//readFromHid();//printf("获取缓冲区的数据\n");if(hr->getDataWaitProcess() > 0)//可以定义_dataWaitProcess为一次拨号数据的长度{unsigned long i = 0;for(i = 0; i < 9; i++){ht->_inputReportBuffer[i] = hr->_inputReportBuffer[i];//printf("read data from device is:%d\n",ht->_inputReportBuffer[1]);}ht->processData();memset(hr->_inputReportBuffer,0,sizeof(hr->_inputReportBuffer));//printf("数据处理!\n");}int status = 0;//PHIDP_PREPARSED_DATA PreparsedData ;//status = HidD_GetPreparsedData(_hidDevice.HidDevice,&PreparsedData); status = HidD_GetAttributes(hr->getHidDevice()->HidDevice,&hr->getHidDevice()->Attributes);if(!status){hr->setUsbCommRunning(false);memset(ht->_inputReportBuffer,0,sizeof(ht->_inputReportBuffer));ht->_inputReportBuffer[2] = HID_DEVICE_REMOVE;ht->processData();printf("设备移走!");//return false;break;}//HidD_FreePreparsedData (PreparsedData);// PreparsedData = NULL;Sleep(100);}return 0;}4.mcdbox.h#ifndef MCDMAIN_H_INCLUDED#define MCDMAIN_H_INCLUDEDclass MCDHid;class MCDCallBack;class MCDBox{public:static MCDBox & getInstance(){static MCDBox mcdBox;return mcdBox;}~MCDBox();unsigned long deviceIOControl(unsigned long dwIoControlCode,void* lpInBuffer, unsigned long nInBufferSize,void* lpOutBuffer, unsigned long nOutBufferSize);void findDevice(void* lpInBuffer, unsigned long nInBufferSize,void* lpOutBuffer, unsigned long nOutBufferSize);unsigned long openDevice(void* lpInBuffer, unsigned long nInBufferSize, void* lpOutBuffer, unsigned long nOutBufferSize);void closeDevice();void processData();unsigned char _inputReportBuffer[9];unsigned char _outputReportBuffer[9];unsigned long _inputBufferByteLength;unsigned long _outputBufferByteLength;bool isDeviceOpen(){return _openDevice;}void setDeviceOpen(bool deviceOpen){_openDevice = deviceOpen;}private:MCDBox();char * _mcdHidName;unsigned long _mcdStatus;MCDHid & _mcdHid;MCDCallBack &_mcdCallback;bool _openDevice;//char _key;};/**定义回调函数*/typedef void (*CALLBACK_MCDBOX)(void* wParam, void* lParam, unsigned long ParameterOfApp);class MCDCallBack{public:static MCDCallBack & getInstance(){static MCDCallBack mcdCallback;return mcdCallback;}MCDCallBack(MCDCallBack & mcdCallback);MCDCallBack & operator=(MCDCallBack & mcdCallback);virtual ~MCDCallBack();void create(void* pCallBackFunction = 0, unsigned long dwParameterOfApplication = 0);void callBack(unsigned long wParam,void* lParam = 0);private:MCDCallBack();void copy(MCDCallBack & mcdCallback);struct {CALLBACK_MCDBOX func;unsigned long lParam;}_fCallBack;};//extern MCDCallBack mcdCallBack;#endif // MCDMAIN_H_INCLUDED5.cpp/*mcdbox.cppfunction description: 数据处理接口author:date:version:*/#ifndef MCDBOX_CPP_INCLUDED#define MCDBOX_CPP_INCLUDED#include <windows.h>#include <stdio.h>#include "mcdbox.h"#include "MCDInterface.h"#include "mcdhid.h"#include "pthread.h"void *findDeviceThread(void *param);unsigned long MCD_DeviceIoControl(unsigned long dwIoControlCode,void* lpInBuffer, unsigned long nInBufferSize,void* lpOutBuffer, unsigned long nOutBufferSize) {unsigned long br = 0;MCDBox *ht = (MCDBox *)&(MCDBox::getInstance());//MCDBox ht = getInstance();;try{br =ht->deviceIOControl(dwIoControlCode,lpInBuffer,nInBufferSize,lpOutBuffer,n OutBufferSize);}catch (unsigned long BytesReturned){br = BytesReturned;}return br;}MCDBox::MCDBox():_mcdHid(MCDHid::getInstance()),_mcdCallback(MCDCallBack::getInstance()){_openDevice =false;_inputBufferByteLength = 8;_outputBufferByteLength = 8;for (int i = 0; i < (int)_inputBufferByteLength; i++){_inputReportBuffer[i] = 0;}for (int j = 0;j < (int)_outputBufferByteLength; j++){_outputReportBuffer[j] = 0;}}MCDBox::~MCDBox(){}unsigned long MCDBox::deviceIOControl(unsigned long dwIoControlCode,void* lpInBuffer, unsigned long nInBufferSize,void* lpOutBuffer, unsigned long nOutBufferSize) {switch (dwIoControlCode){case MCD_IOCTRL_FIND_SIG:findDevice(lpInBuffer,nInBufferSize,lpOutBuffer,nOutBufferSize);break;case MCD_IOCTRL_CLOSE_SIG:if (_openDevice){closeDevice();}_mcdHid.closeMCDHid();_openDevice = false;return 0;case MCD_IOCTRL_OPEN_SIG:if (_openDevice)return MCD_RETURN_HID_IS_OPENED;openDevice(lpInBuffer,nInBufferSize,lpOutBuffer,nOutBufferSize);break;//case CLIENT_READY_WRITE_SIG://软件运行正常,通知硬件设备// _mcdHid.writeToHid();// return 0;default:if (!_openDevice) return MCD_RETURN_HID_NO_OPEN;break;}return 0;}void MCDBox::findDevice(void* lpInBuffer, unsigned long nInBufferS ize,void* lpOutBuffer, unsigned long nOutBufferSize) {pthread_t m_processT;int threadID;_mcdCallback.create(lpInBuffer,nInBufferSize);if((threadID=pthread_create(&m_processT, NULL, findDeviceThread, this) != 0)){return ;}}unsigned long MCDBox::openDevice(void* lpInBuffer, unsigned long nInBufferSize,void* lpOutBuffer, unsigned long nOutBufferSize) {_mcdCallback.create(lpInBuffer,nInBufferSize);unsigned long dwReturnValue = _mcdHid.openMCDHid();if(dwReturnValue == MCD_RETURN_SUCCESS){_openDevice = true;// _mcdCallback.create(lpInBuffer,nInBufferSize);_mcdStatus = MCD_IOCTRL_READY;//_mcdHid.writeToHid();//软件运行正常,通知硬件设备//_key = 0;_mcdHid.startComm(this);_mcdHidName = _mcdHid.getHidDeviceName();}else{_mcdHid.closeMCDHid();}return dwReturnValue;}void MCDBox::closeDevice(){_mcdHid.closeMCDHid();}/************************************************************* *******************/***读取缓冲区,第二个字节为有效数据,buffer size = 8bytes。
VC环境下 USB HID类说明
VC环境下 USB HID类说明1、头文件包含,库文件链接在VC中开发HID应用程序时,需要包含setupapi.h和hidsdi.h,包含方式必须为extern "C",如下所示:extern "C" {// Declare the C libraries used#include "setupapi.h" // Must link in setupapi.lib#include "hidsdi.h" // Must link in hid.lib};然后在setting—>Link—>object/libary modules 中添加setupapi.lib hid.lib 两个库文件。
void __stdcall HidD_GetHidGuid(__out LPGUID HidGuid //指针指向调用者分配的GUID的内存区域,通常返回HID设备的GUID );2.2 SetupDiGetClassDevsHDEVINFO SetupDiGetClassDevs(__in_opt const GUID *ClassGuid,// 一个特定类别GUID的指针__in_opt PCTSTR Enumerator, //过滤梅举的内容__in_opt HWND hwndParent, //用于关联到集合成员中的用户接口的顶层窗口句柄__in DWORD Flags //建立设备信息表的控制选项,DIGCF_PRESENT(当前存在的设备)DIGCF_ALLCLASSES(所有设备)DIGCF_PROFILE(当前硬件概况);) 如成功,返回包含所有与指定参数匹配的已经安装设备信息句柄,否则返回INV ALID_HANDLE_V ALUE 2.3 SetupDiEnumDeviceInterfacesBOOL SetupDiEnumDeviceInterfaces(__in HDEVINFO DeviceInfoSet, //一个指向设备信息集合的句柄,包含设备接口返回信息,通常是SetupDiGetClassDevs的返回值__in_opt PSP_DEVINFO_DATA DeviceInfoData, //指向特定设备的SP_DEVINFO_DATA类型的指针,__in const GUID *InterfaceClassGuid, //指向制定设备接口类的GUID指针__in DWORD MemberIndex, //设备信息中接口列表的索引值(初始值为0)__out PSP_DEVICE_INTERFACE_DA TA DeviceInterfaceData //指向调用者分配的SP_DEVICE_INTERFACE_DATA类型的内存区域的指针,调用前必须先配置DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DA TA)); 如成功,返回TRUE,否则返回FALSE,并可以调用GetLastError(void)获取错误信息2.4 SetupDiGetDeviceInterfaceDetailBOOL SetupDiGetDeviceInterfaceDetail(__in HDEVINFO DeviceInfoSet, //一个指向设备信息集合的句柄,包含设备接口返回信息,通常是SetupDiGetClassDevs的返回__in PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, //指向SP_DEVICE_INTERFACE_DA TA类型的内存区域的指针,SetupDiEnumDeviceInterfaces的返回 __out_opt PSP_DEVICE_INTERFACE_DETAIL_DATADeviceInterfaceDetailData,//SP_DEVICE_INTERFACE_DETAIL_DATA类型指针,用于获取路径,调用前必须先配置DeviceInterfaceDetailData.cbSize =sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)__in DWORD DeviceInterfaceDetailDataSize, //DeviceInterfaceDetailData 的长度,__out_opt PDWORD RequiredSize, //DeviceInterfaceDetailData 的实际长度__out_opt PSP_DEVINFO_DA TA DeviceInfoData //PSP_DEVINFO_DATA 类型的指针,存放支持的设备接口信息,DeviceInfoData.cbSize =sizeof(SP_DEVINFO_DATA) ); 如成功,返回TRUE,否则返回FALSE,并可以调用GetLastError(void)获取错误信息2.5 HidD_GetAttributesBOOLEAN __stdcall HidD_GetAttributes(__in HANDLE HidDeviceObject, //HID设备句柄__out PHIDD_ATTRIBUTES Attributes //HIDD_A TTRIBUTES类型指针);2.6 CreateFileHANDLE WINAPI CreateFile(__in LPCTSTR lpFileName, //已打开的设备名称__in DWORD dwDesiredAccess, //操作权限,GENERIC_READ, GENERIC_WRITE(写模式), 或者both__in DWORD dwShareMode, //共享模式,0(禁止访问),FILE_SHARE_DELETE(删除),FILE_SHARE_READ(读),FILE_SHARE_WRITE(写)__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, //SECURITY_A TTRIBUTES类型指针__in DWORD dwCreationDisposition, //打开方式,对于设备来说经常设为OPEN_EXISTING__in DWORD dwFlagsAndAttributes, //设备属性和标识,经常设为FILE_ATTRIBUTE_NORMAL__in_opt HANDLE hTemplateFile //模板文件句柄); 如成功,则返回一个文件或设备的句柄2.7 ReadFileBOOL WINAPI ReadFile(__in HANDLE hFile, //文件或设备的句柄__out LPVOID lpBuffer, //存放读取数据的指针__in DWORD nNumberOfBytesToRead, //读取数据长度的最大值__out_opt LPDWORD lpNumberOfBytesRead, //读取数据的实际长度__inout_opt LPOVERLAPPED lpOverlapped //OVERLAPPED类型指针,若设备或文件被重复打开,需此参数); 如成功,返回TRUE,否则返回FALSE,并可以调用GetLastError(void)获取错误信息2.8 WriteFileBOOL WINAPI WriteFile(__in HANDLE hFile, //文件或设备的句柄__in LPCVOID lpBuffer, //存放写入数据的指针__in DWORD nNumberOfBytesToWrite, //写入数据长度的最大值__out_opt LPDWORD lpNumberOfBytesWritten, //写入数据的实际长度__inout_opt LPOVERLAPPED lpOverlapped //OVERLAPPED类型指针,若设备/文件被重复打开,需此参数); 如成功,返回TRUE,否则返回FALSE,并可以调用GetLastError(void)获取错误信息2.9 SetupDiDestroyDeviceInfoListBOOL SetupDiDestroyDeviceInfoList( __in HDEVINFO DeviceInfoSet); //释放SetupDiGetClassDevs使用的资源3、代码示例3.1 打开一个指定V endorID和ProductID的HID设备PSP_DEVICE_INTERFACE_DETAIL_DATA HID_FindDevices(USHORT V_ID, USHORT P_ID, unsigned short *FIFO_Length){GUID HidGuid;HDEVINFO DevInfo;HIDD_A TTRIBUTES DevAttributes;SP_DEVICE_INTERFACE_DATA DevData;PSP_DEVICE_INTERFACE_DETAIL_DATA DevDetail;PHIDP_PREPARSED_DA TA PreparsedData;HIDP_CAPS Capabilities;ULONG Length;int Index;BOOL ok;HANDLE DevHandle;int DevCount = 0;/* Get GUID for all System HIDs */HidD_GetHidGuid(&HidGuid);/* Get Device Information for all present devices */DevInfo=SetupDiGetClassDevs(&HidGuid,NULL,NULL,(DIGCF_PRESENT | DIGCF_DEVICEINTERFACE) );DevData.cbSize = sizeof(DevData);DevDetail = NULL;Index = -1;*FIFO_Length = 0;/* Scan all Devices */do {Index++;/* Device Interface Element of a Device Information set */ok = SetupDiEnumDeviceInterfaces(DevInfo, 0, &HidGuid, Index, &DevData);if (!ok) break;/* Get Device Interface Details - Get Length */ok = SetupDiGetDeviceInterfaceDetail(DevInfo, &DevData, NULL, 0, &Length, NULL);/* Allocate memory for Device Detailed Data */DevDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(Length);/* Set cbSize in the DevDetail structure */DevDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);/* Get Device Interface Details */ok = SetupDiGetDeviceInterfaceDetail(DevInfo, &DevData, DevDetail, Length, NULL, NULL);if (!ok){free(DevDetail);DevDetail = NULL;continue;}/* Create File for Device Read/Write */DevHandle = CreateFile(DevDetail->DevicePath, GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,(LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL);if (DevHandle == INV ALID_HANDLE_V ALUE){free(DevDetail);DevDetail = NULL;continue;}DevAttributes.Size = sizeof(DevAttributes);ok = HidD_GetAttributes(DevHandle,&DevAttributes);if(!ok){free(DevDetail);CloseHandle(DevHandle);DevDetail = NULL;continue;}if(DevAttributes.VendorID!=V_ID||DevAttributes.ProductID != P_ID){free(DevDetail);CloseHandle(DevHandle);DevDetail = NULL;continue;}/* Get Preparsed Data */ok = HidD_GetPreparsedData(DevHandle, &PreparsedData);if (!ok){free(DevDetail);CloseHandle(DevHandle);DevDetail = NULL;continue;}/* Get Device's Capabilities */HidP_GetCaps(PreparsedData, &Capabilities);*FIFO_Length = Capabilities.InputReportByteLength;CloseHandle (DevHandle);break;} while (DevCount < 20);SetupDiDestroyDeviceInfoList (DevInfo);return DevDetail;}3.2 发送过程(PC->Device)BOOL WINAPI WriteFile(__in HANDLE hFile, //文件或设备的句柄__in LPCVOID lpBuffer, //存放写入数据的指针__in DWORD nNumberOfBytesToWrite, //写入数据长度的最大值__out_opt LPDWORD lpNumberOfBytesWritten, //写入数据的实际长度__inout_opt LPOVERLAPPED lpOverlapped //OVERLAPPED类型指针,若设备/文件被重复打开,需此参数); 如成功,返回TRUE,否则返回FALSE,并可以调用GetLastError(void)获取错误信息此函数需要注意:(1)hFile是CreateFile创建的句柄;注意:CreateFile中的参数:GENERIC_READ | GENERIC_WRITE(2)lpBuffer是个全局型数值变量,且此数值一般要大于unsigned char [65],而且lpBuffer[0]需要赋予特定的值,用来存储REPORT ID(底层定义的特定值)。
VC编程实现与USB设备通信
VC编程实现与USB设备通信
内容摘要:
本文旨在探讨基于VC的USB设备通信实现。
从基本的概念出发,介绍了USB设备通信的概念,原理以及大致过程;进而深入讨论了基于VC +WIN32API的USB设备通信实现,包括设备上线和识别,数据发送和接收,以及数据处理和编程封装;最后总结了提出了基于VC的USB设备通信实现的讨论方向。
关键词:VC;USB设备;通信;实现
1. 引言
2. USB设备通信概述
Universal Serial Bus,简称USB,是一种计算机通信技术,它可以将多台设备连接到一台电脑,它由系统总线(System Bus)、设备总线(Device Bus)和并行总线(Parallel Bus)三部分组成。
vc编程实现与usb设备通信.doc
第1章绪论1.1USB简介USB是由世界著名计算机和通信公司等共同推出的新一代接口标准,全称为Universal Serial Bus(通用串行总线)[1],是一种快速、灵活的总线接口。
它是为了解决日益增加的PC外设与有限的主板插槽和端口之间的矛盾而制定的一种串行通信标准。
USB应用十分广泛,并具有下述优点:1、适用于多种外设,使它不需要为不同的外设准备不同的接口和协议;2、Windows能自动检测到USB设备的热插拔,并自动配置;3、PC机上的接口线非常紧缺,而USB设备并不需要用户设置端口故无论从用户使用方便性,或从对资源的占用方面看,USB都很优秀;4、当接入一个USB设备时,全速USB接口可达12Mbit/s。
考虑到状态、控制和出错信息,最大理论速度仍可达到9.6Mbit/s,这是其他串行接口协议所不能比拟的,且USB也支持1.5Mbit/s的低速传输。
5、USB接口芯片价格低廉,这也大大促进USB设备的开发与应用。
在USB出现之前,计算机典型接口有并行口、串行口、鼠标口、键盘口、显示器口,及各种卡式接口等,与这些接口对应的有各种不同的电缆,在传输速度方面,这些接口都存在速度偏低的问题。
在技术方面,这种设计容易产生I/O冲突,中断不够用,以及对于每一种新的外设都必须设计新的接口卡等缺点。
当今的计算机外部设备,都在追求高速度和高通用性。
USB接口适应了这种要求,并以其速度快、使用方便、成本低等优点,迅速得到了众多PC厂商和半导体厂商的大力支持,外设向USB过度成为必然趋势。
1.2USB驱动程序的意义如果PC主机不知道如何与USB外设通信,那么这个USB外设一点用处都没有,人机接口设备(HID)[2]类是Windows完全支持的USB设备类型1中的一种,应用程序可以使用操作系统内设置的驱动与HID通信,但与HID 通信不像打开一个端口,设定几个参数,然后就可以读写数据那么简单,在应用程序能与HID交换数据之前,它先要找到设备,获取有关它的报告信息。
基于VISUAL C#的USB接口通信程序设计
摘要:详细介绍了usb接口的特点以及接口通信流程,研究在microsoft visual studio 2008环境下,运用visual c #调用windows api 函数方法进行usb接口通信程序设计的一般方法。
关键字:c#usb通信接口中图分类号:tp311.1 文献标识码:a 文章编号:1007-9416(2010)08-0090-021 hid、usb介绍hid(human interface device)类设备即人机接口设备,是usb设备类型中的一种,是直接与人交互的设备,如键盘、鼠标等。
hid类设备并不一定是标准的外设类型,只要交换的数据格式存储在报文的结构中,并且设备固件支持报文的格式,则任何工作在该限制之内的设备均可称为hid设备,如电压计、温度计、读卡器等。
hid设备与主机交换数据使用“报表”结构,报表格式富有弹性,可以处理任何类型的数据;一个报表可以使用多个事务,每笔事务可以携带小量和中量的数据,高速设备每笔事务最大是1024 b;主机定时轮询设备,设备可以为预期的时间传送信息给主机,hid设备除了传送数据给主机外,也会从主机接收数据。
usb协议定义和支持音频设备类、通信设备类、显示设备类、人机接口设备类(hid)和海量存储设备类等设备类型。
hid是windows完全支持的第一批usb设备类型,在运行win 98以上版本的pc机上,应用程序可以与使用操作系统内置驱动的hid类设备通信。
因此,基于hid类设计的usb设备易于设置和运行。
2 usb人机通信开发方法hid运行在windows98以上版本操作系统的pc机中,系统除了提供通用的usb设备的底层驱动以外,还单独提供了一些hid设备的完整驱动,应用程序可以很容易的与操作系统内部的hid通讯。
这样使得符合hid类的usb设备很容易开发与运行。
也就是说,我们如果想实现一个usb的hid类设备,不需要在windows下开发自己的驱动程序。
vc下usb接口的实现
vc下usb接口的实现#include <setupApi.h>#pragma comment(lib, "setupApi.lib")//加载lib文件//-----------------Initilize USB port---------unsigned int VendorID,ProductID;char temp_buffer[100];unsigned char DataBuffer[1],BufferLength; //接收unsigned char SendDataBuffer[1],SendBufferLength; //发送int HIDCounter=0;GUID hidGuid;HDEVINFO AllHIDDeviceInfo=NULL;HANDLE HIDDevice=NULL,ReadHIDDevice= NULL;HIDD_ATTRIBUTES Attributes;PSP_DEVICE_INTERFACE_DETAIL_DATA ClassDeviceData ;SP_INTERFACE_DEVICE_DATA deviceInfoData;ULONG neededLength,requiredLength;DWORD bytesRead;bool InitUSB(){VendorID = 0x0000;ProductID = 0x0000;// 查找设备// 本例程使用HID设备的API,它查找HID设备列表,找出与Vendor ID 和 Product ID匹配的设备ClassDeviceData =NULL;HIDDevice =NULL;deviceInfoData.cbSize =sizeof(deviceInfoData);// 从操作系统获取HIDs 的GUIDHidD_GetHidGuid(&hidGuid);// 获取所有HIDs的设备信息AllHIDDeviceInfo=SetupDiGetClassDevs(&hidGuid,NULL,NU LL,DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);HIDCounter=0;while (TRUE){// 这个API将发现的设备信息写入 deviceInfoData// HIDCounter 允许这个API重复调用所有HID设备// 如果API调用返回0,没有更多的HID设备发现if (!SetupDiEnumDeviceInterfaces(AllHIDDeviceInfo,0,&hid Guid,HIDCounter,&deviceInfoData)){// 没有发现与Vendor ID 和 Product ID匹配的HID设备SetupDiDestroyDeviceInfoList(AllHIDDeviceInfo);return FALSE;}else{// 发现一个HID设备,获取设备的详细信息// 第一次调用SetupDiGetDeviceInterfaceDetail得到ClassDeviceData// 的大小,但返回错误SetupDiGetDeviceInterfaceDetail(AllHIDDeviceInfo,&deviceI nfoData,NULL,0,&requiredLength,NULL);neededLength =requiredLength;ClassDeviceData =(PSP_DEVICE_INTERFACE_ DETAIL_DATA)malloc(neededLength);ClassDeviceData->cbSize =sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);//第二次调用SetupDiGetDeviceInterfaceDetail// 使用合适的neededLength.if (!SetupDiGetDeviceInterfaceDetail(AllHIDDeviceInfo,&de viceInfoData,ClassDeviceData,neededLength,&requiredLength,NULL)){free(ClassDeviceData);SetupDiDestroyDeviceInfoList(AllHIDDeviceInfo);return FALSE;}// 建立HID设备的句柄HIDDevice=CreateFile(ClassDeviceData-> DevicePath, GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);// 获取 attributes 以便得到Vendor ID 和 Product IDHidD_GetAttributes(HIDDevice,&Attributes);if ((Attributes.VendorID == VendorID) && (Attributes.ProductID == ProductID)){// 找到了匹配的Vendor ID 和 Product ID的HID设备// 建立ReadHIDDevice设备的句柄以便读取信息ReadHIDDevice=CreateFile(ClassDeviceData-> DevicePath, GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);free(ClassDeviceData); SetupDiDestroyDeviceInfoList(AllHIDDeviceInfo);//初始化成功return TRUE;}else{CloseHandle(HIDDevice);}free(ClassDeviceData);HIDCounter = HIDCounter+1;}}}//Read from usb prot,that is listen to usb port ,if it has character,system would display it on user interf acebool ReadUSB(){BufferLength=1;memset(DataBuffer,0,1);if(!ReadFile(ReadHIDDevice,DataBuffer,BufferLength,&bytes Read,NULL)) //失败return false; //读数失败立即返回elsereturn true;}//Wirte a character or a string to usb portbool WriteUSB(){CString str;SendBufferLength=1;SendDataBuffer[0]=65;str=SendDataBuffer;if (!WriteFile(ReadHIDDevice,SendDataBuffer,SendBufferLe ngth,&bytesRead,NULL)){return false;//失败}else{AfxMessageBox( "Success! ");return true;//成功}}//Thread callback functionvoid CUsblistenDlg::OnSend(){// TODO: Add your control notification handler cod e hereSendDataBuffer[0]= 'C ';WriteUSB();}void CUsblistenDlg::OnTimer(UINT nIDEvent){// TODO: Add your message handler code here an d/or call default//CString str;//ReadUSB();//str=DataBuffer;//if(DataBuffer[0]!=0)//{// CListBox *listbox=(CListBox*)GetDlgItem(IDC_ LIST1);// listbox-> AddString(str);//}//else//{// CListBox *listbox=(CListBox*)GetDlgItem(IDC_LIST1 );// listbox-> AddString( "No Charcters is sent to usb port ");//}WriteUSB();CDialog::OnTimer(nIDEvent);}。
基于VC的USB接口通信程序设计
基于VC的USB接口通信程序设计随着信息技术的快速进展,数据采集和处理技术广泛应用于雷达、通信、遥测、遥感等领域。
而在早期的计算机系统上通常用法串口或并口来发送数据,每个接口都需要占用计算机内部无数的资源,传统的接口普通采纳PCI或RS-232串行总线。
PCI总线有较高的传输速率,可达132 Mbit /s,也可以即插即用,但是它们的扩充槽有限且插拔不便利;RS-232串行总线衔接比较便利,但是传输速率太慢,不易用于高速传送数据和传送大量数据。
(通用串行总线)集中了PCI和RS-232串行总线的优点,具有便利的即插即用和热插拔特性以及较高的传输速率,因此,将USB 技术应用于数据采集是十分合适的,可以达到数据采集系统的高速度处理。
目前,USB已经推出了其协议的2.0版本,速率高达480 Mbit/s。
本文研发了一套基于USB接口的数据采集系统,囫囵系统的设计涉及到硬件、设备固件(Firmware)、USB设备驱动程序及客户应用软件。
下面分离加以解释。
2 USB接口芯片本文介绍的USB数据采集系统采纳了公司EZ-USBFX2系列的CY7C68013-128AC芯片,它同时集成了8051微控制器和USB2.0,在提高集成度的同时也加快了数据传输的速度。
在系统中,CY7C68013-128AC既是数据采集控制器又是USB控制器,EZ-USBFX2系列有3种型号:CY7C68013-56PVC、CY7C68013-100AC、CY7C68013-128AC。
该系列的芯片都是针对USB2.0的,并且与USB1.1兼容。
其中,CY7C68013-128AC是128脚,TPQF封装,功能十分完美,与另外两种相比,主要是增强了16位地址总线和8位数据总线以及更多的IO口,因此,CY7C68013-128AC的可扩展性最好。
图1是该芯片的内部结构图。
3 USB的固件和驱动程序设计3.1 固件固件是储存在程序内存中的代码,它使得USB接口芯片与主机和外设第1页共6页。
C++ Builder 访问 USB 口的方法
C++ Builder 访问USB 口的方法(浏览 41700 次)Victor Chen, (C++ 爱好者)编译环境: Borland C++ Builder 6.0, Windows Server 2003 DDK 运行环境: Win98/2000/XP/2003下面是访问 USB 口必备的函数:有了上面的函数就可以访问 USB 口了:USB 设备、USB 驱动、USB 应用程序B 设备硬件部分a.这个硬件的标识是用的 Vender ID 和 Product ID, 即“厂家标识”和“产品标识”b.这个硬件规定了各个 End Point (端点) 的性质, 读/写及类型(Control/Interrupt/Bulk/Isochronous)c.这个硬件的固件里面有 DeviceIoControl 的实现部分, 规定了这个函数的具体参数和动作B 设备驱动①硬件接口a.需要识别 Vender ID 和 Product IDb.对每个 EndPoint 的每个 I/O 分配一个 Pipe, 并且起一个名字作为软件接口c.做 DeviceIoControl 的接口②软件接口a.GUID, 驱动程序的标识, 每个驱动程序使用不同的 GUID, GUID 是识别驱动的, 与硬件无关 (驱动程序升级版本 GUID 不能修改)b.硬件接口里面的 b: Pipe 名字是软件接口, 这个 Pipe 名字纯粹由驱动定义的, 和硬件无关, 升级驱动不能改 Pipe 的名字c.硬件接口里面的 c 的各个参数也是软件的接口, 这些参数是由硬件带来的, 不是驱动规定的, 当然也可以在驱动里面转义, 隐藏设备的真实情况③这个驱动程序是用 WinDDK 编译的, 可以用文本编辑器或其他开发工具的编辑器编程序代码, 然后调用 WinDDK 编译3.读写 USB 口的程序①与驱动的接口a.利用驱动程序里面的 GUID 找出设备的文件名, 用 CreateFile 函数打开设备。
VC封装USB接口的智能卡读写应用层
VC封装USB接口的智能卡读写(应用层)编译时需要包含头文件“Winscard.h”和库文件winscard.1ib。
第一步要通过初始化连接函数获得设备的连接旬柄:SCARDCONTEXT hSC = NULL;LONG IReturn = 0:IReturn=SCardEstablishContext(SCARD COPE SER.NULL.NULL.& hSC):第一个参数指定资源管理连接的范围,另一个可选值为SCARD_ SCOPE_ SYSTEM。
第二步要取得读写器列表:char szReaderNameList[MAX_RESPONSE]:DWORD dwLength = O:IReturn= SCardListReaders(hSC, NULL, szReaderNameList,&dwLength):如果调用成功,则szReaderNameList中存放的是读写器的名字,如果有多个则中间用‘\O’分割,dwLength的值为返回的有效字符的长度,包括所有的‘\O’。
得到读写器的名字后就可以取得某个读写器中智能卡的句柄.第三步要取得指定读写器中卡片的句柄(与卡片建立连接):要取得读写器列表中第一个读写器中卡片的句柄:SCARDHANDLE hCardHandIe = NULL;DW0RD dwActiveProtocol= O:IReturn=SCardConnect{hSC,szReaderNameList,SCARD_ SHARE_EXCLUSIVE,SCARD_ PROTOCOL_T0,SCARD_PR0T0C0L_T1,& hCardHandle,&dwActiveProtoco1);第三个参数表示连接的共享模式,另外两个模式是SCARD_ SHARE SHARED和SCARD_SHARE_DIRECT。
第四个参数指定首选的通信协议类型包括T:0和T=1,dwActiveProtocol返回最终确定的通信协议类型。
VC++6.0 中使用libUsb库进行Hid USB设备通讯
VC++6.0 中使用libUsb库进行Hid USB设备通讯1、首先在/wiki/libusb-win32#下载得到libusb-win32库和一些例子,插上需通讯的HID USB设备,打开下载的库,里面有个可执行文件,运行它,根据提示(注意PID和VID选好你所插的设备)生成inf文件并安装它。
2、完成上一步就可以打开vc++6.0 开发应用程序和HID USB设备通讯了,注意要把与刚才生成的inf文件同文件夹下的lib文件、dll文件和usb.h文件添加到工程文件夹下,并在Project-》Settings-》Link下的Object/library modules 中添加libusb.lib库文件,还有添加usb.h头文件。
3、程序中用到的全局变量:#define MY_VID 0x8888#define MY_PID 0x0006usb_dev_handle *handle;HANDLE m_hDevice=INVALID_HANDLE_VALUE;CWinThread *m_pReadReportThread=NULL;OVERLAPPED ReadOverlapped;char ReadReportBuffer[16]={0};BYTE KeyStatus=0;volatile BOOL m_bReadReportRunFlag=FALSE;4、然后在OnInitDialog()下添加如下代码:struct usb_bus *busses, *bus;// usb_dev_handle *handle = NULL; //这个需定义为全局变量,在读线程中也许使用usb_init();usb_find_busses();usb_find_devices();busses = usb_get_busses();for(bus = busses; bus; bus = bus->next) {struct usb_device *dev;for(dev = bus->devices; dev; dev = dev->next) {struct usb_device_descriptor *desc = &(dev->descriptor);if((desc->idVendor == 0x8888) && (desc->idProduct == 0x0006)) { handle = usb_open(dev);if (!handle ){MessageBox("error opening device: \n%s\n", usb_strerror());return false;}}}}usb_set_configuration(handle,1);usb_claim_interface(handle,0);这是libusb的初始化代码,接下来就可以读写USB数据了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
用VC++实现USB接口读写数据的程序2009-08-15 11:55用VC++实现USB接口读写数据的程序使用一个GUIDguidHID_1查找并打开一个USB设备extern "C" int PASCAL SearchUSBDevice(){HANDLE hUsb;int nCount, i, j;//标记同一设备个数HDEVINFO hDevInfoSet;BOOL bResult;PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail =NULL;memset(m_sysversion, 0, 20);GetSysVersion(m_sysversion);// 检索相关GUID的USB设备总设备个数if (!GetUSBList()){return 0;}// 取得一个该GUID相关的设备信息集句柄hDevInfoSet = ::SetupDiGetClassDevs((LPGUID)&guidHID_1,//GUID_CLASS_USB_DEVICE, // class GUIDNULL, // 无关键字NULL, // 不指定父窗口句柄DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // 目前存在的设备// 失败...if (hDevInfoSet == INVALID_HANDLE_VALUE){return NULL;}// 申请设备接口数据空间nCount = 0;bResult = TRUE;for (i=0; i< 34; i++){bDeviceOpen = FALSE;memset(m_DeviceDesc, 0, 256);}SP_DEVICE_INTERFACE_DATA ifdata;// 设备序号=0,1,2... 逐一测试设备接口,到失败为止while (bResult){ifdata.cbSize = sizeof(ifdata);// 枚举符合该GUID的设备接口bResult = ::SetupDiEnumDeviceInterfaces(hDevInfoSet, // 设备信息集句柄NULL, // 不需额外的设备描述(LPGUID)&guidHID_1,//GUID_CLASS_USB_DEVICE, // GUID(ULONG)nCount, // 设备信息集里的设备序号&ifdata); // 设备接口信息if (bResult){ULONG predictedLength = 0;ULONG requiredLength = 0;// 取得该设备接口的细节(设备路径)bResult = SetupDiGetInterfaceDeviceDetail(hDevInfoSet, // 设备信息集句柄&ifdata, // 设备接口信息NULL, // 设备接口细节(设备路径)0, // 输出缓冲区大小&requiredLength, // 不需计算输出缓冲区大小(直接用设定值)NULL); // 不需额外的设备描述// 取得该设备接口的细节(设备路径)predictedLength=requiredLength;// if(pDetail)// {// pDetail =NULL;// }pDetail = (PSP_INTERFACE_DEVICE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, predictedLength);pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);bResult = SetupDiGetInterfaceDeviceDetail(hDevInfoSet, // 设备信息集句柄&ifdata, // 设备接口信息pDetail, // 设备接口细节(设备路径)predictedLength, // 输出缓冲区大小&requiredLength, // 不需计算输出缓冲区大小(直接用设定值)NULL); // 不需额外的设备描述if (bResult){// 复制设备路径到输出缓冲区//::strcpy(pszDevicePath[nCount], pDetail->DevicePath);if (strcmp(m_sysversion, "winnt")==0){char ch[18];for(i=0;i<17;i++){ch=*(pDetail->DevicePath+8+i);}ch[17]='\0';if (strcmp(ch,"vid_0471&pid_0666")==0)//比较版本号,防止意外出错{memset( &READ_OS, 0, sizeof( OVERLAPPED ) ) ;memset( &WRITE_OS, 0, sizeof( OVERLAPPED ) ) ;READ_OS.hEvent = CreateEvent( NULL, // no securityTRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (READ_OS.hEvent == NULL){break;}WRITE_OS.hEvent = CreateEvent( NULL, // no securityTRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (NULL == WRITE_OS.hEvent){CloseHandle( READ_OS.hEvent );break;}hUsb=CreateFile(pDetail->DevicePath,//&guidHID_1,//GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL/*|FILE_FLAG_OVERLAPPED*/,NULL);if (hUsb != NULL){// 比较定位找到的USB在哪个USB PORT上char id[30];memset(id, 0, 30);i=0;do{id=*(pDetail->DevicePath+26+i);i++;}while(id!='#');id = '\0';for (j=0; j<34; j++){if(strcmp(id, m_USBList[j])==0){sprintf(m_DeviceDesc[j+1], "%s", pDetail->DevicePath); m_USBPositionMap[nCount] = j+1;break;}}CloseHandle(hUsb);nCount++;// break;}}// 比较驱动版本}// 比较操作系统版本else{memset( &READ_OS, 0, sizeof( OVERLAPPED ) ) ;memset( &WRITE_OS, 0, sizeof( OVERLAPPED ) ) ;READ_OS.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (READ_OS.hEvent == NULL){break;}WRITE_OS.hEvent = CreateEvent( NULL, // no security TRUE, // explicit reset reqFALSE, // initial event resetNULL ) ; // no nameif (NULL == WRITE_OS.hEvent){CloseHandle( READ_OS.hEvent );break;}hUsb=CreateFile(pDetail->DevicePath,//&guidHID_1,// GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL/*|FILE_FLAG_OVERLAPPED*/,NULL);if (hUsb != NULL){if(strcmp(pDetail->DevicePath, m_USBList[j])==0){sprintf(m_DeviceDesc[j+1], "%s", pDetail->DevicePath); m_USBPositionMap[nCount] = j+1;break;}CloseHandle(hUsb);nCount++;// break;}}}}}// 释放设备接口数据空间::GlobalFree(pDetail);// 关闭设备信息集句柄::SetupDiDestroyDeviceInfoList(hDevInfoSet); iDeviceCount = nCount;return nCount;}// 写BOOL Writestr(char *buf,int buflen, int index){BOOL fWriteStat;DWORD dwErrorFlags;DWORD dwError;COMSTAT ComStat;char szError[ 10 ] ;DWORD ret;int len, i, j, packet;div_t div_result;BYTE sendpacket[65];BYTE xorcode="0x00";if (m_gphdCom[index] == NULL) // no usb device(jk100c) {return -1;}div_result = div(buflen, 58);if (div_result.rem == 0){packet = div_result.quot;}else{packet = div_result.quot+1;}for (i=0; i<packet; i++){memset(sendpacket, 0, 65);if(i==packet-1){// end packetif (div_result.rem == 0){len = 58;}else{len = div_result.rem;}}else{len = 58;}sendpacket[0] = 0x13;sendpacket[1] = 3+len;sendpacket[2] = 0x01;sendpacket[3] = packet*16+i+1;memcpy(sendpacket+4, buf+(i*58), len);for(j=0;j<len+3;j++){xorcode^=sendpacket[j+1];}sendpacket[len+4] = (char)xorcode;sendpacket[len+5] = 0x23;PurgeComm(m_gphdCom[index],PURGE_RXCLEAR|PURGE_TXCLEAR);// Sleep(10);fWriteStat = WriteFile(m_gphdCom[index], sendpacket, len+6,&ret, NULL); if (!fWriteStat){if(GetLastError() == ERROR_IO_PENDING){dwError = GetLastError();// an error occurred, try to recoverwsprintf( szError, "\n\r <CE-%u>", dwError ) ;OutputDebugString(szError);ClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;if (dwErrorFlags >0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ; OutputDebugString(szError);}}else{// some other error occurredClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;if (dwErrorFlags > 0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ; OutputDebugString(szError);}return FALSE;}}if (i != packet-1){// should be receive ackif (ReceivePacketAnswer(index) != 0){return FALSE;}}}return TRUE;}// 读int Readstr(char *buf,int nMaxLength, int index){BOOL fReadStat ;COMSTAT ComStat;DWORD dwErrorFlags;DWORD dwLength;DWORD dwError;char szError[ 10 ];if (fCOMMOpened==0){return FALSE; //串口未打开}// only try to read number of bytes in queueClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat) ;//dwLength = min( (DWORD) nMaxLength, ComStat.cbInQue ) ;dwLength=nMaxLength;if (dwLength > 0){if (olap==TRUE){fReadStat = ReadFile(m_gphdCom[index],buf, dwLength, &dwLength,&READ_OS) ; if (!fReadStat){if (GetLastError() == ERROR_IO_PENDING){OutputDebugString("\n\rIO Pending");while(!GetOverlappedResult(m_gphdCom[index], &READ_OS,&dwLength, TRUE )){dwError = GetLastError();if(dwError == ERROR_IO_INCOMPLETE) continue;else{// an error occurred, try to recoverClearCommError(m_gphdCom[index],&dwErrorFlags, &ComStat ) ;break;}}}else // end-----if (GetLastError() == ERROR_IO_PENDING){// some other error occurreddwLength = 0 ;ClearCommError(m_gphdCom[index], &dwErrorFlags, &ComStat ) ;if (dwErrorFlags >0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ;OutputDebugString(szError);}}} // end-----if (!fReadStat)} // end-----if (olap==TRUE)else{fReadStat = ReadFile( m_gphdCom[index],buf, dwLength, &dwLength, NULL ) ; if (!fReadStat){dwError = GetLastError();ClearCommError(m_gphdCom[index],&dwErrorFlags, &ComStat ) ;if (dwErrorFlags >0){wsprintf( szError, "\n\r <CE-%u>", dwErrorFlags ) ;OutputDebugString(szError);}}PurgeComm(m_gphdCom[index],PURGE_RXCLEAR|PURGE_TXCLEAR);}}return dwLength;用VC++编写USB接口通讯程序摘要:详细介绍Visual C++ 6.0环境下利用Windows API(Application Program Interface)函数来实现与符合HID设备类的USB接口通讯,并给出了通信程序的部分代码。