エンジニア風味 (Engineer-taste)

電子系エンジニアのメモ帳

FTDIデバイスを複数使う

複数のFTDIデバイスを1台のPCに接続すると、制御がややこしくなります。また、FT2232Dのように複数のチャンネルを持つデバイスもあります。
制御のコツについて、まとめてみました。

1.デバイスを把握する
 FTDIが配布するプログラムFT_Progを起動します。持っていない、と言う場合はこちらからダウンロードしましょう。

f:id:engineer-paju:20190317172915p:plain
FT_Progのダウンロード

インストールして、起動します。
FTDIデバイスをPCに接続します。一度に複数個、接続するとどれかわからなくなるので、1ケずつ接続します。

f:id:engineer-paju:20190317173551p:plain
FT_Progの起動画面

左上の虫眼鏡マークをクリックするとデバイスを検索して、情報が表示されます。
必要な情報は、
 ① Product Description
 ② Serial Number
 ③ Location ID
です。これらを用いるときは、FT_Openでなく、FT_OpenExを使います。dllが古いと動かないので注意です。

2.プログラミング

① Product Descriptionを指定して接続する場合のプログラム  

#include<windows.h>
#include<stdio.h>
#include<conio.h>
#include"ftd2xx.h"

main()
{
	FT_HANDLE	hft;	
	BYTE x;
	DWORD n;
	int i;

	if( FT_OK != FT_OpenEx("FT232R USB UART", FT_OPEN_BY_DESCRIPTION, &hft))
	{
		printf("open error\n");
		return 0;
	}

	FT_SetBaudRate( hft, 9600 );		// 転送レート指定

	FT_SetBitMode( hft, 0xff,1);		// 出力8ビット

	printf("オンオフ動作\n");
	for( i = 0 ; i< 10 ; i++ ){			// 10回オン・オフする
		printf( "%d \n", i );	
		x = 0xff;

		FT_Write( hft, &x, 1, &n ); 

		Sleep( 500 );					// wait 500ミリ秒
		x = 0;
		FT_Write( hft, &x, 1, &n);
		Sleep( 500 );					// wait 500ミリ秒
	}
	
	FT_Close( hft );

	return(0);
}


② Serial Numberを用いて接続する場合のプログラム
 Serial NumberはFTDIチップそのものではなく、外付けのメモリに記憶されています。ですので、メモリが搭載されていないモジュール(秋月電子のFT2232Dなど)では、Serial Numberで指定する方法は使えません。プログラムは下記のとおりです。

#include<windows.h>
#include<stdio.h>
#include<conio.h>
#include"ftd2xx.h"

main()
{
	FT_HANDLE	hft;	
	BYTE x;
	DWORD n;
	int i;

	if( FT_OK != FT_OpenEx("A800e3ia", FT_OPEN_BY_SERIAL_NUMBER, &hft))
	{
		printf("open error\n");
		return 0;
	}

  // 中略
	
	FT_Close( hft );

	return(0);
}


③ Location IDを用いて接続、制御するプログラム
 Location IDは、PCのUSBコネクタに「ある程度」紐付けされているようです。ただし、1chもののFT232Rを接続したときには0x22だったものが、2chもののFT2232Dを接続すると0x221になったりします(FT2232DのB-chを指定するときは0x222とします。0x221,0x222でゼロ始まりでないので注意)。
 FT232Hを接続すると、0x34になったりして、絶対的な紐付けではないので、デバイスを変える際は確認したほうがよいと思います。
 プログラムは下記のとおりです。

#include<windows.h>
#include<stdio.h>
#include<conio.h>
#include"ftd2xx.h"

main()
{
	FT_HANDLE	hft;	
	BYTE x;
	DWORD n;
	int i;
	long dwLoc;   // Location ID用


	dwLoc=0x22;  // Location ID 指定
	if( FT_OK != FT_OpenEx((void*)dwLoc, FT_OPEN_BY_LOCATION, &hft))
	{
		printf("open error\n");
		return 0;
	}

  // 中略
	
	FT_Close( hft );

	return(0);
}


3.結局、どれがおすすめなのか?

 ① Product Description
  これは、同じデバイスだと、カブるのが難です。
 ② Serial Number
  メモリが載っていれば使える。しかし、複数chのデバイス内で指定ができません。
 ③ Location ID
  同じUSBポートに同じデバイスを接続するのであれば、これがお勧めです。複数chにも対応できます。

なお、複数chを持つデバイスを1つだけ使いたい、chの指定をしたい場合は、FT_Openを使って、

  // 前略

main()
{
	FT_HANDLE	hft0; // 1ch 用ハンドル
	FT_HANDLE	hft1; // 2ch 用ハンドル
	BYTE x;
	DWORD n;
	int i;

if( FT_OK != FT_Open( 0, &hft0)) // 1chめをオープン
	{
		printf("open error ch 0 \n");
		return 0;
	}

if( FT_OK != FT_Open( 1, &hft1)) // 2chめをオープン
	{
		printf("open error ch 1 \n");
		return 0;
	}

// 中略

	FT_Close( hft0 );
	FT_Close( hft1 );

	return(0);
}

とすれば、複数chの使い分けができます。2chめだけ使うことも可能です。