如何使用Delphi 2009调用Microchip PIC USB DLL

发布于 2024-07-22 07:54:54 字数 6868 浏览 2 评论 0原文

不是问题,只是一个声明,旨在帮助其他可能花费数小时让 Microchip PIC USB DLL 与 Unicode 正常工作的人。

它需要几个字符串,虽然这些是简单的 PAnsiChar,但获得 DLL 调用约定的正确组合花了我很长时间。 网上有很多人使用 Delphi(非 Unicode)和这个 DLL 并逃脱了谋杀。

unit UArtPic32USBDriver;

interface

uses
  Windows,
  SysUtils,
  UArtGeneralHwDefs;


type
  EArtPic32Usb = class( EArtGeneralHw );

function Pic32Usb_GetDllVersion : integer;
// Returns a number representing the DLL version.

function Pic32Usb_GetDeviceCount( const AVendorProductID : string ) : integer;
// Returns the number of devices with this vendor ID

function Pic32Usb_Open(
           AInstance : DWORD;
           const AVendorProductID, AEndpointID : string;
           ADirectionCode : integer;
           ARaise         : boolean ) : THANDLE;
// Opens an endpoint. Can raise an exception if no valid handle is returned.


procedure Pic32Usb_Close( AHandle : THandle );
// Closes the device

function Pic32Usb_Write(
            AHandle              : THANDLE;
            ABufferPtr           : pointer;
            ALengthBytes         : integer ) : DWORD;
// Performs a write using this handle. Returns the number of bytes written

function Pic32Usb_Read(
            AHandle              : THANDLE;
            ABufferPtr           : pointer;
            ALengthBytes         : integer ) : DWORD;
// Performs a Read using this handle. Returns the number of bytes read

const
  MP_WRITE                   = 0;
  MP_READ                    = 1;

implementation



var

  _MPUSBGetDLLVersion  : function () :DWORD; cdecl stdcall;

  // Number of vid & pid matching USB Devices
  _MPUSBGetDeviceCount : function( pVID_PID : PAnsiChar ) : DWORD; cdecl;

  _MPUSBOpen           : function ( instance   : DWORD;
                                    pVID_PID   : PAnsiChar;
                                    pEP        : PAnsiChar;
                                    dwDir      : DWORD;
                                    dwReserved : DWORD ) : THANDLE; cdecl;

  _MPUSBClose          : function ( handle :THANDLE ) : DWORD; cdecl;

  _MPUSBRead           : function (     handle          : THANDLE;
                                        pData           : pointer;
                                        dwLen           : DWORD;
                                    var pLength         : DWORD;
                                        dwMilliseconds  : DWORD  ) : DWORD; cdecl;

  _MPUSBReadInt        : function (     handle         : THANDLE;
                                    var pData          : pointer;
                                        dwLen          : DWORD;
                                    var pLength        : PDWORD;
                                        dwMilliseconds : DWORD   ) : DWORD; cdecl;

  _MPUSBWrite          : function (     handle         : THANDLE;
                                        pData          : pointer;
                                        dwLen          : DWORD;
                                    var pLength        : DWORD;
                                        dwMilliseconds : DWORD ) : DWORD; cdecl;


  UsbDllHandle : THandle = 0;

const

  MillisecondPollingInterval = 100; //Represents 1 ms is hardware
  CharBufSize = 64;

type
  TAnsiCharBuf64 = array[0..CharBufSize-1] of AnsiChar;


function LoadDLL : THandle;
var
  S : string;
begin
  S := 'mpusbapi.dll';
  UsbDllHandle := LoadLibrary( PChar(S) );

  If UsbDllHandle = 0 then
     Raise EArtPic32Usb.CreateFmt(
       'The usb library is required but cannot be loaded. Check that it is installed. (%s)',
       [S]
        );

  @_MPUSBGetDLLVersion := GetProcAddress(UsbDllHandle,'_MPUSBGetDLLVersion');
  Assert(@_MPUSBGetDLLVersion <> nil);

  @_MPUSBGetDeviceCount := GetProcAddress(UsbDllHandle,'_MPUSBGetDeviceCount');
  Assert(@_MPUSBGetDeviceCount <> nil);

  @_MPUSBOpen := GetProcAddress(UsbDllHandle,'_MPUSBOpen');
  Assert(@_MPUSBOpen <> nil);

  @_MPUSBClose := GetProcAddress(UsbDllHandle,'_MPUSBClose');
  Assert(@_MPUSBClose <> nil);

  @_MPUSBRead := GetProcAddress(UsbDllHandle,'_MPUSBRead');
  Assert(@_MPUSBRead <> nil);

  @_MPUSBReadInt := GetProcAddress(UsbDllHandle,'_MPUSBReadInt');
  Assert(@_MPUSBReadInt <> nil);

  @_MPUSBWrite := GetProcAddress(UsbDllHandle,'_MPUSBWrite');
  Assert(@_MPUSBWrite <> nil);

  Result := UsbDllHandle;

end;

procedure NeedDLL;
begin
  If UsbDllHandle = 0 then
    LoadDll;
end;



function Pic32Usb_GetDllVersion : integer;
// Returns a number representing the DLL version.
begin
  NeedDLL;
  Result := _MPUSBGetDLLVersion();
end;


function Pic32Usb_GetDeviceCount( const AVendorProductID : string ) : integer;
// Returns the number of devices with this vendor ID
var
  bufVendorProductID : TAnsiCharBuf64;
begin
  NeedDLL;

  StrPCopy( bufVendorProductID, AnsiString(AVendorProductID) );

  Result := _MPUSBGetDeviceCount( @bufVendorProductID );
end;


function Pic32Usb_Open(
           AInstance : DWORD;
           const AVendorProductID, AEndpointID : string;
           ADirectionCode : integer;
           ARaise : boolean ) : THANDLE;
// Opens an endpoint. Can raise an exception if no valid handle is returned.
var
  bufVendorProductID, bufEndpointID : TAnsiCharBuf64;
begin
  NeedDLL;

  StrPCopy( bufVendorProductID, AnsiString(AVendorProductID) );
  StrPCopy( bufEndpointID, AnsiString(AEndpointID) );

  Result := _MPUSBOpen(
    AInstance,
    @bufVendorProductID,
    @bufEndpointID,
    DWORD(ADirectionCode),
    0 );

  if Result = 0 then
    If ARaise then
      Raise EArtPic32Usb.CreateFmt(
        'Unable to open USB device "%s", endpoint "%s"', [AVendorProductID, AEndpointID]);
end;


procedure Pic32Usb_Close( AHandle : THandle );
begin
  If UsbDllHandle <> 0 then
    _MPUSBClose( AHandle );
end;


function Pic32Usb_Write(
            AHandle              : THANDLE;
            ABufferPtr           : pointer;
            ALengthBytes         : integer ) : DWORD;
// Performs a write using this handle. Returns the number of bytes written
var
  I : integer;
begin
  I := _MPUSBWrite(
    AHandle,
    ABufferPtr,
    DWORD( ALengthBytes ),
    Result,
    MillisecondPollingInterval );
  if I <> 1 then
    Raise EArtPic32Usb.CreateFmt( 'Error performing USB write', []);
end;


function Pic32Usb_Read(
            AHandle              : THANDLE;
            ABufferPtr           : pointer;
            ALengthBytes         : integer ) : DWORD;
// Performs a Read using this handle. Returns the number of bytes read
var
  I : integer;
begin
  I := _MPUSBRead(
    AHandle,
    ABufferPtr,
    DWORD( ALengthBytes ),
    Result,
    MillisecondPollingInterval );
  if I <> 1 then
    Raise EArtPic32Usb.CreateFmt( 'Error performing USB read', []);
end;



initialization
finalization
  If UsbDllHandle <> 0 then
    FreeLibrary(UsbDllHandle)
end.

Not a question, just a statement to help anyone else who might spend hours getting the Microchip PIC USB DLL to work properly with Unicode.

It expects several strings, and although these are simple PAnsiChar, getting the right combination of DLL call convention took me ages. There are a lot of people on the 'net using Delphi (non-Unicode) with this DLL and getting away with murder.

unit UArtPic32USBDriver;

interface

uses
  Windows,
  SysUtils,
  UArtGeneralHwDefs;


type
  EArtPic32Usb = class( EArtGeneralHw );

function Pic32Usb_GetDllVersion : integer;
// Returns a number representing the DLL version.

function Pic32Usb_GetDeviceCount( const AVendorProductID : string ) : integer;
// Returns the number of devices with this vendor ID

function Pic32Usb_Open(
           AInstance : DWORD;
           const AVendorProductID, AEndpointID : string;
           ADirectionCode : integer;
           ARaise         : boolean ) : THANDLE;
// Opens an endpoint. Can raise an exception if no valid handle is returned.


procedure Pic32Usb_Close( AHandle : THandle );
// Closes the device

function Pic32Usb_Write(
            AHandle              : THANDLE;
            ABufferPtr           : pointer;
            ALengthBytes         : integer ) : DWORD;
// Performs a write using this handle. Returns the number of bytes written

function Pic32Usb_Read(
            AHandle              : THANDLE;
            ABufferPtr           : pointer;
            ALengthBytes         : integer ) : DWORD;
// Performs a Read using this handle. Returns the number of bytes read

const
  MP_WRITE                   = 0;
  MP_READ                    = 1;

implementation



var

  _MPUSBGetDLLVersion  : function () :DWORD; cdecl stdcall;

  // Number of vid & pid matching USB Devices
  _MPUSBGetDeviceCount : function( pVID_PID : PAnsiChar ) : DWORD; cdecl;

  _MPUSBOpen           : function ( instance   : DWORD;
                                    pVID_PID   : PAnsiChar;
                                    pEP        : PAnsiChar;
                                    dwDir      : DWORD;
                                    dwReserved : DWORD ) : THANDLE; cdecl;

  _MPUSBClose          : function ( handle :THANDLE ) : DWORD; cdecl;

  _MPUSBRead           : function (     handle          : THANDLE;
                                        pData           : pointer;
                                        dwLen           : DWORD;
                                    var pLength         : DWORD;
                                        dwMilliseconds  : DWORD  ) : DWORD; cdecl;

  _MPUSBReadInt        : function (     handle         : THANDLE;
                                    var pData          : pointer;
                                        dwLen          : DWORD;
                                    var pLength        : PDWORD;
                                        dwMilliseconds : DWORD   ) : DWORD; cdecl;

  _MPUSBWrite          : function (     handle         : THANDLE;
                                        pData          : pointer;
                                        dwLen          : DWORD;
                                    var pLength        : DWORD;
                                        dwMilliseconds : DWORD ) : DWORD; cdecl;


  UsbDllHandle : THandle = 0;

const

  MillisecondPollingInterval = 100; //Represents 1 ms is hardware
  CharBufSize = 64;

type
  TAnsiCharBuf64 = array[0..CharBufSize-1] of AnsiChar;


function LoadDLL : THandle;
var
  S : string;
begin
  S := 'mpusbapi.dll';
  UsbDllHandle := LoadLibrary( PChar(S) );

  If UsbDllHandle = 0 then
     Raise EArtPic32Usb.CreateFmt(
       'The usb library is required but cannot be loaded. Check that it is installed. (%s)',
       [S]
        );

  @_MPUSBGetDLLVersion := GetProcAddress(UsbDllHandle,'_MPUSBGetDLLVersion');
  Assert(@_MPUSBGetDLLVersion <> nil);

  @_MPUSBGetDeviceCount := GetProcAddress(UsbDllHandle,'_MPUSBGetDeviceCount');
  Assert(@_MPUSBGetDeviceCount <> nil);

  @_MPUSBOpen := GetProcAddress(UsbDllHandle,'_MPUSBOpen');
  Assert(@_MPUSBOpen <> nil);

  @_MPUSBClose := GetProcAddress(UsbDllHandle,'_MPUSBClose');
  Assert(@_MPUSBClose <> nil);

  @_MPUSBRead := GetProcAddress(UsbDllHandle,'_MPUSBRead');
  Assert(@_MPUSBRead <> nil);

  @_MPUSBReadInt := GetProcAddress(UsbDllHandle,'_MPUSBReadInt');
  Assert(@_MPUSBReadInt <> nil);

  @_MPUSBWrite := GetProcAddress(UsbDllHandle,'_MPUSBWrite');
  Assert(@_MPUSBWrite <> nil);

  Result := UsbDllHandle;

end;

procedure NeedDLL;
begin
  If UsbDllHandle = 0 then
    LoadDll;
end;



function Pic32Usb_GetDllVersion : integer;
// Returns a number representing the DLL version.
begin
  NeedDLL;
  Result := _MPUSBGetDLLVersion();
end;


function Pic32Usb_GetDeviceCount( const AVendorProductID : string ) : integer;
// Returns the number of devices with this vendor ID
var
  bufVendorProductID : TAnsiCharBuf64;
begin
  NeedDLL;

  StrPCopy( bufVendorProductID, AnsiString(AVendorProductID) );

  Result := _MPUSBGetDeviceCount( @bufVendorProductID );
end;


function Pic32Usb_Open(
           AInstance : DWORD;
           const AVendorProductID, AEndpointID : string;
           ADirectionCode : integer;
           ARaise : boolean ) : THANDLE;
// Opens an endpoint. Can raise an exception if no valid handle is returned.
var
  bufVendorProductID, bufEndpointID : TAnsiCharBuf64;
begin
  NeedDLL;

  StrPCopy( bufVendorProductID, AnsiString(AVendorProductID) );
  StrPCopy( bufEndpointID, AnsiString(AEndpointID) );

  Result := _MPUSBOpen(
    AInstance,
    @bufVendorProductID,
    @bufEndpointID,
    DWORD(ADirectionCode),
    0 );

  if Result = 0 then
    If ARaise then
      Raise EArtPic32Usb.CreateFmt(
        'Unable to open USB device "%s", endpoint "%s"', [AVendorProductID, AEndpointID]);
end;


procedure Pic32Usb_Close( AHandle : THandle );
begin
  If UsbDllHandle <> 0 then
    _MPUSBClose( AHandle );
end;


function Pic32Usb_Write(
            AHandle              : THANDLE;
            ABufferPtr           : pointer;
            ALengthBytes         : integer ) : DWORD;
// Performs a write using this handle. Returns the number of bytes written
var
  I : integer;
begin
  I := _MPUSBWrite(
    AHandle,
    ABufferPtr,
    DWORD( ALengthBytes ),
    Result,
    MillisecondPollingInterval );
  if I <> 1 then
    Raise EArtPic32Usb.CreateFmt( 'Error performing USB write', []);
end;


function Pic32Usb_Read(
            AHandle              : THANDLE;
            ABufferPtr           : pointer;
            ALengthBytes         : integer ) : DWORD;
// Performs a Read using this handle. Returns the number of bytes read
var
  I : integer;
begin
  I := _MPUSBRead(
    AHandle,
    ABufferPtr,
    DWORD( ALengthBytes ),
    Result,
    MillisecondPollingInterval );
  if I <> 1 then
    Raise EArtPic32Usb.CreateFmt( 'Error performing USB read', []);
end;



initialization
finalization
  If UsbDllHandle <> 0 then
    FreeLibrary(UsbDllHandle)
end.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

ぽ尐不点ル 2024-07-29 07:54:54

我会将其作为临时答案发布。 @Brian Frost 可以发布完整的代码。
这个故事的要点是,当您处理需要它的驱动程序时,使用单字节 ANSI 字符串。

StrPCopy( bufVendorProductID, AnsiString(AVendorProductID) );

I'll post this as temporary answer. @Brian Frost can post the full code.
The gist of the story is to use single byte ANSI string when you are dealing with a driver that expects it.

StrPCopy( bufVendorProductID, AnsiString(AVendorProductID) );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文