这个例程只是实现了HC32F460通过USB与matlab数据回环交换,更复杂的例子比如实时采集数据可以在此基础上通过Timer定时读取Read函数实现。
1.准备好之前HC32F460的WINUSB例程与其上位机,并简单测试HC32F460能否每秒发送一次数据:
HC32F460_WINUSB MS_OS_20.zip
(6.66 MB)
win_usb.zip
(23.4 KB)
2.替换文件:
将下图文件放入工程中:
工程目录由
替换为
其中USB.cpp和USB_Dll.cpp主要是对WINUSB开启、读写、关闭做进一步的封装,方便matlab调用。
USB_Dll.h
#ifndef USB_Dll_H
#define USB_Dll_H
#ifdef __cplusplus
extern"C"
{
#endif
__declspec(dllexport) unsigned char Connect();
__declspec(dllexport) unsigned char Read(unsigned char *ptr, const int len);
__declspec(dllexport) unsigned char Write(unsigned char *ptr, unsigned long* cbsize, const int len);
__declspec(dllexport) void Close();
#ifdef __cplusplus
}
#endif
#endif
USB_Dll.cpp
#include "WUSB.h"
#include "USB_Dll.h"
#include <cfgmgr32.h>
DEVICE_DATA deviceData;
PIPE_ID PipeID;
unsigned char Connect()
{
BOOL bResult = TRUE;
unsigned char result;
bResult = USB_Init(&deviceData, &PipeID);
if (bResult == FALSE)
{
result = 0;
}
else
{
result = 1;
}
return result;
}
unsigned char Read(unsigned char* ptr, const int len)
{
BOOL bResult = TRUE;
unsigned char result;
bResult = ReadFromBulkEndpoint(deviceData.WinusbHandle, &PipeID.PipeInId, len, ptr);
if (bResult == FALSE)
{
CloseDevice(&deviceData);
result = 0;
}
else
{
result = 1;
}
return result;
}
unsigned char Write(unsigned char* ptr, unsigned long *cbsize,const int len)
{
BOOL bResult = TRUE;
unsigned char result;
bResult = WriteToBulkEndpoint(deviceData.WinusbHandle, &PipeID.PipeOutId, cbsize, ptr, len);
if (bResult == FALSE)
{
CloseDevice(&deviceData);
result = 0;
}
else
{
result = 1;
}
return result;
}
void Close()
{
CloseDevice(&deviceData);
}
USB.c
#include <stdio.h>
#include "WUSB.h"
BOOL GetUSBDeviceSpeed(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pDeviceSpeed)
{
if (!pDeviceSpeed || hDeviceHandle == INVALID_HANDLE_VALUE)
{
return FALSE;
}
BOOL bResult = TRUE;
ULONG length = sizeof(UCHAR);
bResult = WinUsb_QueryDeviceInformation(hDeviceHandle, DEVICE_SPEED, &length, pDeviceSpeed);
if (!bResult)
{
printf("Error getting device speed: %d.\n", GetLastError());
goto done;
}
if (*pDeviceSpeed == LowSpeed)
{
printf("Device speed: %d (Low speed).\n", *pDeviceSpeed);
goto done;
}
if (*pDeviceSpeed == FullSpeed)
{
printf("Device speed: %d (Full speed).\n", *pDeviceSpeed);
goto done;
}
if (*pDeviceSpeed == HighSpeed)
{
printf("Device speed: %d (High speed).\n", *pDeviceSpeed);
goto done;
}
done:
return bResult;
}
BOOL QueryDeviceEndpoints(WINUSB_INTERFACE_HANDLE hDeviceHandle, PIPE_ID* pipeid)
{
if (hDeviceHandle == INVALID_HANDLE_VALUE)
{
return FALSE;
}
BOOL bResult = TRUE;
USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
ZeroMemory(&InterfaceDescriptor, sizeof(USB_INTERFACE_DESCRIPTOR));
WINUSB_PIPE_INFORMATION Pipe;
ZeroMemory(&Pipe, sizeof(WINUSB_PIPE_INFORMATION));
bResult = WinUsb_QueryInterfaceSettings(hDeviceHandle, 0, &InterfaceDescriptor);
if (bResult)
{
for (UCHAR index = 0; index < InterfaceDescriptor.bNumEndpoints; index++)
{
bResult = WinUsb_QueryPipe(hDeviceHandle, 0, index, &Pipe);
if (bResult)
{
if (Pipe.PipeType == UsbdPipeTypeControl)
{
printf("Endpoint index: %d Pipe type: %d Control Pipe ID: %d.\n", index, Pipe.PipeType, Pipe.PipeId);
}
if (Pipe.PipeType == UsbdPipeTypeIsochronous)
{
printf("Endpoint index: %d Pipe type: %d Isochronous Pipe ID: %d.\n", index, Pipe.PipeType, Pipe.PipeId);
}
if (Pipe.PipeType == UsbdPipeTypeBulk)
{
if (USB_ENDPOINT_DIRECTION_IN(Pipe.PipeId))
{
printf("Endpoint index: %d Pipe type: %d Bulk Pipe ID: %d.\n", index, UsbdPipeTypeBulk, Pipe.PipeId);
pipeid->PipeInId = Pipe.PipeId;
}
if (USB_ENDPOINT_DIRECTION_OUT(Pipe.PipeId))
{
printf("Endpoint index: %d Pipe type: %d Bulk Pipe ID: %d.\n", index, Pipe.PipeType, Pipe.PipeId);
pipeid->PipeOutId = Pipe.PipeId;
}
}
if (Pipe.PipeType == UsbdPipeTypeInterrupt)
{
printf("Endpoint index: %d Pipe type: %d Interrupt Pipe ID: %d.\n", index, Pipe.PipeType, Pipe.PipeId);
}
}
else
{
continue;
}
}
}
//done:
return bResult;
}
BOOL SendDatatoDefaultEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle)
{
if (hDeviceHandle == INVALID_HANDLE_VALUE)
{
return FALSE;
}
BOOL bResult = TRUE;
UCHAR bars = 0;
WINUSB_SETUP_PACKET SetupPacket;
ZeroMemory(&SetupPacket, sizeof(WINUSB_SETUP_PACKET));
ULONG cbSent = 0;
//Set bits to light alternate bars
for (short i = 0; i < 7; i += 2)
{
bars += 1 << i;
}
//Create the setup packet
SetupPacket.RequestType = 0;
SetupPacket.Request = 0xD8;
SetupPacket.Value = 0;
SetupPacket.Index = 0;
SetupPacket.Length = sizeof(UCHAR);
bResult = WinUsb_ControlTransfer(hDeviceHandle, SetupPacket, &bars, sizeof(UCHAR), &cbSent, 0);
if (!bResult)
{
goto done;
}
printf("Data sent: %d \nActual data transferred: %d.\n", bars, cbSent);
done:
return bResult;
}
BOOL WriteToBulkEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID, ULONG* pcbWritten, UCHAR* szBuffer, ULONG cbSize)
{
if (hDeviceHandle == INVALID_HANDLE_VALUE || !pID || !pcbWritten)
{
return FALSE;
}
BOOL bResult = TRUE;
ULONG cbSent = 0;
bResult = WinUsb_WritePipe(hDeviceHandle, *pID, szBuffer, cbSize, &cbSent, 0);
if (!bResult)
{
goto done;
}
printf("Wrote to pipe %d: %s \nActual data transferred: %d.\n", *pID, szBuffer, cbSent);
*pcbWritten = cbSent;
done:
return bResult;
}
BOOL ReadFromBulkEndpoint(WINUSB_INTERFACE_HANDLE hDeviceHandle, UCHAR* pID, ULONG cbSize, UCHAR* szBuffer)
{
if (hDeviceHandle==INVALID_HANDLE_VALUE)
{
return FALSE;
}
BOOL bResult = TRUE;
ULONG cbRead = 0;
bResult = WinUsb_ReadPipe(hDeviceHandle, *pID, szBuffer, cbSize, &cbRead, 0);
if(!bResult)
{
goto done;
}
printf("Read from pipe %d: %s \nActual data read: %d.\n", *pID, szBuffer, cbRead);
done:
LocalFree(szBuffer);
return bResult;
}
BOOL USB_Init(DEVICE_DATA *deviceData, PIPE_ID *PipeID)
{
HRESULT hr;
BOOL noDevice;
BOOL bResult;
USB_DEVICE_DESCRIPTOR deviceDesc;
UCHAR DeviceSpeed;
ULONG lengthReceived;
//
// Find a device connected to the system that has WinUSB installed using our
// INF
//
hr = OpenDevice(deviceData, &noDevice);
if (FAILED(hr)) {
if (noDevice) {
wprintf(L"Device not connected or driver not installed\n");
}
else {
wprintf(L"Failed looking for device, HRESULT 0x%x\n", hr);
}
return FALSE;
}
//
// Get device descriptor
//
bResult = WinUsb_GetDescriptor(deviceData->WinusbHandle,
USB_DEVICE_DESCRIPTOR_TYPE,
0,
0,
(PBYTE)&deviceDesc,
sizeof(deviceDesc),
&lengthReceived);
if (FALSE == bResult || lengthReceived != sizeof(deviceDesc)) {
wprintf(L"Error among LastError %d or lengthReceived %d\n",
FALSE == bResult ? GetLastError() : 0,
lengthReceived);
CloseDevice(deviceData);
return FALSE;
}
//
// Print a few parts of the device descriptor
//
wprintf(L"Device found: VID_%04X&PID_%04X; bcdUsb %04X\n",
deviceDesc.idVendor,
deviceDesc.idProduct,
deviceDesc.bcdUSB);
bResult = GetUSBDeviceSpeed(deviceData->WinusbHandle, &DeviceSpeed);
if (!bResult)
{
CloseDevice(deviceData);
return FALSE;
}
bResult = QueryDeviceEndpoints(deviceData->WinusbHandle, PipeID);
if (!bResult)
{
CloseDevice(deviceData);
return FALSE;
}
return TRUE;
}
3.编译生成DLL文件:
修改工程属性:
编译生成DLL文件:
win_usb_dll.zip
(784.96 KB)
4.将生成的DLL与.h文件拷贝至matlab工作环境,打开matlab,切换工作环境至DLL所在文件夹中:
在命令行中使用如下函数,加载DLL与查看:
可以看到DLL加载成功。
编写m文件,简单测试回环通信:
clc
loadlibrary('USB_Dll.dll','USB_Dll.h')
state = calllib('USB_Dll','Connect');
if(state == 1)
disp('USB Connect')
str = [1 2 3 4 5]
len = 0;
wptr = libpointer('uint8Ptr',str);
n_ptr = libpointer('uint32Ptr',len);
state = calllib('USB_Dll','Write',wptr,n_ptr,length(str));
if(state == 0)
disp('USB error')
else
rptr = libpointer('uint8Ptr',zeros(1,64));
state = calllib('USB_Dll','Read',rptr,63);
if(state == 0)
disp('USB error')
else
char(rptr.Value)
calllib('USB_Dll','Close');
disp('USB Disonnect')
end
end
else
disp('USB do not open')
end
一切正常:
5.总结
总体来说matlab对usb通信的支持力度远没有串口的大,为了实现usb通信就不得不实现混合编程,难度挺大的。这个例子只是简单的实现matlab与HC32F460的通信,但其有很多需要完善的地方。写这篇帖子仅仅起到抛砖引玉的作用,欢迎大家提出建议。
|
|