##1.はじめに
昨今、データ通信の多くはシリアルになっており、デバイスへの入出力もI2Cなどが使われることが多くなっています。
ですが、一部のデバイスにおいて、8ビットマイコン(死語?)に接続することを前提としたようなものもあります。
この場合に、データバスに8ビットを割り振り、WE(ライトイネーブル)、RE(リードイネーブル)、CS(チップセレクト)といった制御信号を駆使してやり取りを行うことになります。
FTDI(Future Technology Device Internatinal Ltd.)社のUSB to パラレルのデバイス(モジュール)は、PCから安全にデジタル信号を出したり、取り込んだりするのに使われています。
本稿では、MATLABスクリプトにより、FTDIデバイスの2つ(または、それ以上)のポートを用いてデータの入出力を行う手法について、まとめてみました。
##2.既に公開されている資料について
MathWorks の MATLAB File Exchange にRoger M. Ellingson氏の投稿した Test_FTD2XX_NET_BitBang.m があります。これは、FTDI社が提供している .NET用のライブラリ FTD2XX_NET.dll を用いて、MATLABによりFTDIデバイスを操作するものです。
手順は
1)まずFTDIのページからFTD2XX_NET.dll をダウンロード します。
2)dllファイルをPCのどこかわかりやすいところに置きます(ここではCドライブ直下に置いたとして話を進めます)。
3)FTDIデバイスとPCをUSBケーブルで接続します。
4)ここからはMATLAB上での作業となります。まず、dllの場所を指定します。
f = NET.addAssembly('C:\FTD2XX_NET.dll');
以下はTest_FTD2XX_NET_BitBang.m にあるので省略しますが、
methodsview( 'FTD2XX_NET.FTDI');
これを実行しますと、ファンクション一覧が表示されるので便利です。
(FTD2XX_NET.dllは正式なマニュアルがないらしいので、かなり参考になります)。
##3.複数のポートの使い方
Test_FTD2XX_NET_BitBang.m は1つのポートからデータを出力する場合、また、同じ作者の、FTD2XX_NET_Write_GetPinStatesは、1つのポートから入出力を行う例が示されています(読み込みにはReadでなくGetPinStates を使うことに注意)。
しかし、複数のポートを使う例が示されていません。
最も簡単な例は、ポートのインデックスを使うもので、
% dllの場所を指定する
f = NET.addAssembly('C:\FTD2XX_NET.dll');
% 2つのポートへのFTDIプロパティを割り当てる
f0=FTD2XX_NET.FTDI;
f1=FTD2XX_NET.FTDI;
pause(0.1);%準備ができるのを待つ
% ポートを開く
OpenByIndex(f0,0);
OpenByIndex(f1,1);
allBitsOutputMask = uint8(255); % '1' bit is output
bitBangMode = uint8(1); % '1' mode is async bitbang
resetMode = uint8(0); % terminate bitbang
mixBitsMask = uint8(15); % '1'=output, d7-d=input, d3-d0=output
r = SetBitMode( f0,0,resetMode);
r = SetBitMode( f1,0,resetMode);
SetBaudRate(f0,115200);%ボーレート(転送レート)設定
SetBaudRate(f1,115200);%ボーレート(転送レート)設定
% 入出力指定 ポート0は全ビット出力、ポート1は下4ビットが出力
r = SetBitMode( f0, allBitsOutputMask, bitBangMode);
r = SetBitMode( f1, mixBitsMask, bitBangMode);
%%% このあたりで、データの入出力を行う %%%
%ポートのクローズ
r = Close(f0);
r = Close(f1);
というようになります。
##4.ポートの指定方法
ポートの指定ですが、上記の方法はインデックスで指定しました。
インデックスでの指定は簡単で良いのですが、例えばFTDIデバイスを複数使うような場合には
どのデバイスのポートなのかわからなくなります(複数使う人は、それほどいるとは思いませんが)。
この場合に、ロケーションIDで指定する場合と、シリアルナンバーで指定する方法があります。
ロケーションIDで指定するにはロケーションIDがどうなっているかを調べる必要がありますが、そのためにはFTDIが用意しているユーティリティであるFT_Progを使う必要があります。
FT_Progをダウンロードしてきて、起動します。
虫眼鏡アイコンをクリックします(FTDiデバイスは接続しておくこと)。
Property,Valueのところで、Location IDを見ると、'0x111' とあります。
今、デバイスがFT2232Hで2ポートあるので、Location ID は'0x111' '0x112'の
2つとなります。
MATLAB でのスクリプトは、
% dllの場所を指定する
f = NET.addAssembly('C:\FTD2XX_NET.dll');
% 2つのポートへの を割り当てる
f0=FTD2XX_NET.FTDI;
f1=FTD2XX_NET.FTDI;
pause(0.1);%準備ができるのを待つ
dwLoc0=hex2dec('111');
dwLoc1=hex2dec('112');
% ポートを開く
r = OpenByLocation(f0,dwLoc0);
r = OpenByLocation(f1,dwLoc1);
%%% 以下、同じです %%%
となります。
ロケーションIDで指定する場合には、PCのどのUSBコネクタに接続するかで、ロケーションIDが変わるため、注意が必要です(毎回同じところに挿せばよいという話も)。
どこに挿しても、特定のFTDIデバイスの特定のポートが指定されるようにしたい、という場合には、シリアルナンバーで指定する必要があります。
先ほどのFT_Progにもシリアルナンバーは表示されています。
今、ここでは'FT2OZ2EO'となっています。この場合に1つめのポートのシリアルナンバーは、
これに'A'がついて、'FT2OZ2EOA'、2つめのポートのシリアルナンバーは'B'がついて、'FT2OZ2EOB'となります。
MATLABでシリアルナンバーを取得して、2つのポートを用いて読み書きする例を以下に示します。
f = NET.addAssembly('C:\FTD2XX_NET.dll');
f0=FTD2XX_NET.FTDI;
% 接続されているデバイスのch数がchsに入る
% FT4232の場合は4となる
% (fo,0)のゼロは便宜上入力
[r,chs]=GetNumberOfDevices(f0,0)
% シリアルナンバーを取得する
for t=0:chs-1
% fn = FTD2XX_NET.FTDI;
dum=['f' num2str(t) '=FTD2XX_NET.FTDI;'];
eval(dum);
%インデックス番号でポート接続
% r = OpenByIndex(fn,n);
dum=['r=OpenByIndex(f' num2str(t) ',' num2str(t) ');'];
eval(dum);
% シリアルナンバーを取得する
% [r,sn] = GetSerialNumber(fn,0);
dum=['[r,s' num2str(t) ']=GetSerialNumber(f' num2str(t) ');'];
eval(dum);
%ポートを閉じる
% r = Close(fn);
dum=['r=Close(f' num2str(t) ');'];
eval(dum);
end
% これでs0,s1,...にシリアルナンバーが入っている
%%% s0 と s1 を使ってデータのやり取りをする
r = OpenBySerialNumber(f0,s0);
r = OpenBySerialNumber(f1,s1);
pause(0.1);
allBitsOutputMask = uint8(255); % '1' bit is output
bitBangMode = uint8(1); % '1' mode is async bitbang
resetMode = uint8(0); % terminate bitbang
mixBitsMask = uint8(15); % '1'=output, d7-d=input, d3-d0=output
r = SetBitMode( f0,0,resetMode);
r = SetBitMode( f1,0,resetMode);
SetBaudRate(f0,115200);%ボーレート(転送レート)設定
SetBaudRate(f1,115200);%ボーレート(転送レート)設定
r = SetBitMode( f0, allBitsOutputMask, bitBangMode);
r = SetBitMode( f1, mixBitsMask, bitBangMode);
x = uint8([0,0,0]);%FTDIからポートに出力する値を入れる場所を用意
for n=0:5
t=0;
x(1) =uint8(t);%符号なし8ビットにする
r = Write( f0, x, 1, 0);%書き出す AD0-7
t=0;
x(1) =uint8(t);%符号なし8ビットにする
r = Write( f0, x, 1, 0);%書き出す
m=0;
x(1) =bitand(uint8(m),15);%符号なし8ビットにする
r = Write( f1, x, 1, 0);%書き出す
m=15;
x(1) =bitand(uint8(m),15);%符号なし8ビットにする
r = Write( f1, x, 1, 0);%書き出す
[~,pinStates] = GetPinStates( f1, 0);% 4bit 読み込み
bitshift(pinStates,-4)
end
r = Close(f0);
r = Close(f1);
ちなみに、秋月電子で入手できるFT2232Dですが、シリアルナンバーを記憶するためのメモリが実装されていません。ですので、シリアルナンバーは使えないはずですが、上記のスクリプトを実行させると、2つのポートは 'A' , 'B' と識別されます。FT2232Dを1つだけ使う分には問題ないかもしれません。
以上です。
お疲れさまでした。