記事

I2C接続キャラクタLCDモジュール用の関数を作る(2)制御できる項目

LCD制御モジュールをコマンドによって制御できること

 HD47780互換のLCD制御モジュールには、次の制御ビットが用意されています。この制御ビットは、このモジュールの制御レジスタへのコマンドの書き込みによってON/OFFされます。

入力モードのセット
 データの読み書きのときのカーソル、アドレス・カウンタ、表示時領域の動きを指定します。

I/D:DDRAM(メモリ)にデータを書き込んだ後、アドレス・カウンタのデータをインクリメントするか、ディクリメントするか示す制御ビット。1でインクリメント、0でディクリメント
 リセット後デフォルト値 I/D=1
S:表示領域のシフト
 リセット後デフォルト値 S=0

●表示モードのセット

D:LCDの文字表示のON/OFFを行う。1で文字を表示、0で文字を非表示。
  リセット後デフォルト値 D=0
C:カーソルの表示/非表示を制御。1でカーソルを表示、0でカーソルを非表示。
  リセット後デフォルト値 C=0
B:ブリンクのON/OFF、1でブリンクを実行、0でブリンクをキャンセル。
  リセット後デフォルト値 B=0

カーソルLCD表示と移動
 この命令で、直接カーソル、表示領域を変更します。

S/C:表示範囲のシフトの制御、1でR/Lで指定された方向に表示範囲をシフトする。アドレス・カウンタは変化しない。0の場合表示範囲のシフトは行わず、カーソルの位置が変化する。合わせてアドレス・カウンタも変化する。
  リセット後デフォルト値 S/C=0
R/L:カーソルの移動方向 1で右、0で左に移動する。
  リセット後デフォルト値 R/L=1

イニシャル・セット

DL:データ転送のデータ幅を決める。1のとき8ビット、0のとき4ビットを2回。
   リセット後デフォルト値 DL=1
N:表示ライン数を設定する。1のとき2行、0のとき1行。
   リセット後デフォルト値 N=0

Busy/アドレス読み取り

BF:Busyフラグ


※今回使用している「I2C接続キャラクタLCDモジュール」はコマンド、データの書き込みにのみ対応していて、Busyフラグやアドレス・カウンタやデータの読み取りは行えません。

その他のコマンドやデータの読み書き 
 制御ビットを必要としないコマンドとして、モジュールの表示クリアのコマンド、カーソルを上段・左端にセットするホーム・コマンド、CGRAM、DDRAMのアドレスをセットするコマンドが、それぞれ用意されています。
 表示データはデータ・レジスタ経由で、アドレス・カウンタが示すアドレスのDDRAMへの読み書きを行います。

 制御コマンド、制御ビットの関係は次表のようになります。

   命令 制御信号       命令コード 
 RS  R/W  DB7  DB6  DB5  DB4  DB3  DB2  DB1 DB0
クリア  0  0  0  0  0  0  0  0  0  1
 ホーム  0  0  0  0  0  0  0  0  1 ×
 入力モード・セット  0  0  0  0  0  0  0  1  I/D  S
 表示モード・セット  0  0  0  0  0  0  1  D  C  B
 カーソルLCD表示移動  0  0  0  0  0  1  S/C  R/L ×  ×
 イニシャル・セット  0  0  0  0  1  DL  N  ※  ×  ×
 CGRAMアドレス・セット  0  0  0  1  AC5  AC4  AC3  AC2  AC1  AC0
 DDRAMアドレス・セット  0  0  1  AC6  AC5  AC4  AC3  AC2  AC1  AC0
 Busy/アドレス読み取り  0  1  BF  AC6  AC5  AC4  AC3  AC2  AC1  AC0
 表示データ書き込み  1  0  D7  D6  D5  D4  D3  D2  D1  D0
表示データ読み込み  1  1  D7  D6  D5  D4  D3  D2  D1  D0

  ※今回使用したモジュールでは使っていないが、フォント・サイズの選択ビットとなる。

初期化ルーチン
 再度、初期化ルーチンinit_lcd()の内容を確認します。

void init_lcd() {
    delay(145);


 リセット直後などモジュールの回路の安定化を待ちます。次のイニシャル・セットのコマンドを書き込みます。DL=1でデータ転送8ビット幅、N=1で2行表示のコマンドとして0x38のコマンドを i2cwritecmd(0x38);の関数で書き込みます。このモジュールではコマンドを2回に分けて書き込むモードもあるため、プログラム実行中に再度初期化を行う場合に最初に書き込んだコマンドがコマンド後半と誤認されることが考えられます。そのため、再度8ビット幅(DL=1)で、2行表示(N=1)と設定する初期化のためのコマンド0x38を2回書き込んでいます。Busyフラグのチェックは行えませんので、処理の完了をdelay(1)関数で待ちます。

    i2cwritecmd(0x38);
    delay(1);
    i2cwritecmd(0x38);
    delay(1);


 次にLCDの表示をイネーブル(D=1)、カーソル非表示(C=0)、ブリンクなし(B=1)のコマンド0x0Cを書き込み表示の設定を行います。その後、LCDのクリアのため0x01を書き込んで初期化を終えます。

    i2cwritecmd(0x0C);
    delay(1);
    i2cwritecmd(0x01);
    delay(1);
}

DDRAMは表示メモリ
 DDRAMはDisplay data RAMのことで、80バイトのRAMで構成されています。表示データはこのDDRAMに書き込まれると、このDDRAMの32バイト分の表示領域が16列2行のディスプレイに表示されます。

DDRAMへの書き込み
 データ・レジスタへの書き込み処理を行うと書き込まれたデータはアドレス・カウンタで指定されたアドレスのDDRAMに書き込まれます。
 DDRAMへの書き込み処理が行われたときは、アドレス・カウンタの値をI/Dビットの値に従いインクリメント(1)、デクリメント(0)します。

DDRAMは80バイト
 DDRAMは上段表示用としては0x00から0x3Fまでの64バイト分のアドレスが割り当てられています。そのため2行目の左端のアドレスが0x40となっていて、2行目のアドレスは0x40から割り当てられています。
 しかし、実装されているメモリは1行40バイト、2行で計80バイトのみです。そのため実装されているメモリのアドレスは0x00~0x27と0x40~0x67の範囲となります。

カウント・アップ/ダウン時、未実装域はスキップ
 DDRAMへデータの読み書きを行う場合、アドレス・カウンタは自動的にカウント・アップまたはカウント・ダウンします。その際、アドレス・カウンタが未実装の領域を示すと未実装領域のアドレスをスキップします。
 この関係を確認するために、次のプログラムでDDRAMに16文字連続で1から順番に2、3、4カウントアップした値を表示します。

void setup() {
    // put your setup code here, to run once:
    Wire.begin();
    init_lcd();
}
void loop() {
    // put your main code here, to run repeatedly:
    int odata = 0x31;
    for (int i = 1; i < 10; i++) {
         for (int j = 1; j < 17; j++) {
            i2cwritedata(odata);
           delay(500);
        }
        odata = odata + 1;
       delay(1500);
    }
    delay(3000);
}


 次に示すように、1を16文字表示し、2を16文字、3を8文字表示して2行目の左端から8文字3を表示しています。
 1行目の表示されないDDRAMのアドレス0x10から0x27までの24バイトに2、3が格納され0x28からはスキップして0x40の2行目左端のDDRAMに書き込まれています。

 次回はカーソルの表示、ブリンク、表示域のシフトを試します。

(2016/7/11 V1.0)

<神崎康宏>

バックグラウンド

ブリンク;点滅
Busyフラグ;LCD内部で処理が行われている間は、ホスト側に待ってもらうための信号。これ接続していないときは、十分な時間をおいてから次のコマンドを送るようにプログラミングします。

連載メニュー I2C接続キャラクタLCDモジュール用の関数を作る

(1) コントローラはHD47780の互換がメイン

(2) LCD制御モジュールをコマンドによって制御できること

(3) カーソル・セット、ホーム、クリア関数の作成とテスト

(4) 文字列として数値をLCDに表示する

(5) 文字列として数値をLCDに表示する(2)