2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MATLABでFTDIデバイスの複数のポートを使う

Last updated at Posted at 2022-09-24

##1.はじめに
昨今、データ通信の多くはシリアルになっており、デバイスへの入出力もI2Cなどが使われることが多くなっています。
ですが、一部のデバイスにおいて、8ビットマイコン(死語?)に接続することを前提としたようなものもあります。
この場合に、データバスに8ビットを割り振り、WE(ライトイネーブル)、RE(リードイネーブル)、CS(チップセレクト)といった制御信号を駆使してやり取りを行うことになります。

Qiitaイラスト220924.png

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の場所を指定します。

xx.m
f = NET.addAssembly('C:\FTD2XX_NET.dll');

以下はTest_FTD2XX_NET_BitBang.m にあるので省略しますが、

yy.m
methodsview( 'FTD2XX_NET.FTDI');

これを実行しますと、ファンクション一覧が表示されるので便利です。
(FTD2XX_NET.dllは正式なマニュアルがないらしいので、かなり参考になります)。

##3.複数のポートの使い方
Test_FTD2XX_NET_BitBang.m は1つのポートからデータを出力する場合、また、同じ作者の、FTD2XX_NET_Write_GetPinStatesは、1つのポートから入出力を行う例が示されています(読み込みにはReadでなくGetPinStates を使うことに注意)。
しかし、複数のポートを使う例が示されていません。

最も簡単な例は、ポートのインデックスを使うもので、

cde.m
% 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デバイスは接続しておくこと)。

FTProg1.png

Property,Valueのところで、Location IDを見ると、'0x111' とあります。

FTProg2.png

今、デバイスがFT2232Hで2ポートあるので、Location ID は'0x111' '0x112'の
2つとなります。
MATLAB でのスクリプトは、

cde.m
% 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にもシリアルナンバーは表示されています。

SerialNumber1.png

今、ここでは'FT2OZ2EO'となっています。この場合に1つめのポートのシリアルナンバーは、
これに'A'がついて、'FT2OZ2EOA'、2つめのポートのシリアルナンバーは'B'がついて、'FT2OZ2EOB'となります。
MATLABでシリアルナンバーを取得して、2つのポートを用いて読み書きする例を以下に示します。

serialport_open.m
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つだけ使う分には問題ないかもしれません。

以上です。
お疲れさまでした。

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?