FT245RL用DLLの使い方 2007.10.03(水)〜
著作者名: 中野 良知 作成開始: 2007.10.02(火) 最新更新: 2008.03.06(木)
目次 1. 概要 2. 参考資料 3. DLLの入手とインストール 3.1. 入手 3.2. インストール 4. FTD2XX.DLL呼び出し方法 4.1. unsafeの許可 4.2. FTD2XX.DLLの参照定義の場所 4.3. FT Open (オープン) 4.4. FT Close (クローズ) 4.5. FT_SetBitMode (BitBangモード設定) 4.6. FT_SetBaudRate (ボーレート設定) 4.7. FT_Write (ポート出力) 4.8. FT_GetBitMode (ポート入力) 4.9. FT_Read (データ読み出し) 4.10. FT_ListDevices (デバイス数の取得) 4.11. FT_EE_Read (EEPROMの読出し) 5. プログラム例1(パルス出力) 6. プログラム例2(クロックとシリアルデータ出力) 7. プログラム例3(入出力) 1. 概要 VC#でFT245RL用のDLLを利用する方法です。 FT245RL・FT232RLの実験記事から資料を抜粋しました。 使用したDLLは、FTDIの"FTD2XX.DLL"です。 FT245RLモジュールは秋月製です。 VC#は、Microsoft Visual C# 2005 Express Editionを使用しました。 2. 参考資料 FTDIの「D2XX Programmer's Guide」(D2XXPG33.pdf)。 3. DLLの入手とインストール 3.1. 入手 DLLは、FTDIのWebサイトの[Driver][D2XX]から「CDM 2.00.00.zip」をダウンロード しました。 2007.10.03現在の最新版は「CDM 2.02.04.zip」です。 3.2. インストール ダウンロードした「CDM 2.00.00.zip」を解凍すると、デバイスドライバーやDLLが 入ったフォルダーが展開されます。 モジュールにUSBケーブルを接続し、新しいハードウェアーが検出されてから、 解凍したドライバーが入っているフォルダーを指定し、 デバイスドライバーをインストールします。 インストール操作は2回行います。(DCXX BitBang modeとVCP modeの2回分) 4. FTD2XX.DLL呼び出し方法 4.1. unsafeの許可 関数の引数でポインターを渡す場合には、 コンパイラーでunsafeの許可を設定します。 1) [プロジェクト]の [プロパティ]をクリック。 2) [ビルド] のタグをクリック。 3) 全般の[アンセーフ コードの許可] をチェックオン。 この設定により unsafe private static extern UInt32 FT_Open(Int16 DeviceNumber, UInt32 *ftHandle); のように unsafe が付いた関数が使えます。 4.2. FTD2XX.DLLの参照定義の場所 VC# Appのプロジェクト名が"FT245"のForm1.csの一部です。 1) using System.Runtime.InteropServices;を冒頭部に追加します。 2) DLLの参照用定義は class Form1 の {} 内に記述します。 例: using System; using System.Collections.Generic; ...... // [DllImport("ftd2xx.dll")]参照用のusing指定 using System.Runtime.InteropServices; namespace FT245 { public partial class Form1 : Form { // public変数や定数定義等を記述 ...... public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // App立上げ時の初期化処理等を記述 ...... } // イベント処理や関数等を記述 ...... ...... // ========================================== // DLL参照定義 // ========================================== // FT Open [DllImport("ftd2xx.dll")] unsafe private static extern UInt32 FT_Open( Int16 DeviceNumber, UInt32 *ftHandle ); // FT Close [DllImport("ftd2xx.dll")] private static extern UInt32 FT_Close(UInt32 ftHandle); ...... ...... } } 4.3. FT Open (オープン) FT245RLとApp間の通信を開きます。 DLL参照定義: // FT Open [DllImport("ftd2xx.dll")] unsafe private static extern UInt32 FT_Open( Int16 DeviceNumber, UInt32 *ftHandle ); 使用例: UInt32 ftHandle; UInt32 ftStatus; // FT245RLとの通信を開く ftStatus = FT_Open(0, &ftHandle); if (ftStatus != FT_OK) { MessageBox.Show("注意", "FT245との通信に失敗しました。"); return; } *ftHandleにデバイスハンドル値が代入されます。 4.4. FT Close (クローズ) FT245RLとAPP間の通信を閉じます。 DLL参照定義: // FT Close [DllImport("ftd2xx.dll")] private static extern UInt32 FT_Close(UInt32 ftHandle); 使用例: // FT245との通信を閉じる ftStatus = FT_Close(ftHandle); 引数はFT_Open()で取得したデバイスハンドルです。 4.5. FT_SetBitMode (BitBangモード設定) FT245RLのモードを切り換えます。 ハンドシェークモードは、RXF#、RD#、TXF#、WRの制御信号を用いて、8ビットデータ バスからデータの授受を行います。 BitBangモードでは、8ビットデータバスが汎用ポートとして利用出来ます。 DLL参照定義: // FT_SetBitMode [DllImport("ftd2xx.dll")] private static extern UInt32 FT_SetBitMode ( UInt32 ftHandle, Byte Mask, Byte Mode ); 使用例: // BitBangモード設定。b1-b7=Out, b0=In ftStatus = FT_SetBitMode(ftHandle, 0xFE, 0x01); 第1引数はデバイスハンドルです。 第2引数でビット毎に入出力方向を指定します。 1=出力、0=入力 第3引数でBitBangモードとデフォルトモードを指定します。 1=BitBangモード、0=ハンドシェークモード 4.6. FT_SetBaudRate (ボーレート設定) BitBangモードでFIFOのデータを出力する時のボーレートを設定します。 データシートでは設定値の16倍のバイト転送レートが得られるとありますが、 実際には大きく変動する為、使用にあたっては注意を要します。 DLL参照定義: // FT_SetBaudRate [DllImport("ftd2xx.dll")] private static extern UInt32 FT_SetBaudRate ( UInt32 ftHandle, UInt32 BaudRate ); 使用例: // ボーレート設定 ftStatus = FT_SetBaudRate(ftHandle, 19200); 第1引数はデバイスハンドルです。 第2引数はボーレートです。 4.7. FT_Write (ポート出力) FT245RLのFIFOバッファーへデータを書き込み(転送)します。 DLL参照定義: // FT_Write [DllImport("ftd2xx.dll")] unsafe private static extern UInt32 FT_Write ( UInt32 ftHandle, [MarshalAs(UnmanagedType.LPArray)] byte[] bdata, UInt32 BufferSize, UInt32 *BytesWriten ); 使用例: // 10バイトのデータを出力 ftStatus = FT_Write(ftHandle, buf, 10, &writesize); 第1引数はデバイスハンドルです。 第2引数はデータ配列の参照先です。 第3引数はFT245RLに書き込みバイト数です。 第4引数は書き込めたバイト数を返す変数の参照先です。 4.8. FT_GetBitMode (ポート入力) BitBangモードでFT245RLの汎用ポート入力を取得します。 DLL参照定義: // FT_GetBitMode(ポート入力用) [DllImport("ftd2xx.dll")] unsafe private static extern UInt32 FT_GetBitMode( UInt32 ftHandle, [MarshalAs(UnmanagedType.LPArray)] byte[] bdata ); 使用例: Byte[] buf = new Byte[1]; ftStatus = FT_GetBitMode(ftHandle, buf); 4.9. FT_Read (データ読み出し) FT245RLのFIFOからデータを読み出します。 DLL参照定義: // FT_Read [DllImport("ftd2xx.dll")] unsafe private static extern UInt32 FT_Read( UInt32 lngHandle, [MarshalAs(UnmanagedType.LPArray)] byte[] bdata, UInt32 lngBufferSize, UInt32* lngBytesReturned ); 使用例: while (true) { // ポート入力 ftStatus = FT_Read(ftHandle, data, 64, &readsize); data[0] >>= 4; // 下位4ビットへシフト // ポート出力 ftStatus = FT_Write(ftHandle, data, 1, &writesize); Application.DoEvents(); // メニュークリック等を許可 if (stop_flg) break; // stopメニュークリックイベントで // フラグがセットされたら終了 } 4.10. FT_ListDevices (デバイス数の取得) DLL参照定義: // FT_ListDevices [DllImport("ftd2xx.dll")] unsafe private static extern UInt32 FT_ListDevices( void* arg1, void* arg2, UInt32 dwFlags); 使用例: 接続しているデバイス数を取得します。 public const UInt32 FT_LIST_NUMBER_ONLY = 0x80000000; UInt32 numDevs; ftStatus = FT_ListDevices(&numDevs, null, FT_LIST_NUMBER_ONLY); numDevsに接続しているデバイス数が入ります。 このdllは、引数を変更することでシリアルNoやディスクリプター等を取得できる ようですが、これまでのところ利用できそうな結果が得られていません。 デバイスの情報取得には、FT_EE_Read()が使用できます。 4.11. FT_EE_Read (EEPROMの読出し) DLL参照定義: // FT_EE_Read [DllImport("ftd2xx.dll")] unsafe private static extern UInt32 FT_EE_Read( UInt32 lngHandle, FT_PROGRAM_DATA* pData); unsafe public struct FT_PROGRAM_DATA { public UInt32 Signature1; // Header - must be 0x00000000 public UInt32 Signature2; // Header - must be 0xffffffff public UInt32 Version; // Header - FT_PROGRAM_DATA version // 0 = original // 1 = FT2232C extensions public UInt16 VendorId; // 0x0403 public UInt16 ProductId; // 0x6001 public char* Manufacturer; // "FTDI" public char* ManufacturerId; // "FT" public char* Description; // "USB HS Serial Converter" public char* SerialNumber; // "FT000001" if fixed, or NULL public UInt16 MaxPower; // 0 < MaxPower <= 500 public UInt16 PnP; // 0 = disabled, 1 = enabled public UInt16 SelfPowered; // 0 = bus powered, 1 = self powered public UInt16 RemoteWakeup; // 0 = not capable, 1 = capable // // Rev4 extensions // public Byte Rev4; // non-zero if Rev4 chip, zero otherwise public Byte IsoIn; // non-zero if in endpoint is isochronous public Byte IsoOut; // non-zero if out endpoint is isochronous public Byte PullDownEnable; // non-zero if pull down enabled public Byte SerNumEnable; // non-zero if serial number to be used public Byte USBVersionEnable; // non-zero if chip uses USBVersion public Byte USBVersion; // BCD (0x0200 => USB2) // // FT2232C extensions // public Byte Rev5; // non-zero if Rev5 chip, zero otherwise public Byte IsoInA; // non-zero if in endpoint is isochronous public Byte IsoInB; // non-zero if in endpoint is isochronous public Byte IsoOutA; // non-zero if out endpoint is isochronous public Byte IsoOutB; // non-zero if out endpoint is isochronous public Byte PullDownEnable5; // non-zero if pull down enabled public Byte SerNumEnable5; // non-zero if serial number to be used public Byte USBVersionEnable5; // non-zero if chip uses USBVersion public UInt16 USBVersion5; // BCD (0x0200 => USB2) public Byte AIsHighCurrent; // non-zero if interface is high current public Byte BIsHighCurrent; // non-zero if interface is high current public Byte IFAIsFifo; // non-zero if interface is 245 FIFO public Byte IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target public Byte IFAIsFastSer; // non-zero if interface is Fast serial public Byte AIsVCP; // non-zero if interface is to use VCP drivers public Byte IFBIsFifo; // non-zero if interface is 245 FIFO public Byte IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target public Byte IFBIsFastSer; // non-zero if interface is Fast serial public Byte BIsVCP; // non-zero if interface is to use VCP drivers }; public FT_PROGRAM_DATA[] ftData = new FT_PROGRAM_DATA[16]; unsafe private void button6_Click(object sender, EventArgs e) { int i; UInt32 ftHandle; ftStatus = FT_Open(0, &ftHandle); if (ftStatus != FT_OK) return; char[] ManufacturerBuf = new char[64]; char[] ManufacturerIdBuf = new char[16]; char[] DescriptionBuf = new char[64]; char[] SerialNumberBuf = new char[16]; fixed (char* MPtr = &ManufacturerBuf[0], MIDPtr = &ManufacturerIdBuf[0], DPtr = &DescriptionBuf[0], SPtr = &SerialNumberBuf[0]) { fixed (FT_PROGRAM_DATA* APtr = &ftData[0]) { //ftData[0].Signature1 = 0x00000000; //ftData[0].Signature2 = 0xffffffff; //ftData[0].Version = 0x00000002; // EEPROM structure with FT232R extensions ftData[0].Manufacturer = MPtr; ftData[0].ManufacturerId = MIDPtr; ftData[0].Description = DPtr; ftData[0].SerialNumber = SPtr; // EEPROMデータ読出し ftStatus = FT_EE_Read(ftHandle, APtr); } listBox1.Items.Add("VID=" + ftData[0].VendorId.ToString("X4")); listBox1.Items.Add("PID=" + ftData[0].ProductId.ToString("X4")); string tmp = "SerialNumber="; for (i = 0; ; i++) { if ((int)(ftData[0].SerialNumber[i]) == 0) break; tmp += byte2chr((Byte)((int)(ftData[0].SerialNumber[i]) & 0xFF)); tmp += byte2chr((Byte)((ftData[0].SerialNumber[i] >> 8) & 0xFF)); } listBox1.Items.Add(tmp); tmp = "Manufacturer="; for (i = 0; ; i++) { if ((int)((ftData[0].Manufacturer[i]) & 0xFF) == 0) break; tmp += byte2chr((Byte)((int)(ftData[0].Manufacturer[i]) & 0xFF)); if ((int)(((ftData[0].Manufacturer[i]) >> 8) & 0xFF) == 0) break; tmp += byte2chr((Byte)((ftData[0].Manufacturer[i] >> 8) & 0xFF)); } listBox1.Items.Add(tmp); tmp = "Description="; for (i = 0; ; i++) { if ((int)((ftData[0].Description[i]) & 0xFF) == 0) break; tmp += byte2chr((Byte)((int)(ftData[0].Description[i]) & 0xFF)); if ((int)(((ftData[0].Description[i]) >> 8) & 0xFF) == 0) break; tmp += byte2chr((Byte)((ftData[0].Description[i] >> 8) & 0xFF)); } listBox1.Items.Add(tmp); listBox1.Items.Add("USBVersion=" + ftData[0].USBVersion.ToString("X2")); listBox1.Items.Add("MaxPower=" + ftData[0].MaxPower.ToString("D")); if (ftData[0].SelfPowered == 0) { listBox1.Items.Add("BUS Powered"); } else { listBox1.Items.Add("Self Powered"); } listBox1.Items.Add("FT_PROGRAM_DATA version=" + ftData[0].Version.ToString("X")); } } 5. プログラム例1(パルス出力) Startメニューをクリックするとパルスを5個出力します。 実行結果: プログラム: Form1.csの冒頭に // [DllImport("ftd2xx.dll")]参照用のusing指定 using System.Runtime.InteropServices; を追加します。 unsafe private void startSToolStripMenuItem_Click(object sender, EventArgs e) { const Uint32 FT_OK = 0; UInt32 ftHandle; UInt32 ftStatus; UInt32 writesize; Byte[] data = { 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00 }; // FT245モジュールとの通信を開きます ftStatus = FT_Open(0, &ftHandle); if (ftStatus != FT_OK) { // 通信の開始に失敗したら return; } // BitBangモードに設定。b0-b7=出力に設定。 ftStatus = FT_SetBitMode(ftHandle, 0xFF, 0x01); // ボーレートを設定 ftStatus = FT_SetBaudRate(ftHandle, 9600); int n; Byte[] out_data = new Byte[1]; for (n = 0; n < 10; n++) { // データを出力 out_data[0] = data[n]; ftStatus = FT_Write(ftHandle, out_data, 1, &writesize); // 1msecの遅延 Msec_Delay(1); } // FT245との通信を終了 ftStatus = FT_Close(ftHandle); } //------------------------------------------ // 1msec倍遅延 // 2007.07.03(火) //------------------------------------------ [DllImport("kernel32.dll")] extern static short QueryPerformanceCounter(ref long x); [DllImport("kernel32.dll")] extern static short QueryPerformanceFrequency(ref long x); public void Msec_Delay(int t) { long count1 = 0; long count2 = 0; long freq = 0; QueryPerformanceFrequency(ref freq); // システムの周波数取得 count2 = (long)t * freq / 1000; // カウント値計算 QueryPerformanceCounter(ref count1); // 計測開始カウント取得 count2 += count1; // 遅延後のカウント値計算 while (true) { QueryPerformanceCounter(ref count1); if (count1 >= count2) break; } } //------------------------------------------ // FTD2XX.DLL呼び出し参照 // 2007.07.03(火) //------------------------------------------ // FT Open [DllImport("ftd2xx.dll")] unsafe private static extern UInt32 FT_Open(Int16 DeviceNumber, UInt32 *ftHandle); // FT Close [DllImport("ftd2xx.dll")] private static extern UInt32 FT_Close(UInt32 ftHandle); // FT_SetBitMode [DllImport("ftd2xx.dll")] private static extern UInt32 FT_SetBitMode(UInt32 ftHandle, Byte Mask, Byte Mode); // FT_SetBaudRate [DllImport("ftd2xx.dll")] private static extern UInt32 FT_SetBaudRate(UInt32 ftHandle, UInt32 BaudRate); // FT_Write [DllImport("ftd2xx.dll")] unsafe private static extern UInt32 FT_Write(UInt32 ftHandle, [MarshalAs(UnmanagedType.LPArray)] byte[] bdata, UInt32 BufferSize, UInt32 *BytesWriten); 6. プログラム例2(クロックとシリアルデータ出力) 1バイトのデータをクロックと同期してMSBからシリアルで出力します。 タイミングチャート ──┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐┌┐ CLOCK ──┴┘└┘└┘└┘└┘└┘└┘└┘└ ──┬─┬─┬─┬─┬─┬─┬─┬── DATA ──┴─┴─┴─┴─┴─┴─┴─┴── MSB LSB [start]メニューをクリックすると実行し、 FT245RLのデータバスのbit7にシリアルデータを、 bit6にクロックを出力します。 シフト演算子<<は半角英記号に変更してください。 Form1.csの冒頭に // [DllImport("ftd2xx.dll")]参照用のusing指定 using System.Runtime.InteropServices; を追加します。 // ========================================== // シリアルデータ出力(クロック同期式) // ========================================== unsafe private void startSToolStripMenuItem_Click(object sender, EventArgs e) { UInt32 n; Byte[] data = new Byte[16]; UInt32 ftHandle; UInt32 ftStatus; // FT245との通信を開きます ftStatus = FT_Open(0, &ftHandle); // ボーレート設定 ftStatus = FT_SetBaudRate(ftHandle, 19200); // クロックとシリアルデータ出力 // b0=int, b2-b7=Out Byte data_buf = 0x55; // 出力データ Byte clock_low = 0x00; // b6=クロックビット=LOW Byte clock_high = 0x40; // b6=クロックビット=HIGH for (n = 0; n < 16; n += 2 ) { // MSBから出力するデータと、同期するクロックを生成 data[n] = (Byte)((data_buf & 0x80) | clock_low); data[n + 1] = (Byte)(data[n] | clock_high); data_buf <<= 1; // 次の出力ビットをMSBへシフト } // 8ビットのシリアルデータとクロックを出力 ftStatus = FT_Write(ftHandle, data, n, &writesize); // FT245との通信を閉じます ftStatus = FT_Close(ftHandle); } // DLL参照用定義は省略しました。 クロック波形: 上:8ビットのクロック列。50usec/dev。全長158usecから210usec。 下:5usec/devに時間軸を拡大。最小幅=3.2usec。 7. プログラム例3(入出力) Bit Bangモードで、ポート上位4ビットに接続したスイッチのオン・オフを、 ポートの下位4ビットに出力します。 実行結果: 上:b4スイッチ入力信号 下:b0出力信号 スイッチ入力の変化から出力変化までの遅れ時間は、 実測で最小3.4msecから最大9.6msecの範囲でばらつきます。 プログラム: Form1.csの冒頭に // [DllImport("ftd2xx.dll")]参照用のusing指定 using System.Runtime.InteropServices; を追加します。 unsafe private void startSToolStripMenuItem_Click(object sender, EventArgs e) { Byte[] data = new Byte[1]; UInt32 ftHandle; UInt32 ftStatus; // FT245との通信を開きます ftStatus = FT_Open(0, &ftHandle); // ボーレート設定 ftStatus = FT_SetBaudRate(ftHandle, 19200); while (true) { // ポート入力 ftStatus = FT_GetBitMode(ftHandle, data); data[0] >>= 4; // 下位4ビットへシフト // ポート出力 ftStatus = FT_Write(ftHandle, data, 1, &writesize); } } // DLL参照用定義は省略しました。
ページのTopへ
サイトのTopへ
法律条項 この資料により生じたいかなる障害や損害に対し、著者は全てを免責されるものとします。 この資料は、著作権法の下で保護され、入手先、著者、日付、法律条項を含んだ場合に複製が可能です。
inserted by FC2 system