· 

CでFTDI BitBang(1)

せっかくNativeな開発環境を構築できたので、CでBitBangしてみます(いよいよ進歩してない感が、、、)。どうするか、、、まぁdllを直叩きです。同じdll直叩きでもPythonと比較すると、だいぶコードが長いです。が、変数の型とかポインタなのか変数なのかとかで変換せんといかんとかいう困りごとはないです。やっぱりこっちのほうがなじみがあります。

これが一体何の役に立つのか、、、そうだなーマイコンなしでSPIとかI2Cとか、、、まぁそんなもんしかないわ。ビットレートがあんまり正確じゃないから何かの波形パタンとか作るのにも向いてないしなー

 

では、

Pythonの時と同じく、FTDIのドライバ(CDM v?.??.??.? WHQL Certified)をダウンロードして、AMD64フォルダにあるftd2xx64.dllをcのソースコードがあるフォルダに入れておきます。

では。

「Developper Command Prompt for VS 2019」を起動して、フォルダを作成して、code .でVSCodeを起動します。

新しくソースファイルを作ります。いつも通りどこまでやるかわからんstudy1.cです。

ソースコードはこんなんです。

 

#include <windows.h>

typedef PVOID   FT_HANDLE;
typedef ULONG   FT_STATUS;

const char dllfile[]="ftd2xx64.dll";

typedef FT_STATUS (WINAPI *FT_Open_type)(int deviceNumber,FT_HANDLE *pHandle);
typedef FT_STATUS (WINAPI *FT_Close_type)(FT_HANDLE ftHandle);
typedef FT_STATUS (WINAPI *FT_SetBitMode_type)(FT_HANDLE ftHandle,UCHAR ucMask,UCHAR ucEnable);
typedef FT_STATUS (WINAPI *FT_SetBaudRate_type)(FT_HANDLE ftHandle,ULONG BaudRate);
typedef FT_STATUS (WINAPI *FT_Write_type)(FT_HANDLE ftHandle,LPVOID lpBuffer,DWORD dwBytesToWrite,LPDWORD lpBytesWritten);
typedef FT_STATUS (WINAPI *FT_Read_type)(FT_HANDLE ftHandle,LPVOID lpBuffer,DWORD dwBytesToRead,LPDWORD lpBytesReturned);
typedef FT_STATUS (WINAPI *FT_GetQueueStatus_type)(FT_HANDLE ftHandle,DWORD *dwRxBytes);

HMODULE dll;
FT_Open_type FT_Open;
FT_Close_type FT_Close;
FT_SetBitMode_type FT_SetBitMode;
FT_SetBaudRate_type FT_SetBaudRate;
FT_Write_type FT_Write;
FT_Read_type FT_Read;
FT_GetQueueStatus_type FT_GetQueueStatus;
FT_HANDLE ftHandle;
FT_STATUS ftStatus;

int main(int argc,char** argv){
    dll=LoadLibrary(dllfile);

    FT_Open=(FT_Open_type)GetProcAddress(dll, "FT_Open");
    FT_Close=(FT_Close_type)GetProcAddress(dll, "FT_Close");
    FT_SetBitMode=(FT_SetBitMode_type)GetProcAddress(dll, "FT_SetBitMode");
    FT_SetBaudRate=(FT_SetBaudRate_type)GetProcAddress(dll, "FT_SetBaudRate");
    FT_Write=(FT_Write_type)GetProcAddress(dll, "FT_Write");
    FT_Read=(FT_Read_type)GetProcAddress(dll, "FT_Read");
    FT_GetQueueStatus=(FT_GetQueueStatus_type)GetProcAddress(dll, "FT_GetQueueStatus");

    printf("dll              =%d\n",dll);
    printf("FT_Open          =%d\n",FT_Open);
    printf("FT_Close         =%d\n",FT_Close);
    printf("FT_SetBitMode    =%d\n",FT_SetBitMode);
    printf("FT_SetBaudRate   =%d\n",FT_SetBaudRate);
    printf("FT_Write         =%d\n",FT_Write);
    printf("FT_Read          =%d\n",FT_Read);
    printf("FT_GetQueueStatus=%d\n",FT_GetQueueStatus);

    ftStatus=FT_Open(0,&ftHandle);
    printf("%d\n",ftStatus);

    ftStatus=FT_SetBaudRate(ftHandle,57600);//921600MS/s is assumed
    printf("%d\n",ftStatus);

    ftStatus=FT_SetBitMode(ftHandle,0xFF,4);
    printf("%d\n",ftStatus);

    UCHAR senddata[]={0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff};
    ULONG written;
    ftStatus=FT_Write(ftHandle,senddata,8,&written);
    printf("%d\n",ftStatus);

    ftStatus=FT_Close(ftHandle);
    printf("%d\n",ftStatus);
    Sleep(1000);

    FreeLibrary(dll);

    return 0;
}

FTDIからは静的リンク用のインポートライブラリも提供されていますが、動的リンクで行きます。ちょっと面倒だけど、いざという時はこの方法になるので、知っておいたほうが良い。これ意味わかってやっているかっていうとそうでもない。今までこうやってきたので疑問も持たずにこうやっている、、、9行目からの関数型を定義するこの書き方とか、、、

おそらくだけど、関数名のアスタリスクの前のWINAPI(__stdcallでもいいらしい)はなくても動く。コンパイラのデフォルトのオプションとかで要否が変わるんだろうけど、念のために書いておく。

いまどきやる人はあまりいないprintfデバッグをやっています。せっかく簡単に表示できるので、、、

 

で、

実行してみた。

コマンド画面にはこう出る。

dllやら関数やらのアドレスが取得できていて、関数の実行結果が成功(FT_OK=0)であることがわかります。

今回使ったのはいつもの秋月のFT231Xモジュールです。みなさんよく使ってますよね。こちらの文書によると、

D0 : TXD

D1 : RXD

D2 : RTS#

D3 : CTS#

D4 : DTR#

D5 : DSR#

D6 : DCD#

D7 : RI#

 らしい。今回0x00と0xFFしか書いてないから差が見えないけど、、、

ロジアナで見るとこうなってます。ちゃんと動いてます!

ロジアナのサンプリングが100MS/sでA-B=216なので、0.925926(=100/216*2)MS/sで動いたことになる。まぁちょっとずれてる(期待値=0.9216MS/s(SetBaudRateで設定した値の16倍だと文書に書いてある))。

 

いちおう送信データも変えてみる。

UCHAR senddata[]={0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF};

いいね。ちゃんと出てる。

 

 が、心は晴れない。

 

ホント何か良い事起こらんもんかね、、、が、良い事って何だろう、、、人として、口に出して言ってはいけないことしか思いつかん。