ゆけッ! やっせんぼ・とよちゃん!

SG12864AS を使ってみました (2010年03月16日)

SG12864ASを3.3Vで使ってみました (2010年06月02日追記)




インデックス




はじめに

今製作に取り掛かっているスペクトルアナライザの表示部として秋月さんで売られている SG12864AS を使ってみました。 インターネットで調べたら他に使っている方々がいらしたので、ある方のソースコードを参考にしてテストプログラムを作ってみたのだけど なかなか巧く行きませんでした。 結局、ダウンロードしてきたソースコードの方法は無視して、データシートのとおりにやったら、なんとか描画できるようになりました。

インターネットで見つけた情報では

  • Eラインを H=>L、L=>H に併せて RW、DI ラインも反転させる
  • データを書き込むときには CS1、CS2 も反転させる
という感じだったのですが、実際にはこんな面倒くさい事などしなくても Eライン L=>H=>L で正しくコマンド、データともに書き込むことが出来ました。

ただし、データとステータスの読み出しは試していません。

以下、PICを使った場合について説明します。




コマンドの書き込み

データシートのタイミングチャート(右図)からは、

  1. 初期状態 E=1、チップ選択無し
  2. E=0 セット
  3. RW=x、DI=x をセット
  4. チップの選択(CS1、CS2設定)
  5. ディレイ(tAS)
  6. E=1 セット
  7. データ・コマンドポートにデータまたはコマンドをセット
  8. ディレイ(tDSW)
  9. E=0 セット
のように読み取れます。 ただし、x は、書き込み、読み出し、データ、コマンド等にあわせて適当な値を設定します。

そこで、私は コマンドの書き込みは以下の手順にしました:

  1. 初期状態は E=0、チップ選択無し
  2. チップの選択(CS1、CS2設定)
  3. データ・コマンドポートにコマンドをセット
  4. E=0、RW=0、DI=0 をセット
  5. 0.5μ秒以上ディレイ
  6. E=1、RW=0、DI=0 をセット
  7. 0.5μ秒以上ディレイ
  8. E=0、RW=0、DI=0 をセット
  9. チップを無選択にする(初期状態に戻る)
基本的にコマンド、RW、DI の設定の後 Eラインの L=>H=>L のストローブで問題ありません。 私の場合、SG12864AS に対して何もしない場合、基本的に CS1=0、CS2=0、E=0 を設定しています。

私が使っているコマンド書き込み関数は以下のような感じです。 データ・コマンドポートは PORTB に、E、RW、DI は PORTC の 5、4、3 ビットにアサインされています。 チップの選択は sg12864_command() 関数を呼び出す直前に行っています。

void sg12864_delay(void)
{
    unsigned char i;

    // looping once should be enough for the PIC with the clock less than 20MHz
    for (i =0; i < 1; ++i);
}

void sg12864_command(unsigned char value)
{
    unsigned char d;

    // pin assignment
    // E:  RC5
    // RW: RC4
    // DI: RC3

    d = PORTC & 0xc7;
    PORTB = value;

    PORTC = d | 0x00;    // E=0, RW=0, DI=0
    sg12864_delay ();

    PORTC = d | 0x20;    // E=1, RW=0, DI=0
    sg12864_delay ();

    PORTC = d | 0x00;    // E=0, RW=0, DI=0
}




データの書き込み

データの書き込みもコマンドと同様に以下の手順で行います:

  1. 初期状態は E=0、チップ選択無し
  2. チップの選択(CS1、CS2設定)
  3. データ・コマンドポートにデータをセット
  4. E=0、RW=0、DI=1 をセット
  5. 0.5μ秒以上ディレイ
  6. E=1、RW=0、DI=1 をセット
  7. 0.5μ秒以上ディレイ
  8. E=0、RW=0、DI=1 をセット
  9. チップを無選択にする(初期状態に戻る)
コマンドの場合との違いは DI=1 に設定してある点だけです。

データ書き込み関数は以下のような感じです。

void sg12864_data(unsigned char value)
{
    unsigned char d;

    // pin assignment
    // E:  RC5
    // RW: RC4
    // DI: RC3

    d = PORTC & 0xc7;
    PORTB = value;

    PORTC = d | 0x08;    // E=0, RW=0, DI=1
    sg12864_delay ();

    PORTC = d | 0x28;    // E=1, RW=0, DI=1
    sg12864_delay ();

    PORTC = d | 0x08;    // E=0, RW=0, DI=1
}




最後に

最初にソースコードを参考させてもらった方が何故あんなに面倒くさいコントロールをしないといけなかったのかと考えた結果、推測ですが、E、RW、DI ラインを以下のように別々にコントロールしているためではないかと考えます。 コマンド書き出しの関数の一部を参照させてもらいます。

        PORTx = (コマンド);

	set_LOW(E);
	set_HIGH(RW);
	set_HIGH(DI);;
	Delay();

	set_HIGH(E);
	set_LOW(RW);
	set_LOW(DI);
	Delay();

	set_LOW(E);
	set_HIGH(RW);
	set_HIGH(DI);
	Delay();

	PORTx = 0;

このように別々にコントロールするように記述している理由は、ソースコードの移植性を高めるためなのですが、結果的に各ラインの立ち上がり立下りタイミングが0.5μ秒くらいのオーダーでばらつき、不具合を招いているのではないかと推測します。




3.3Vで使ってみました (2010年06月02日追記)

当初は5Vで使用していたのだけど、dsPIC33Fと一緒に使うことにしたので 3.3Vでの動作確認をしてみました。 で、まぁ当然のように動きません。(笑)

秋月さんのSG12864ASのページでは3.3V動作が明記されているので、私の使い方の問題と思って調査し、以下の2点を追加したら動作するようになりました:

  1. 電源投入直後 250msecのディレイを入れる
  2. コマンド・データ送信用Eラインストローブ生成用のディレイ時間を増やす

1.は、試しに250msecくらいの for loop を main関数の先頭に入れたら動作するようになりました。 5V使用時はディレイは必要なかったので、実際のところ250msecも要らないと思います。 最初だけのディレイなので 厳密な値は調査せずそのままです。

2.は、具体的には sg12864_delay() 関数です。 5Vで使用しているときには for loop ではなく 以下のように NOP を3つ挿入していました。 因みに、コントローラーのPIC16F873のクロックは20MHzです。

#define sg12864_delay() \
__asm NOP __endasm;\
__asm NOP __endasm;\
__asm NOP __endasm;

1.を施した時点で何か表示されるようにはなったのだけど、表示された文字が崩れていたので ストローブの問題と気づきました。 3.3Vでは NOP を 5個にして使っています。 4個では少し不安定なように見えました。