FT232R を使ったI2C 制御

[戻る]

とある事情でキャラクタ LCD モジュールを PC に繋げたいと考えました. 当初は FT232R 等のUSB-シリアル変換デバイスを使って, PIC で LCD を制御しようかと考えました. しかし PIC のプログラムを組むのは面倒なので誰か製作記をあげてないかなと ネットをさまよってみると, こんなページを発見しました. すばらしい! 早速該当するモジュールを買って改造を試みてみました.

などいろいろ紆余曲折がありましたが, とりあえず最終的に上手くいきました. すばらしい!

人間ここまで上手くいくと少し贅沢になります. 該当モジュールは 16 文字 2 行と沢山表示できる反面少しごつくかつ高価です. 当方が出したい文字はそこまで多くないのです. 秋月を覗くと もう少し小さくて安い液晶モジュールが転がっています. I2C 接続ですが...

そんなにスピード要らないんだから 以前開拓した FT232R の CBUS を IO ピンに 見立て直接 PC から制御すればいいんじゃないかと思い立ちました. で, 実行に移す前に似たようなこと誰かやってないか探してみると こちら (音が出るページです, 注意!) に先人がいました. しかもタイミングは Asynchronous Bit Bang mode というのを使えば FT232R の方で勝手にやってくれるので PC 側は気にかけなくていいようです.

早速それらの情報を使って実験用回路を組みと C++ の ライブラリにしてみました。 実験回路の配線は次のようなものです. 気をつけないといけないのは SCL および SDA をプルアップしないことです.

一方ライブラリは使用にあたって別途 ftd2xx.h と ftd2xx.lib が必要です. その辺の情報はこちらを参照ください. 使い方は

実際の使い方は例えば 24C256 (A0,A1,A2,WP,Vss⇒GND, Vcc⇒Vdd) なら

char word[64] = "This is I2C writing test by FT232R Asynchronous bit bang mode. ";
ftdiI2Clib lib;

if (!lib.OpenDevice()){
#ifdef WRITE
  lib.SendStart();
  printf("%c\n", lib.SendByte(0xa0) ? 'o' : 'x');
  printf("%c\n", lib.SendByte(0x00) ? 'o' : 'x');
  printf("%c\n", lib.SendByte(0x00) ? 'o' : 'x');
  for (int i=0;i < 64;i++)
    printf("%c", lib.SendByte((byte)word[i]) ? 'o' : 'x');
  printf("\n");
  lib.SendStop();
#else
  byte k;

  lib.SendStart();
  printf("%c\n", lib.SendByte(0xa0) ? 'o' : 'x');
  printf("%c\n", lib.SendByte(0x00) ? 'o' : 'x');
  printf("%c\n", lib.SendByte(0x00) ? 'o' : 'x');

  lib.SendStart();
  printf("%c\n", lib.SendByte(0xa1) ? 'o' : 'x');

  for (int i=0;i < 63;i++){
    lib.RecvByte(&k, true);
    printf("%c", k);
  }
  lib.RecvByte(&k, false);
  printf("\n");
  printf("%c", k);
  lib.SendStop();

#endif
  lib.CloseDevice();
} else {
  fprintf(stderr, "Open Error\n");
}
てな感じでしょうか (このコードでは ack が帰ったかどうかをいちいち ox で確認しています).

一方 kxp84-2050 (GND,ADDR0⇒GND, VDD,IO_VDD,CS⇒Vdd, RESET⇒電源投入後一瞬だけ High) なら

if (!lib.OpenDevice()){
  byte k[6];
  int x,y,z;

  while (!kbhit()){
    lib.SendStart();
    lib.SendByte(0x30);
    lib.SendByte(0x00);

    lib.SendStart();
    lib.SendByte(0x31);

    for (int i=0;i < 5;i++)
      lib.RecvByte(&k[i], true);
	lib.RecvByte(&k[5], false);
    lib.SendStop();

    x = (k[0] << 4) + (k[1] >> 4) - 2048;
    y = (k[2] << 4) + (k[3] >> 4) - 2048;
    z = (k[4] << 4) + (k[5] >> 4) - 2048;

    printf("%d %d %d\n", x,y,z);
    Sleep(20);
  }
  lib.CloseDevice();
} else {
  fprintf(stderr, "Open Error\n");
}
てな感じでうまく動いているように見えます.

なお速度はありません. もともと液晶を表示させようともくろんでいる ものですから.

で, 肝心の液晶は完成品の見た目も重要な要素となることもあり まだ試していません. 上手くいけばまた公開します. 一方で冒頭で述べたシリアル化した液晶モジュールは ちょっとした電子回路の動作確認といった用途に使っていくつもりです.

【追記】: なんとか出来ました


2015.11