BMオプションをプログラムから変更する方法を解説します。

SerialPortクラスを使って高速通信を行うには、BMオプションと呼ばれる待ち時間の変更がほぼ必須です。この設定はデバイスマネージャーから行うことができますが、これを毎回手作業でやるのは非常に面倒です。
本記事では、BMオプションの設定変更をプログラムから行う方法を解説します。
目次
本記事で紹介するBMオプション変更の仕組み

BMオプションをプログラムから変更する方法は3つ考えられます。
- SerialPortの設定変更をする方法
- FTDIドライバのAPIを直接叩く方法
- FTDIドライバのラッパライブラリを利用する方法
ほとんどの方は①のSerialPortから設定変更できないかと考えると思いますが、BMオプションはベンダ独自のオプションであり、汎用的なクラスのSerialPortからは変更できません。
BMオプションはFTDI社のドライバのオプションですので、②か③の方法を使う必要があります。本記事では利用者が多いと思われる③の方法をC#バージョンでご紹介します。
なお、②の方法については下記サイト様をご参考になさってください。
WindowsUSB-Serial(RS232C)の応答速度(訂正) – マイコン工作入門
FTDIの.NETラッパライブラリのダウンロード
下記URLの「managed .NET wrapper」リンクより、ライブラリをダウンロードしてください。
https://www.ftdichip.com/Support/SoftwareExamples/CodeExamples/CSharp.htm

2019年8月現在、下記のファイルがダウンロードできました。
FTDIの.NETラッパライブラリを参照に追加
Visual Studioを立ち上げて、ダウンロードしたファイルの中にある下記のライブラリを参照に追加してください。
.NETラッパライブラリの使い方
ここからは具体的にプログラムの書き方を説明します。
BMオプションの設定(シリアルポートの初期化)
BMオプションの設定は、FTDIクラスのsetLatency()メソッドを使います。
このメソッドはシリアルポートの初期化時に使うので、具体的な初期化コードをお見せします。下記のコードは”COM3″を初期化する時のコードです。
// ポート名
string portName = "COM3";
// FTDIクラス(SerialPort相当)を生成
FTDI port = new FTDI();
// ポートの数を取得
uint portNum = 0;
FT_STATUS ret = port.GetNumberOfDevices(ref portNum);
if (ret != FT_STATUS.FT_OK) {
throw new InvalidOperationException("Could not get port size.");
}
// 指定の名前のポートを探す
for (uint i = 0; i < portNum; i++) {
// indexで指定したポートを開き、名前をチェックする
ret = port.OpenByIndex(i);
if (ret != FT_STATUS.FT_OK) {
throw new InvalidOperationException("Could not get a port.");
}
string tmp;
ret = port.GetCOMPort(out tmp);
if (ret != FT_STATUS.FT_OK) {
throw new InvalidOperationException("Could not get port name.");
}
if (tmp == portName) {
// 指定の名前のポートが見つかったので、各種設定を行う
// Baudrate の設定
ret = port.SetBaudRate(57600);
if (ret != FT_STATUS.FT_OK) {
throw new InvalidOperationException("Could not set BaudRate.");
}
// DataBits, StopBits, Parity の設定
ret = port.SetDataCharacteristics(
FTDI.FT_DATA_BITS.FT_BITS_8,
FTDI.FT_STOP_BITS.FT_STOP_BITS_1,
FTDI.FT_PARITY.FT_PARITY_EVEN);
if (ret != FT_STATUS.FT_OK) {
throw new InvalidOperationException("Could not set DataCharacteristcs.");
}
// ReadTimeout, WriteTimeout の設定
ret = port.SetTimeouts(1000, 1000);
if (ret != FT_STATUS.FT_OK) {
throw new InvalidOperationException("Could not set Timeouts.");
}
// BMオプションの設定
ret = port.SetLatency(1);
if (ret != FT_STATUS.FT_OK) {
throw new InvalidOperationException("Could not set LatencyTimeout.");
}
break;
} else {
port.Close();
}
}
if (!port.IsOpen) {
throw new InvalidOperationException("Could not found the port.");
}
BMオプションの設定以外にも、通信速度やパリティといったよく使う設定のコードも入れておきましたので、ご参考になさってください。
送受信する方法
BMオプションの変更方法は以上ですが、送受信する時のAPIがSerialPortと異なるので、そちらもご紹介しておきます。
送信時
void Send(byte[] req, int length) {
// 送信
uint numBytesWritten = 0;
port.Write(req, length, ref numBytesWritten);
if (length != numBytesWritten) {
// TODO エラー処理をここに書く
}
}
受信時
byte[] Receive(byte[] req, uint length) {
byte[] res = new byte[length];
uint numBytesRead = 0;
port.Read(res, length, ref numBytesRead);
// 長さチェック
if (numBytesRead < length) {
// TODO エラー処理をここに書く
}
return res;
}
その他のAPIの使用方法
ここまでにご紹介した方法で一通りの使い方はできると思いますが、より使いこなしたい方は、公式のドキュメントをご参照ください。APIはC言語ベースですが、内容は理解できるかと思います。
下記URLの「D2XX Programmer’s Guide」をクリックしてください。
https://www.ftdichip.com/Support/Documents/ProgramGuides.htm
終わりに
本記事ではFTDIドライバのBMオプションをC#プログラムから変更する方法をご紹介しました。この方法を使って、手作業からの煩わしさから解消されましょう。