纪国圣 发表于 2021-10-31 17:06

HC32F460通过USB与matlab通讯简单例程

这个例程只是实现了HC32F460通过USB与matlab数据回环交换,更复杂的例子比如实时采集数据可以在此基础上通过Timer定时读取Read函数实现。
1.准备好之前HC32F460的WINUSB例程与其上位机,并简单测试HC32F460能否每秒发送一次数据:




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_INFORMATIONPipe;
    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文件:



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 =
    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的通信,但其有很多需要完善的地方。写这篇帖子仅仅起到抛砖引玉的作用,欢迎大家提出建议。

caigang13 发表于 2021-11-2 07:40

学习了,谢谢分享。

sparrow054 发表于 2021-11-2 11:56

这个是不是要大大的赞啊,太牛了!

foxsbig 发表于 2022-1-21 16:55

这个厉害,MATLAB还能这样玩~~

duo点 发表于 2022-1-21 17:11

厉害,非常赞
页: [1]
查看完整版本: HC32F460通过USB与matlab通讯简单例程