見出し画像

DelphiでFT232Hを使ってみる(1)

0.はじめに


先日の記事(DelphiでLCDに描画する)で「USBからI2Cを使うには、HIDタイプか特定コマンドで動作させる2種類がある」と書きましたが、もう一つあることがわかりました。
MPSSE(Multi-Protocol Synchronous Serial Engine)なんて初めて聞きましたが、これであればRS232Cだけでなく、I2CやSPIもできるとの事なので、興味本位で秋月電子様からFT232Hのモジュールを購入してみました。

1.まずは動作させてみる


購入して最初にやることは、同梱されているコネクターとJPピンのはんだ付けです。とりあえずJP3とJP4はショートさせています。
あとはFTDI社のホームページからCDM212364_Setup.zip(2022年2月1日現在)をダウンロードしてインストールするだけです。
  Drivers - FTDI (ftdichip.com)

動作しているかどうかを確認するために、簡易的にJ2の7-8番ピンをショートしてRS232Cで通信をさせてみます。なお、基板上のJ1/J2のシルクが小さくて見づらいですが、JP4側のコネクターがJ2-1になります。

ピン配列

Tera Termでもいいのかもしれませんが、自分でAsyncProを使ってCOMポートをオープンして、送信、受信するソフトを書いて確認しました。
ここまでは、特別な設定も必要なく、問題もなくて順調に進みました。

2.デバイス情報を入手する


次はこのモジュールの制御方法を知るために、IDなどの情報を得るソフトを作ってみます。
FTDI社のホームページからDelphiのデモソフトをダウンロードすると、D2XXUnit.pasが提供されているものの、それを経由してDLLを使わなければならないようで、初級者には高い壁がありそうです。
どこから手を付けたらいいのかわからないので、とりあえずFTDI社デモソフトを実行してデバイス情報を見てみると、Device数、Description、Serial Noの3種類しか表示されず、しかも文字化けしています。

FTDI社デモソフトの結果

文字化けを直そうとして、一文字ずつ読み込んでAnsiCharに変換して表示させた結果が下記となります。一応読めますので、そのままとしておきます。

Descriptionの修正結果

調べてみるとIDなどの他の情報も存在するようで、富永様(DEKO様?)の第29回デベロッパーキャンプの資料からダウンロードさせていただいて、見様見真似で何とか下記まで表示させることができました。

富永様を参考にしたソフトの結果

という事は、Descriptionの表示もおかしいですし、FTDI社デモソフト以外にも情報収集の手段があることになり、非常に見づらいD2XXUnit.pasを老眼に鞭打って見てみると、確かにAPIが設定されていました。
デバイス数などのfunction名は”GetFTDevicexx”のようになっていますが、他に必要なfunction名は”Get_USB_Device_xx”に変わっていました。
初級者には混乱の元なので、名前は統一して欲しいですね。

Function GetFTDeviceCount : FT_Result;
Function GetFTDeviceSerialNo(DeviceIndex:DWord) : FT_Result;
Function GetFTDeviceDescription(DeviceIndex:DWord) : FT_Result;
Function GetFTDeviceLocation(DeviceIndex:DWord) : FT_Result;
//
Function Create_USB_Device_List : FT_Result;
Function Get_USB_Device_List : FT_Result;
Function Get_USB_Device_List_Detail(Index:DWord) : FT_Result;

D2XXUnit.pasとアプリケーションノート「D2XX Programmer's Guide」を見ながら、試行錯誤して作った結果が下記となります。
実はここまで来るのに何日もかかっているんですよね。。。

D2XXUnit.pasを利用した結果(Descriptionは修正済み)

Descriptionの結果についてですが、FTDI社デモソフトの変換結果は途中の文字が欠落しているように見えます。悲しいかな、初級者の限界でしょうか、この解決のためにポインターを使うなんて考えもしませんでしたし、"strpas"なんて命令は今まで見たこともありませんでした。

Memo1.Lines.Add('Serial No : '+strpas(PAnsiChar(@USB_Device_Info_Node.SerialNumber[0])));
Memo1.Lines.Add('Description : '+strpas(PAnsiChar(@USB_Device_Info_Node.Description[0])));

今回は富永様のソフトを参考にさせていただき、理解できていないまま正しい表示ができるようにはしましたが、初級者の壁を破れるような参考書をEmbarcaderoには期待したいです。
今回は色々と苦労したので、参考になればと思いコードを掲載します。

implementation

uses D2XXUnit;

{$R *.dfm}

procedure TFrmMain.btnDeviceClick(Sender: TObject);
var
  DevIndex:Byte;
  dwDriverVer:DWORD;
  dwLibraryVer:DWORD;
  Res:Byte;
begin
  Memo1.Clear;
//Device数
  Res:=GetFTDeviceCount;
  if Res=0 then
    Memo1.Lines.Add('Device Count : '+inttostr(FT_Device_Count))
    else Memo1.Lines.Add('No Device');
//Indexの設定
  DevIndex:=FT_Device_Count-1;
//Device Listの作成
  Res:=Create_USB_Device_List;
  Res:=Get_USB_Device_List;
//Deviceの読み出し
  Res:=Get_USB_Device_List_Detail(DevIndex);
  if Res=0 then
    begin
      Memo1.Lines.Add('Handle : '+inttostr(USB_Device_Info_Node.DeviceHandle));
      Memo1.Lines.Add('Flags : '+inttostr(USB_Device_Info_Node.Flags));
      case USB_Device_Info_Node.DeviceType of
        0:Memo1.Lines.Add('Device Type : FT232BM');
        1:Memo1.Lines.Add('Device Type : FT232AM');
        2:Memo1.Lines.Add('Device Type : FT100AX');
        3:Memo1.Lines.Add('Device Type : UNKNOWN');
        4:Memo1.Lines.Add('Device Type : FT2232C');
        5:Memo1.Lines.Add('Device Type : FT232R');
        6:Memo1.Lines.Add('Device Type : FT2232H');
        7:Memo1.Lines.Add('Device Type : FT4232H');
        8:Memo1.Lines.Add('Device Type : FT232H');
        9:Memo1.Lines.Add('Device Type : X SERIES');
      end;
      Memo1.Lines.Add('Vender ID : 0x'+copy(inttohex(USB_Device_Info_Node.ID),1,4));
      Memo1.Lines.Add('Product ID : 0x'+copy(inttohex(USB_Device_Info_Node.ID),5,4));
      Memo1.Lines.Add('Location ID : 0x'+inttohex(USB_Device_Info_Node.LocID,2));
      Memo1.Lines.Add('Serial No : '+strpas(PAnsiChar(@USB_Device_Info_Node.SerialNumber[0])));
      Memo1.Lines.Add('Description : '+strpas(PAnsiChar(@USB_Device_Info_Node.Description[0])));
    end;

//Versionを読むために一旦OPEN
  Open_USB_Device;
//DLL Version
  Res:=Get_USB_Driver_Version(@dwDriverVer);
  if Res=0 then
    Memo1.Lines.Add('Driver Version : '+inttohex(dwDriverVer,5));
//Library Version
  Res:=Get_USB_Library_Version(@dwLibraryVer);
  if Res=0 then
    Memo1.Lines.Add('Library Version : '+inttohex(dwLibraryVer,5));
//Close
  Close_USB_Device;

end;

次回は、BitBangModeで動作をさせてみます。

この記事が気に入ったらサポートをしてみませんか?