記事

I2C接続キャラクタLCDモジュール用の関数を作る(3)制御 関数の作成とテスト

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

(1) カーソル位置の制御
 LCDの表示位置を制御するための関数として、Arduinoの標準ライブラリのLiquidCrystalライブラリには、setCursor関数(メソッド)として定義されています。この関数と同じ機能をもった関数を作ります。

●関数の引数
 1行目の文字数40文字、2行目の文字数40文字として、行を0、1の値のYで表し、列を0から39の値のXで表し(X、Y)の座標で表します。このX、YのINT型の整数を引数とします。
 この座標をもとに、DDRAMのカーソル位置のアドレスを計算します。そのアドレスの値をアドレス・カウンタにセットします。この計算は次のように行います。

  ca = X +Y×0x40


 この計算処理を実際にプログラムとすると次のようになります。

void lcdcu_set(int x, int y) {
    byte ca = (x + y * 0x40) | (0x80);
    i2cwritecmd(ca);
}

引数
  x : 0から39 までの値
  y : 0、1 の値で カーソルの位置を示す


 X、Yの座標から、DDRAMのメモリの0x00から0x28と0x40から0x68のアドレスの値が計算されます。アドレス・カウンタをセットするコマンドは最上位のd7ビットが1となります。このコマンドを用意するために0x80とアドレスの値とのビット単位のorの論理演算を行います。加算を用いなかったのは、カーソルの位置を示す引数の値の誤入力でアドレスの値が0x7F以上の値になったとき、アドレス・カウンタのセットのコマンドでなく誤ったコマンドになるのを避けるためです。

(2) クリア
 DDRAMの内容をクリアして、カーソルを上段左端のホーム・ポジションに設定します。この処理を行うコマンドが0x01として用意されています。この関数名をlcdclear()とすると、この関数は次のようになります。クリアとホームのコマンド処理は1ms以上かかる場合があるので、delay(1)で処理の終了を待っています。

void lcdclear() {
    i2cwritecmd(0x01);
    delay(1);
}

(3) ホーム
 表示はそのままで、カーソルをホーム・ポジションに戻す場合は0x02のコマンドを利用します。

void lcdhome() {
    i2cwritecmd(0x02);
    delay(1);
}


(4) 表示全体をシフト
 表示全体を1文字分右にシフトします。カーソルやブリンクスの位置も同じ方向に移動します。コマンドは左シフトで0x18、右シフトで0x1Cとなります。移動方向を示す引数を設定する方法もありますが、関数名にl、rの文字をつけて区別するほうがわかりやすいので、次のように二つの関数を作りました。

void dsift_l() {      // 左シフト
    i2cwritecmd(0x1C);
}
void dsift_r() {      // 右シフト
    i2cwritecmd(0x18);
}

●作成した関数の動作テスト
 カーソル・セット、ホーム、クリアのテストのプログラムを次のように作りました。

void loop() {
    i2cwritedata(0x41);     //上段左端に A を表示
    lcdcu_set(8, 0);        // 上段9列にカーソル設定
    i2cwritedata(0x42);     // Bを表示
    lcdcu_set(8, 1);       // 下段 9列にカーソル設定
    i2cwritedata(0x43);    // Cを表示
    delay(10000);          // 10秒待つ


 ここまでの処理の結果を次に示します。期待通りの表示になっています。

    lcdhome();   // ホームの関数のテスト 上段左端にカーソル・セット
    delay(10000); // 10秒待つ


 カーソルが上段の左端にセットされ、Aの文字の下に表示されています。

 次に、表示画面のクリアの関数、表示画面のシフトの関数のテスト・プログラムを次のように作りました。

    lcdclear();    // 画面がクリア
    int odata = 0x40; // 表示データの初期値をセット
    for (int j = 1; j < 41; j++) { // 40文字 上段のDDメモリに書き込む
        odata = odata + 1;       // 文字データのコードをカウント・アップ
        i2cwritedata(odata);     // DDRAMに書き込む
    delay(100);
}


 表示がクリアされ、A、B、Cが消去され、0x41のコードのAの文字から順番に書き込んでいます。

 小文字のhの文字コードから順番にカウント・ダウンして下段に文字を埋めていきます。

    odata = 0x40 + 41;
    for (int j = 1; j < 41; j++) {
        odata = odata - 1;
        i2cwritedata(odata);
        delay(100);
    }


 上段と下段は同じ文字が逆の順番に表示されます。

 DDRAMに文字を埋め、表示全体を1文字分ずつ右にシフトを24回繰り返します。

    for (int j = 1; j < 25; j++) {
        dsift_r();
        delay(500);
    }
    delay(5000);


 2回右側にシフトしてQ、Rが新たに右側に表示されます。

 24回シフトを繰り返すとDDRAMの右端の値が表示されます。


●左にシフト
 次は、左に24回シフトを繰り返し元の表示に戻ります。

    for (int j = 1; j < 25; j++) {
        dsift_l();
        delay(500);


 4回左にシフトした状態です。U、V、W、Xが新たに左側に表れました。

    }
    delay(5000);


 24回繰り返すと元の表示に戻りました。

    lcdclear();
}


 これで、今回作成した関数の動作確認ができました。
 今までは、バイト単位の文字コードを書き込み表示しています。次回から表示の仕組みについて検討します。

(2016/7/30 V1.0)

<神崎康宏>

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

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

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

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

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

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