Как вызвать Microchip PIC USB DLL с помощью Delphi 2009 - PullRequest
4 голосов
/ 05 июня 2009

Не вопрос, а просто заявление, чтобы помочь кому-либо, кто мог бы потратить часы на то, чтобы 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.

1 Ответ

1 голос
/ 07 июня 2009

Я опубликую это как временный ответ. @ Брайан Фрост может опубликовать полный код. Суть этой истории заключается в использовании однобайтовой строки ANSI, когда вы имеете дело с драйвером, который этого ожидает.

StrPCopy( bufVendorProductID, AnsiString(AVendorProductID) );
...