您的位置:首页 > 其它

上位机与USB设备通信

2015-05-26 23:16 316 查看
首先使用CreateFile打开USB端口,CreateFile函数会返回一个HANDLE类型的句柄,该句柄可以用于下述的ReadFile和WriteFile之间的操作。

///  实现以指定的参数方式打开USB设备
CreateFile(devicePathName,
GENERIC_READ | GENERIC_WRITE,   // 已读写方式打开
FILE_SHARE_READ| FILE_SHARE_WRITE,
0,
OPEN_EXISTING // 打开已经存在的设备,当设备不存在时会返回错误
FILE_ATTRIBUTE_NORMAL| FILE_FLAG_OVERLAPPED,    // 通信时的一些属性的设置、FILE_FLAG_OVERLAPPED表示已异步的方式打开设备
);




这是最关键的一步是如何获取devicePathName, 幸好windows提供了解决的方法,
使用SetupDiGetClassDevs方法, 关于该方法在MSDN有非常详细的解答:
详细请参考以下网址:
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff551069(v=vs.85).aspx>

</pre><pre name="code" class="cpp">
// 关于HDEVINFO类型在setupapi.h文件中有定义
// typedef LPVOID HDEVINFO
// 表示是一个指向void类型的指针
// 如果调用成功,返回所有符合要求的设备信息的句柄
// 如果调用失败,返回INVALID_HANDLE_VALUE
HDEVINFO  SetupDiGetClassDevs(
_In_opt_ constGUID   *ClassGuid,   // 指向device setup class或device interface class接口的guid,这个参数是可选的,                                  // 可以为NULL
_In_opt_       PCTSTREnumerator,   // 指向一个一NULL结尾的字符串,可以是即插即用设备的枚举器ID。该参数也是可选的,                                                 // 可以为NULL
_In_opt_       HWND  hwndParent,
_In_           DWORD Flags
);

// 调用方法
deviceInfoSet = SetupDiGetClassDevs( * guid,  NUL, NULL,  DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if(deviceInfoSet == INVALID_HANDLE_VALUE)   // 失败
{}
else   // 成功
{}


如果想要获取详细的错误信息,通过调用GetLastError可以获取。

同时如果想要调用远程计算机上的设备的时候请使用SetupDiGetClassDevsEx。

当调用SetupDiGetClassDevs成功后,调用SetupDiEnumDeviceInterface方法,

枚举包含在设备信息集中的设备接口(enum the device information contained in the device

详细请参考下述网址:
https://msdn.microsoft.com/en-us/library/windows/hardware/ff551015(v=vs.85).aspx
一般的调用流程如下所述

SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

// 调用一次返回指定设备的硬件信息
while(SetupDiEnumDeviceInterface(deviceInfoSet,       // 设备信息集
NULL,
*guid,      			//设备接口的guid,与SetupDiGetClassDevs保持一致即可
deviceIndex,      		// 索引号,每调用一次该方法,加1,初始为0
&deviceIntefaceData		//  SP_DEVICE_INTERFACE_DATA指针,记住在调用该方法之前必须设置cbSize的大小
))
{
DWORD bufferSize;
DWORD requiredSize;
SetupDiGetDeviceInterfaceDetail(deviceInfoSet,   //
&deviceInterfaceData, // 表示SP_DEVICE_INTERFACE_DATA,指定DeviceInfoSet的接口,一般来说是SetupDiEnumDeviceInterface返回// 的内容
NULL, // SP_DEVICE_INTERFACE_DETAIL_DATA指针用来接收指定interface的信息
0, // SP_DEVICE_INTERFACE_DETAIL_DATA的buffer大小,当上一个参数为NULL时,该参数必须为0
&requiredSize, // 返回DeviceInterfaceDetailData的buffer 大小
NULL );
}


// 第一次调用SetupDiGetDeviceInterfaceDetail方法后返回SP_DEVICE_INTERFACE_DETAIL_DATA的buffer大小

SP_DEVICE_INTERFACE_DETAIL_DATA detailBufferData;
detailBufferData.cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); // 如果指定了这个参数,那么在使用之前必须设置cbSize参数的大小
SetupDiGetDeviceInterfaceDetail

(deviceInfoSet,

&deviceInterfaceData, //

&detailBufferData, // SP_DEVICE_INTERFACE_DETAIL_DATA指针用来接收指定interface的信息

requiredSize, // 上一次调用后返回的SP_DEVICE_INTERFACE_DETAIL_DATA的buffer大小

&requiredSize, // 返回DeviceInterfaceDetailData的buffer 大小

NULL );

如果SetupDiDeviceInterfaceDetail调用成功,detailBufferData包含有USB设备的路径信息。

}

关于SetupDiGetInterfaceDetail方法的详细请参考下述网址
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff551120(v=vs.85).aspx>

还有一个非常重要的结构体需要介绍下。
SP_DEVICE_INTERFACE_DETAIL_DATA

关于详细的资料可以参考以下网址:
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff552343(v=vs.85).aspx>

// 该结构体返回的DevicePath即设备的路径
typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA {
DWORD cbSize;      // 表示该结构体的大小
TCHAR DevicePath[ANYSIZE_ARRAY];    // 已NULL结尾,包括设备接口路径的字符串(device interface path)
// 这个路径信息可以传递给一些win32函数,例如 CreateFile:
} SP_DEVICE_INTERFACE_DETAIL_DATA, *PSP_DEVICE_INTERFACE_DETAIL_DATA;

[/code]

备注: 在SetupDiXXX系列函数中,当SP_DEVICE_INTERFACE_DETAIL_DATA以参数的形式传递时,
函数会判断结构体的大小与成员cbSize是否一致,否则调用的函数会返回error。

/*
调用SetupDiGetClassDevs方法后,请调用SetupDiEnumDeviceInfo方法。该方法返回的SP_DEVINFO_DATA结构体指定了device information set集合中的设备元素信息。
*/

然后是读写USB设备,这有好几种方法,这里介绍两种:
①:ReadFile和WriteFile;
②:使用winusb_readpipe和winusb_writepipe方法;

最后当不再需要的时候一定要记得删除SetupDiGetClassDevs的返回信息,通过调用SetupDiDestroyDeviceInfoList函数即可,关于该函数的详细的介绍请参考下述MSDN网址
<https://msdn.microsoft.com/en-us/library/windows/hardware/ff550996(v=vs.85).aspx>

因为晚上时间有限,写的有不正确的地方希望能指出来,不胜感激。

参考: http://blog.csdn.net/tody_guo/article/details/8675237
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: