パラレル接続型キャラクターLCD Displayモジュール処理

液晶ドライバについて

日立製(互換?)液晶コントローラーを使った液晶表示モジュールへの表示に成功しましたので、これについて記載します。

ドライバVerilogコードは、lcd_driver_8.vです。

ステートマシーンを作り、ステート毎に液晶モジュールへコマンドを

送出します。

1)入出力ポートの説明

ここでは、モジュールの入出力について説明します。

括弧()内の数値は、入出力、ビット数を表しています。I=入力、O=出力、IO=入出力

例)(I:1) 入力、1ビット

clk (I:1):入力クロック、外部で37usecのクロックを生成してこの端子へ入力します。

resetn (I:1):リセット入力、ロー入力でモジュールを初期化します。

addr (O:8):アドレス出力、外部LCDメモリバッファの内容を読み込むためにアドレス指定します。

data (I:8):データ入力、上記で指定したアドレスのデータを読み込みます。

rd (O:1):リード出力、リード時にハイにセットします。

sc1602_en (O:1):液晶モジュールイネーブル出力(H:イネーブル)。

sc1602_rs (O:1):液晶モジュールレジスタセレクト出力(L:インストラクションレジスタ、H:データレジスタ)。

sc1602_rw (O:1):液晶モジュールリードライト出力(L:書き込み)。

sc1602_data (IO:8):液晶モジュールデータバス

rfrsh_rate (O:1):リフレッシュレート出力。16x2文字を書き込む毎にデータを反転出力します。

2)動作説明

このモジュールは表示バッファのデータ内容を読み取り、外部に接続された

パラレル接続タイプの液晶モジュールに転送します。

液晶モジュールのデータレジスタ16x2の内容は常にリフレッシュされます。

動作内容)

  • -外部に接続されているメモリの内容を読み出します。
  • -メモリのアドレスと表示位置は次のようにマッピングしています。

メモリアドレス:00-0F - 液晶モジュール1行目の1桁目から16桁目

メモリアドレス:10-1F - 液晶モジュール2行目の1桁目から16桁目

  • -メモリの内容を液晶モジュールのデータレジスタにセットします。

3)ステートの説明

モジュールは次のステートを持っています。

  • 0-RESET:リセット処理開始ステート
  • 1-WAIT:待ちステート(イネーブル出力をローにします)
  • 2-HOLD:hold_timeで指定された値分ホールドします。
  • 3-FNCSET:ファンクションレジスタ設定ステート
  • 4-DSPOFF:ディスプレイオフステート
  • 5-CLRDSP:クリアディスプレイステート
  • 6-DSPON:ディスプレイオンステート
  • 7-ENMODST:エントリモード設定ステート
  • 8-RETHOM:リターンホーム設定ステート
  • 9-REDCHR:データリード(外部LCDメモリバッファ)ステート
  • 10-WRTCHR:データライト(液晶モジュール)ステート
  • 11-DDRMADSET:DDRAMアドレス(液晶モジュール)設定ステート

stateレジスタが現在のステート、nextレジスタが次のレジスタになります。

state<-nextが実行されるのは、HOLDステートの時です。

4)ステート遷移

  • リセット動作)

RESET->WAIT->HOLD->FNCSET->WAIT->HOLD->DSPOFF->WAIT->HOLD

->CLRDSP->WAIT->HOLD->DSPON->WAIT->HOLD->ENMODST->WAIT->HOLD

->RETHOM->WAIT->HOLD

  • DDRAMリフレッシュ動作)

REDCHR->WAIT->HOLD->WRTCHR->WAIT->HOLD->DDRAMSET

->WAIT->HOLD

上記を繰り返します。

ただし、WRTCHR時にdidxの値が4FHだった場合には、RETHOMへ状態を遷移します。

5)レジスタ

  • state : カレントステート
  • next : 次ステート
  • didx : DDRAMインデックスナンバー。00,01,..0F,40,41..4F,00..と遷移します。
  • hold_time : HOLDステートでの滞在カウンタ

6)コード

lcd_driver_8.v

module lcd_driver_8(clk,resetn,addr,data,rd,sc1602_en,sc1602_rs,sc1602_rw,sc1602_data,rfrsh_rate);

input clk,resetn;

output [7:0] addr;

reg [7:0] addr;

input [7:0] data;

output rd;

reg rd;

output sc1602_en,sc1602_rs,sc1602_rw;

reg sc1602_en,sc1602_rs,sc1602_rw;

output [7:0] sc1602_data;

reg [7:0] sc1602_data;

output rfrsh_rate;

reg rfrsh_rate;

reg [7:0] state, next, didx, hold_time;

parameter RESET=0;

parameter WAIT=1;

parameter HOLD=2;

parameter FNCSET=3;

parameter DSPOFF=4;

parameter CLRDSP=5;

parameter DSPON=6;

parameter ENMODST=7;

parameter RETHOM=8;

parameter REDCHR=9;

parameter WRTCHR=10;

parameter DDRMADSET=11;

// DL=1:8bit, N=1:2-line, F=0:5x8 dot, D=0:disp off

// C=0:Cursor off, B=0:Blinking off

// I/D=1:Increment by 1, S=0:No shift

// clk = 37us

always @(posedge clk or negedge resetn) begin

if (!resetn)

begin

state <= RESET;

didx <= 0;

end

else

begin

case (state)

RESET:

begin

sc1602_en <= 1;

sc1602_rs <= 0;

sc1602_rw <= 0;

sc1602_data <= 8'h38; // DL=1, N=1, F=0

didx = didx + 1;

if (didx > 3)

next <= FNCSET;

else

next <= RESET;

state <= WAIT;

hold_time = 0;

end

WAIT:

begin

sc1602_en <= 0;

state <= HOLD;

end

HOLD:

begin

if (hold_time == 0)

state <= next;

else

begin

hold_time = hold_time - 1;

end

end

FNCSET: // Function set

// Sets interface data length(DL)

// number of display lines (N)

// and character font (F).

// DL : 1=8 bits, 0=4 bits

// N : 1=2-lines, 0=1-line

// F : 5x10 dots, 0=5x8 dots

begin

sc1602_en <= 1;

sc1602_rs <= 0;

sc1602_rw <= 0;

sc1602_data <= 8'h38; // 1, DL=1, N=1, F=0, 0, 0

state <= WAIT;

next <= DSPOFF;

hold_time = 0;

end

DSPOFF: // Display on/off

// D: 1=Display on, 0=off, C: 1=Cursor on, 0=off, B: 1=Cursor blinking, 0=off

begin

sc1602_en <= 1;

sc1602_rs <= 0;

sc1602_rw <= 0;

sc1602_data <= 8'h08; // D=0,C=0,B=0

state <= WAIT;

next <= CLRDSP;

hold_time = 0;

end

CLRDSP: // Clear display / 1.52ms

// Clear entire display and sets DDRAM address 0 in address counter.

begin

sc1602_en <= 1;

sc1602_rs <= 0;

sc1602_rw <= 0;

sc1602_data <= 8'h01; // Clear Display

state <= WAIT;

next <= DSPON;

hold_time = 42;

end

DSPON: // Display on/off

begin

sc1602_en <= 1;

sc1602_rs <= 0;

sc1602_rw <= 0;

sc1602_data <= 8'h0C; // D=1, C=0, B=0

state <= WAIT;

next <= ENMODST;

hold_time = 0;

end

ENMODST: // Entry Mode

// Sets cursor move direction and specifies display shift.

// These operations are performed during data write and read.

// I/D : 1=Increment, 0=Decrement, S : 1=Accompanies display shift

begin

sc1602_en <= 1;

sc1602_rs <= 0;

sc1602_rw <= 0;

sc1602_data <= 8'h06; // 1, I/D=1, S=0

state <= WAIT;

next <= RETHOM;

hold_time = 0;

end

RETHOM: // Return Home / 1.52ms

// Set DDRAM address to "00H"

// from AC and return cursor to its

// original position if shifted. The

// contents of DDRAM are not changed.

begin

sc1602_en <= 1;

sc1602_rs <= 0;

sc1602_rw <= 0;

sc1602_data <= 8'h02;

state <= WAIT;

next <= REDCHR;

didx <= 0;

rfrsh_rate <= ~rfrsh_rate; // output refresh rate;

hold_time = 42;

end

DDRMADSET: // Set DDRAM address

// Sets DDRAM address. DDRAM data is sent and

// received after this setting.

begin

sc1602_en <= 1;

sc1602_rs <= 0;

sc1602_rw <= 0;

sc1602_data <= 8'h80 | didx;

state <= WAIT;

next <= REDCHR;

hold_time = 0;

end

REDCHR:

begin

addr <= didx;

rd <= 1;

state <= WRTCHR;

end

WRTCHR:

begin

sc1602_data <= data;

rd <= 0;

sc1602_rs <= 1;

sc1602_rw <= 0;

sc1602_en <= 1;

didx = didx + 1;

if (didx == 16)

begin

didx = 8'H40;

next <= DDRMADSET;

end

else if (didx > 8'H4F)

begin

didx = 8'H00;

next <= RETHOM;

end

else

next <= REDCHR;

state <= WAIT;

hold_time = 0;

end

endcase

end

end

endmodule

アクセスカウンター
アクセスカウンター