キャラクタLCDモジュールSC1602を使ってみる

HD44780コントローラー互換のSC1602キャラクタLCDモジュールを使ってみます。
マイコンで使う記事は調べるとよくありますが、よくわからないため手動で文字を表示してみます。
全ての信号線にプラス側の電圧がかかるようにスイッチを取り付けてマイナス側に10KΩの抵抗でプルダウンしました。
Eのラインだけはチャタリングが発生しないようにチャタリング防止回路を取り付けてあります。
コントラストの調整は実験中は可変抵抗を取り付けた方がいいです。
なぜかというと、1行表示で抵抗値を決め打ちしてしまうと、2行表示モードに切り替えた時にコントラストが薄くなって見えなくなってしまうことがあるからです。
これが原因で2行表示が出来ずにかなり長い間悩みました。




このすべての端子をプルダウンしてスイッチを取り付けた変態仕様、あくまで手動で動かすのだ!

▼まずは初期化

動作モードが4ビットか8ビットかどうなっているのか判らないため、最初に8ビットモードに強制変更します。

Function Set(通信モード、行数、Font sizeの設定)
0 0 1 DL N F x x

DL=1:8bit
DL=0:4bit
N=1:2line
N=0:1line
F=1:5x10dot
F=0:5x7dot

8bitモードに強制的に変更します。
そのため、次の配線部分をONにします。

0011 0000
B7<--->B0

B7〜B0の必要ビットをONにしながらEを3回ONにします。
その後、B7〜B0をOFFにします。
3回送る事により確実に8ビットモードに移行します。

▼次にディスプレイをONにしてカーソルONにする

Display ON/OFF(表示、カーソルON/OFF)
0000 1DCB

D=1:ディスプレイON
C=1:ブロックカーソルON
B=1:ブリンクON

ディスプレイON、ブロックカーソルONに変更します。
そのため、次のB7〜B0をONにします。

0000 1110
B7<--->B0

B7〜B0の必要ビットをONにしながらEをON→OFFします。
その後、B7〜B0をOFFにします。
そうすると画面の先頭にカーソルが表示されます。

手動で読み書きをやりたいためカーソルが出ていないと混乱するためです。
マイコンで書き込む場合にはカーソルがあるとカッコ悪いですから消した方がいいです。




▼次に2行表示の設定をします。

Function Set(通信モード、行数、Font sizeの設定)
0 0 1 DL N F x x

DL=1:8bit
DL=0:4bit
N=1:2line
N=0:1line
F=1:5x10dot
F=0:5x7dot

8bitモード2行表示、5x10dot表示できるようにします。
そのため、次のB7〜B0をONにします。

0011 1100
B7<--->B0

B7〜B0の必要ビットをONにしながらEをON→OFFにします。
その後、B7〜B0をOFFにします。
これで2行表示が出来るようになりました。




▼次にカーソルを任意の位置に移動します。

Set DDRAM address
1 AC6 AC5 AC4 AC3 AC2 AC1 AC0
DD RAMのアドレス(カーソル位置)をセットします。以後DD RAMへのデータアクセスとなる。

1行目の先頭にカーソルを移動するには、アドレスは0x00ですので、アドレスに000 0000を入れます。

1000 0000
B7<--->B0

B7〜B0の必要ビットをONにしてEをON→OFFします。
その後、B7〜B0をOFFにします。
カーソルが1行目の先頭に移動します。


2行目の先頭にカーソルを移動するには、2行目の先頭アドレスは0x40となりますので
2進数の0x40である1000000をB7〜B0に指定します。

1100 0000
B7<--->B0

B7〜B0の必要ビットをONにしてEをON→OFFします。
その後、B7〜B0をOFFにします。
そうすると、カーソルが二行目の先頭に移動します。




▼カーソルの位置に文字を表示する

Write data to RAM
D7 D6 D5 D4 D3 D2 D1 D0
CG RAM・DD RAMへのデータ書き込み

0011 0000
B7<--->B0

0の文字コード0x30は2進数で 0011 0000

B7〜B0の0011 0000をONにしながら、RSもONにしてEをONにします。
その後、EをOFFにした瞬間に表示されます。
EのON・OFFを繰り返すと連続して表示されます。




▼画面消去

Clear Display
0000 0001

の信号をONにしてEをON→OFFにします。
その後、B7〜B0をOFFにします。
全表示クリア後カーソルをホーム位置(0x00)へ戻ります。






■4bit モード

4ビットモードだと、8ビットモードの時にB0からB7までの端子を使っていたのに対して、B4からB7の4本の端子で操作できます。
ただ、命令やデータは8ビットのため、上位ビット・下位ビットの順に2回の動作に分けて転送する必要があります。


▼まずは初期化

最初はどのような状態なのかわからないため、8ビットモードに強制的に変更します。

Function Set(通信モード、行数、Font sizeの設定)
0 0 1 DL N F x x

DL=1:8bit
DL=0:4bit
N=1:2line
N=0:1line
F=1:5x10dot
F=0:5x7dot


0 0 1 1 + EをON->OFF
0 0 1 1 + EをON->OFF
0 0 1 1 + EをON->OFF
B7<---->B4

B7<->B4の必要な端子をONして、その後、EをON->OFFすることにより実行されます。
3回送ることにより8ビットモードに強制変更されます


▼4ビットモードに変更

0 0 1 0 + EをON->OFF
B7<---->B4

ココから先は4ビットモードのため、8ビットの命令やデータを送る時には、 上位ビット(B7<->B4)のビットをLCDのB7<->B4に入れてからEをON->OFFし、
その後、下位ビット(B3<->B0)をLCDのB7<->B4入れてEをON->OFFすることにより8ビット分が転送できます。


▼ディスプレイをONにしてカーソルONにする

Display ON/OFF(表示、カーソルON/OFF)
0000 1DCB

D=1:ディスプレイON
C=1:ブロックカーソルON
B=1:ブリンクON

ディスプレイON、ブロックカーソルONに変更します。
そのため、次のB7〜B0をONにします。

0 0 0 0 + EをON->OFF
1 1 1 0 + EをON->OFF
B7<---->B4




▼次に2行表示の設定をします。

Function Set(通信モード、行数、Font sizeの設定)
0 0 1 DL N F x x

DL=1:8bit
DL=0:4bit
N=1:2line
N=0:1line
F=1:5x10dot
F=0:5x7dot

4bitモード2行表示、5x10dot表示できるようにします。
そのため、次のB7〜B4をONにします。

0 0 1 0 + EをON->OFF
1 1 0 0 + EをON->OFF
B7<---->B4




▼次にカーソルを任意の位置に移動します。

Set DDRAM address
1 AC6 AC5 AC4 AC3 AC2 AC1 AC0
DD RAMのアドレス(カーソル位置)をセットします。以後DD RAMへのデータアクセスとなる

1行目の先頭にカーソルを移動するには、アドレスは0x00ですので、アドレスに000 0000を入れます。

1 0 0 0 + EをON->OFF
0 0 0 0 + EをON->OFF
B7<---->B4

2行目の先頭にカーソルを移動するには、2行目の先頭アドレスは0x40となりますので
2進数の0x40である1000000を指定します。

1 1 0 0 + EをON->OFF
0 0 0 0 + EをON->OFF
B7<---->B4




▼カーソルの位置に文字を表示する

Write data to RAM
D7 D6 D5 D4 D3 D2 D1 D0
CG RAM・DD RAMへのデータ書き込み

0の文字コード0x30は2進数で 0011 0000

0 0 1 1 RS + EをON->OFF
0 0 0 0 RS + EをON->OFF
B7<---->B4




▼画面消去

Clear Display
0000 0001

0 0 0 0 + EをON->OFF
0 0 0 1 + EをON->OFF
B7<---->B4






■PICマイコンと接続して表示する

4ビットモードの方法が解った事ですのでPIC16F84と接続して表示したいと思います。
あまりたくさんのポートを使いたく無いのでポートB側だけ使用します。

VOにはコントラスト調整用の10KΩぐらいの可変抵抗を取り付けてもう一方の線はマイナス極に接続します。
LEDバックライトの必要なLCDの場合にはAには200Ωぐらいの抵抗を取り付けてプラス極に、Kはマイナス極に接続します。
そして、非常に重要なのが、LCDのRWとD0、D1、D2、D3の端子をマイナス極に接続する事です。
当初、何も接続しないで端子をフリーにしていて、そのため全く動作せず1週間ぐらい悩みました。
ネットを調べると端子はフリーみたいな記述がみられますが、マイナス側に接続しないと全く動きません。
あと、LCDのVddはプラス側にVssはマイナス側に接続しますが、間違えると壊れます。


実際に作って動かしてみた物 デバッグのためのLEDがたくさん並んでます。

4ビットモードで手動で行った操作をそのままPICで再現するだけで動作しました。
以下、上の方で手動で行った操作とほぼ同じ動作をさせるためのアセンブラソースです。
赤文字部分が手動で行った操作を真似てる部分です。
	LIST      P=16F84
	#include <p16F84.inc>

	__CONFIG _CP_OFF & _LP_OSC & _PWRTE_ON & _WDT_OFF

;コンフィグレーションビットの設定
;_LP_OSC		低電力振動子(一般的に200kHz以下)
;_XT_OSC		低周波数振動子(4MHzまで)
;_HS_OSC		高周波数振動子(4-20MHzまで)
;_RC_OSC		抵抗とコンデンサによる発振

;_WDT_ON		ウォッチドッグタイマを有効にする
;_WDT_OFF		ウォッチドッグタイマを無効にする

;_PWRTE_ON		電源投入直後のリセット期間を有効にする
;_PWRTE_OFF		電源投入直後のリセット期間を無効にする

;_CP_ON			プログラムの読み取りを可能にする
;_CP_OFF		プログラムの読み取りを不可能にする

;---------------------------------------------------------------
;アドレスに名前を付ける
;---------------------------------------------------------------


;割り込み時にレジスタを退避させるメモリ
w_temp		equ	0x0C
status_temp	equ	0x0D

pos1			equ	0x0E
pos2			equ	0x0F
;ウェイト用メモリ
wait_val1		equ	0x10
wait_val2		equ	0x11

;PIC16F84では0x0Cから0x4Fまでが使用可能
;***************************************************************
;リセットベクタ
;***************************************************************
		org	0
		goto	start
;***************************************************************
;割り込みベクタ
;***************************************************************
;割り込みの設定
;  INTCONレジスタ
;     0bit   RBIF   RB4〜RB7の状態変化割込みフラグ
;     1bit   INTF   RB0/INTの割込みフラグ
;     2bit   T0IF   TMR0タイマ割込みフラグ
;     3bit   RBIE   RB4〜RB7の割込み許可ビット
;     4bit   INTE   RB0/INTの割込み許可ビット
;     5bit   T0IE   TMR0タイマの割込み許可ビット
;     6bit   EEIE   データEEPROM書き込み完了割込み許可
;     7bit   GIE    全体割込み許可ビット
;***************************************************************
		org	4

		;レジスタの退避
		movwf	w_temp
		movf	STATUS,w
		clrf	STATUS
		movwf	status_temp
		
		;各割り込みに対して適切なアドレスにジャンプさせる
		btfsc	INTCON,RBIF
		goto	int0
		btfsc	INTCON,INTF
		goto	int1
		btfsc	INTCON,T0IF
		goto	int2
intret
		bcf	INTCON,RBIF		;RB4~RB7割り込みフラグリセット
		bcf	INTCON,INTF		;RB0/INT割り込みフラグリセット
		bcf	INTCON,T0IF		;タイマー割り込みフラグリセット
		;レジスタの復帰
		clrf	STATUS
		movf	status_temp,w
		movwf	STATUS
		swapf	w_temp,f
		swapf	w_temp,w
		retfie			;割り込みから復帰

;---------------------------------------------------------------
;RB4〜RB7割り込みにより実行
;---------------------------------------------------------------
int0					;RB4~RB7割り込み

		;割り込み時の処理をここに記述

		goto	intret
;---------------------------------------------------------------
;RB0/INT割り込みにより実行
;---------------------------------------------------------------
int1					;RB0/INT割り込み

		;割り込み時の処理をここに記述

		goto	intret
;---------------------------------------------------------------
;タイマー割り込みにより実行
;---------------------------------------------------------------
int2		;タイマー割り込み
		;タイマーにはクロックが1/4周期で供給されるため、
		;10MHzクロックでは 1/2500000secとなる
		;1/19200 sec(52 usec)毎にタイマー割り込みを入れるために
		;減算タイマー値に256-130=0x7Eを設定
		;しかし、割り込みから、ここまでに0x0Eほどかかるため加算する
		movlw	0x7E+0x0E		;タイマー値リセット
		movwf	TMR0

		;割り込み時の処理をここに記述
		goto	intret		;ジャンプ
;***************************************************************
;スタート
;***************************************************************
start
;---------------------------------------------------------------
;ポートの設定
;---------------------------------------------------------------
		clrf	PORTA
		clrf	PORTB
		bsf	STATUS,5		;ページを1に切り替え
		movlw	b'00000000
		movwf	TRISA			;portAの00000000を入力に設定
		movlw	b'00000000
		movwf	TRISB			;portBの00000000を入力に設定(全て出力に設定)
		bcf	STATUS,5		;ページを0に切り替え
;---------------------------------------------------------------
;***************************************************************
;割り込みの設定
;  INTCONレジスタ
;     0bit   RBIF   RB4〜RB7の状態変化割込みフラグ
;     1bit   INTF   RB0/INTの割込みフラグ
;     2bit   T0IF   TMR0タイマ割込みフラグ
;     3bit   RBIE   RB4〜RB7の割込み許可ビット
;     4bit   INTE   RB0/INTの割込み許可ビット
;     5bit   T0IE   TMR0タイマの割込み許可ビット
;     6bit   EEIE   データEEPROM書き込み完了割込み許可
;     7bit   GIE    全体割込み許可ビット
;***************************************************************
		clrf	INTCON
;---------------------------------------------------------------
;RB0/INT割り込みの設定
;---------------------------------------------------------------
		bsf	STATUS,5		;ページを1に切り替え
		bcf	OPTION_REG,6		;RB0のエッジ設定は立ち上がり
		bcf	STATUS,5		;ページを0に切り替え
;		bsf	INTCON,INTE		;RB0/INT割り込み発生許可
;---------------------------------------------------------------
;RB4〜RB7割り込みの設定
;---------------------------------------------------------------
;		bsf	INTCON,RBIE		;RB4〜RB7割り込み
;---------------------------------------------------------------
;タイマー割り込みの設定
;---------------------------------------------------------------
;		movlw	0x00			;タイマー値リセット
;		movwf	TMR0
;		bsf	STATUS,5		;ページを1に切り替え
;		bsf	OPTION_REG,0		;PS0	プリスケーラの設定
;		bsf	OPTION_REG,1		;PS1	
;		bsf	OPTION_REG,2		;PS2	
;		bsf	OPTION_REG,3		;PSA	プリスケーラをTMRで使用する場合は0,WDTで使用する場合は1
;		bcf	OPTION_REG,5		;T0CS	タイマ0の入力先 1でRA4ピン入力,0でクロック1/4入力
;		bcf	STATUS,5		;ページを0に切り替え
;		bsf	INTCON,T0IE		;タイマ割り込み発生許可
;---------------------------------------------------------------
;割り込みの開始
;---------------------------------------------------------------
;		bsf	INTCON,GIE		;割り込み許可
;***************************************************************
;メイン
;***************************************************************
init

main
		call wait_long

;初期化
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'00110000
		call lcd_out
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'00110000
		call lcd_out
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'00110000
		call lcd_out
;4ビットモードに変更
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'00100000
		call lcd_out

;ディスプレイをONにしてカーソルONにする

;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'00000000
		call lcd_out
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'11100000
		call lcd_out

;2行表示の設定
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'00100000
		call lcd_out
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'11000000
		call lcd_out


;カーソルを任意の位置に移動
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'11000000
		call lcd_out
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'00000000
		call lcd_out

;カーソルの位置に文字を表示する
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'00111000
		call lcd_out
;                         7654SE    LCDの端子に出力するためのビット位置
		MOVLW	b'00001000
		call lcd_out



		sleep
		goto	main


;---------------------------------------------------------------
;Wレジスタの内容をLCDに送り一定時間待つ
;---------------------------------------------------------------
lcd_out
		MOVWF	pos1		;WレジスタからFレジスタに代入
		MOVWF	pos2		;WレジスタからFレジスタに代入
		BSF pos2, 2		;EをONにする

		MOVFW	pos2
		MOVWF	PORTB		;WレジスタからFレジスタに代入
		call wait_short

		MOVFW	pos1
		MOVWF	PORTB		;WレジスタからFレジスタに代入
		call wait_short

		clrf	PORTB
		return

;---------------------------------------------------------------
;短い時間のウエイト
;---------------------------------------------------------------
wait_short
		MOVLW	0x00
		MOVWF	wait_val1
wait_short_loop0
		decfsz	wait_val1,F
		goto	wait_short_loop0
;
		return

;---------------------------------------------------------------
;長い時間のウエイト
;---------------------------------------------------------------
wait_long
		MOVLW	0x00
		MOVWF	wait_val1
wait_long1
		MOVLW	0x00
		MOVWF	wait_val2
wait_long2	
		decfsz	wait_val2,F
		goto	wait_long2
		decfsz	wait_val1,F
		goto	wait_long1

		return

		END


▲トップページ > マイコンなど