2013年6月30日日曜日

秋月 小型I2C液晶 AQM0802A-RN-GBW  駆動方法

小型のI2C液晶を動かしてみたので忘れないうちにメモ。(調べると沢山情報が出てきますがw

まず配線。液晶のピン番号はデータシートに書いてあるように左から1,2,3,...,9
接続例も載ってあるのでそのように繋げばおk

私はチップコンデンサを直接ピンに実装したが、あまり長く加熱してるとICのモールド部分が焦げるので短時間ではんだ付け。汚いけど問題ない。
このようにピンの名前を書いておくと間違わなくて良。

電源電圧が3.3Vであることに注意。3.3Vで動作させているときはコントラスト調整が最小でもちょうどいいくらい。

次に制御プログラム。
今回はMikroElektronika社のPIC用Cコンパイラ、mikroC for PICを使用した。知らない間にVer 6.0.0が出ていたが、、、目立った変化はない感じ。ライブラリが豊富で良いんだけど、エディタに若干バグがあるのが残念。試用版では2Kワードまですべての機能を使うことが出来る。
マイコンはPIC12F683を使用し、内蔵クロック4MHzで動作させた。

I2C通信はこのLCDの場合は書き込みのみなので割とシンプル。
データバイトを1つだけ送信する場合は、

1.スタートコンディション発行
2.スレーブアドレス送信(このLCDだと0x7c)
3.コントロールバイトを送信
4.データバイトを送信
5.ストップコンディションを発行

という流れになってる。
この中の「コントロールバイトを送信」ってのが、次に送るデータバイトが「コマンド」であるか「データ」であるかを識別するために重要。

コントロールバイトの構成は2進数で
[Co][RS][0][0] [0][0][0][0]
となっており、下位6ビットは0で変わらない。コマンドを送りたいときは[RS]を0に、データを送りたいときは[RS]を1にする。
[Co]は連続してデータを送るか指定する為に用いる。
[Co]に0を指定すると、そのコントロールバイトの後に続けて複数のデータバイトを送信することができる。つまり、

1.スタートコンディション発行
2.スレーブアドレス送信(このLCDだと0x7c)
3.コントロールバイトを送信[Co] = 0
4.データバイトを送信
  データバイトを送信
  データバイトを送信
  .
  .
  データバイトを送信
5.ストップコンディションを発行

となる。
逆に言えば、途中でコントロールバイトは変更できないので、文字を幾つか送信してその後にコマンドを送信ってのはおそらく出来ない。一度ストップコンディションを発行して終了させる必要がある。

[Co]に1を指定した場合はコントロールバイト、データバイトの二組を続けて送信しないといけない(データを2つ以上連続して送れない)。
つまり、

1.スタートコンディション発行
2.スレーブアドレス送信(このLCDだと0x7c)
3.コントロールバイトを送信[Co] = 1
4.データバイトを送信
  コントロールバイトを送信[Co] = 1
  データバイトを送信
  コントロールバイトを送信[Co] = 1
  .
  .
  コントロールバイトを送信[Co] = 1
  データバイトを送信
5.ストップコンディションを発行

となる。最後のコントロールバイトも1にしておく。途中でコマンドとデータが別れる場合に便利。
秋月のデータシートを見ると、「データを複数送る場合Co=1で、最終データはCo=1です。」と書かれてあるが、データを複数送る場合は[Co] = 0の間違いではなかろうか..? 

以上を踏まえて液晶に「Hello World!」と表示するプログラムをベタで書くとこんな感じになる。

液晶1行目の「Hello」は[Co] = 1としてコントロールバイトとデータを1組づつ送っている。
液晶2行目の「World!」は[Co] = 0としてデータを連続で送っている。
実際に動かすとこのように表示される。

以上が文字表示時のデータ送信手順。

LCD初期化はデータシートの通りにやれば問題ない。
コードはこんな感じ。

液晶にコマンドを1つ送るための関数(i2c_lcd_cmd)はこうなってる。


あとは文字を一文字送信する関数、文字列を送信する関数などを作っておくと便利。

とりあえずメモは以上。

マイコンとは2線で繋ぐだけだからポート数も余裕があるしデバッグが捗るね。

7 件のコメント:

  1. 使用しているPICは何ですか?
    後、プログラムをすべてみせてください。
    お願いします!!

    返信削除
    返信
    1. PICは12F683を使用しました。
      プログラムは以下URLのような感じです。(当時のが残っていなかったので動作未確認)
      LCD表示部は改行の必要あり。
      http://db.tt/QB5Bbfzd

      削除
    2. すみません、HiTECHのコンパイラーを使ってPIC16F877AとAQM0802LCDに表示したいですがなかなか出来ない状況です。それにかんして情報があれば助かります。

      削除
  2. PICAXE 08M2のLCD制御の参考にさせていただきます。
    情報ありがとうございます。

    返信削除
  3. このサイトを参考にしてLPC1114FN28で動かせました。ありがとうございます。

    返信削除
  4. 小型のI2C液晶は使い勝手がイイですよね.自分も挑戦してみました.
    http://www.youtube.com/watch?v=QdaBERh0mT4

    返信削除
  5. 下記にソースを貼り付けましたが問題が有れば教えて頂く。

    #include
    #include "i2c.h" // The same file as provided by HiTECH\samples\i2c
    #ifndef _XTAL_FREQ
    // Unless already defined assume 4MHz system frequency
    // This definition is required to calibrate __delay_us() and __delay_ms()
    #define _XTAL_FREQ 10000000
    #endif

    __CONFIG (FOSC_HS & WDTE_OFF & PWRTE_OFF & BOREN_OFF & LVP_ON & WRT_OFF & DEBUG_ON & CPD_OFF & CP_OFF);

    // AQM0802 LCD Address
    #define LCD_ADD 0x7C
    #define SDA RC4
    #define SCL RC3
    #define SDA_DIR TRISC4
    #define SCL_DIR TRISC3
    #define SPEED 100 //kbps

    /***********************************************
    * Initialize the PIC16F877A
    ***********************************************/
    void init_i2c(void)
    {
    TRISB = 0x00; // pins are set as output.

    //Setting RC3 and RC4 as input.
    SDA_DIR = 1;
    SCL_DIR = 1;

    SSPADD = (_XTAL_FREQ/(4000*SPEED))-1;
    SSPSTAT = 0x80;
    SSPCON = 0x28;
    SSPCON2 = 0x00;

    PSPIF=0; // clear SSPIF interrupt flag
    BCLIF=0; // clear bus collision flag
    }

    /***********************************************
    * For sending command with Control Byte as 0x80
    * cmd : input command.
    ***********************************************/
    void send_lcd_cmd(unsigned char cmd)
    {
    i2c_Start();
    i2c_WriteTo(LCD_ADD);
    i2c_PutByte(0x80);
    i2c_PutByte(cmd);
    i2c_Stop();
    }
    /***********************************************
    * For sending data with Control Byte as 0xC0
    * data : input data to write.
    * NOTE before this method call address shall be
    * set by calling the send_lcd_cmd.
    ***********************************************/
    void send_lcd_data(unsigned char data)
    {
    i2c_Start();
    i2c_WriteTo(LCD_ADD);
    i2c_PutByte(0xC0);
    i2c_PutByte(data);
    i2c_Stop();
    }

    void main(void)
    {
    init_i2c(); //initialize.
    __delay_ms(40); //40ms wait.

    send_lcd_cmd(0x38);
    send_lcd_cmd(0x39);
    send_lcd_cmd(0x14);
    send_lcd_cmd(0x70);
    send_lcd_cmd(0x56);
    send_lcd_cmd(0x6C);

    __delay_ms(210); //wait for 210ms.

    send_lcd_cmd(0x38);
    send_lcd_cmd(0x0C);
    send_lcd_cmd(0x01);

    __delay_ms(2); //wait.

    send_lcd_cmd(0x00);
    send_lcd_data(0x16);
    send_lcd_cmd(0x01);
    send_lcd_data(0x9F);
    }

    返信削除