目次>5章 第2ステップ(色々な実験)>(17)液晶ディスプレイを使う >ソース

液晶ディスプレイを使う(ソース)

更新日2008.4.13

以下のソースを取り込んで、アセンブル→PIC書き込み→実行して下さい。

; ========================== ここから ==============================
;	PIC16F84A
;	clock:20MHz
;
;	LCDを4ビットで制御
;
;	PICのピン接続
;		RB0	LCD DB4
;		RB1	LCD DB5
;		RB2	LCD DB6
;		RB3	LCD DB7
;
;		RA0	LCD R/W	(6:Read/Write)
;		RA1	LCD E	(5:Enable Signal)
;		RA2	LCD RS	(4:Register Select)
;
;	使用タイマ(プログラムループ)
;		 15mS	LCDパワーオンリセット待ち
;		  5mS	LCD初期化ルーチン
;		  1mS	LCD初期化ルーチン
;		 50uS	LCD初期化ルーチン,書き込み待ち
;


       LIST    P=PIC16F84A
       INCLUDE P16F84A.INC
       __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF


	CBLOCK	020h
	save_st			;STATUSのセーブ
	save_w			;W-regのセーブ
	CNT15mS			;15mSカウンタ
	CNT5mS			;5mSカウンタ
	CNT1mS			;1mSカウンタ
	CNT50uS			;50μSカウンタ
	char			;LCD表示データ
	ENDC

RW	EQU	00h		;LCD R/W
E	EQU	01h		;LCD Enable
RS	EQU	02h		;LCD Register Select
BUSY	EQU	03h		;BUSY FLAG (PORTB,3)


; ==================== 初期処理 =====================
	org	0
init
	BSF	STATUS,RP0	;■バンク1に切替え
	MOVLW	0F8h
	MOVWF	TRISA		;RA0-2は出力
	MOVLW	0F0h
	MOVWF	TRISB		;RB0-3は出力
	BCF	STATUS,RP0	;■バンク0に切替え

	CLRF	PORTA
	CLRF	PORTB

	CALL	LCD_init	;LCD 初期化

; ==================== メイン処理 =====================
main
	CALL	LCD_home	;カーソルを1行目の先頭に
	MOVLW	'H'
	CALL	LCD_write
	MOVLW	'e'
	CALL	LCD_write
	MOVLW	'l'
	CALL	LCD_write
	MOVLW	'l'
	CALL	LCD_write
	MOVLW	'o'
	CALL	LCD_write
	MOVLW	','
	CALL	LCD_write

	CALL	LCD_2line	;カーソルを2行目の先頭に
	MOVLW	'w'
	CALL	LCD_write
	MOVLW	'o'
	CALL	LCD_write
	MOVLW	'r'
	CALL	LCD_write
	MOVLW	'l'
	CALL	LCD_write
	MOVLW	'd'
	CALL	LCD_write
	MOVLW	'!'
	CALL	LCD_write

	CLRF	PORTA
	CLRF	PORTB
	SLEEP

	GOTO	main


;================= LCD表示をクリアする ===================
LCD_clear
	MOVLW	01h
	CALL	LCD_command
	RETURN

;================= LCDのカーソル位置を先頭に戻す =========
LCD_home
	MOVLW	02h
	CALL	LCD_command
	RETURN

;================= LCDのカーソル位置を2行目の先頭に =====
LCD_2line
	MOVLW	0C0h
	CALL	LCD_command
	RETURN

;================= LCDのディスプレイをONにする =========
LCD_on
	MOVLW	0Ch
	CALL	LCD_command
	RETURN

;================= LCDのディスプレイとカーソルをONにする ==
LCD_on_cur
	MOVLW	0Eh
	CALL	LCD_command
	RETURN

;================= LCDのディスプレイをOFFにする =======
LCD_off
	MOVLW	08h
	CALL	LCD_command
	RETURN

;================= LCDにデータを送る =====================
LCD_write
	MOVWF	char
	CALL	LCD_BF_wait	;LCD busy 解除待ち

	BCF	PORTA,RW	;R/W=0(Write)
	BSF	PORTA,RS	;RS=1(Data)

	MOVLW	0F0h		;PORTBの下位4ビットを
	ANDWF	PORTB,F		; クリア
	SWAPF	char,W		;上位
	ANDLW	0Fh		;4ビットを
	IORWF	PORTB,F		;PORTB(3-0)にセット(PORTB(7-4)はそのまま)
	BSF	PORTA,E		;LCDにデータ書き込み
	NOP
	BCF	PORTA,E

	MOVLW	0F0h		;PORTBの下位4ビットを
	ANDWF	PORTB,F		; クリア
	MOVF	char,W		;下位
	ANDLW	0Fh		;4ビットを
	IORWF	PORTB,F		;PORTB(3-0)にセット(PORTB(7-4)はそのまま)
	BSF	PORTA,E		;LCDにデータ書き込み
	NOP
	BCF	PORTA,E

	RETURN

;================= LCDにコマンドを送る ===================
LCD_command
	MOVWF	char
	CALL	LCD_BF_wait	;LCD busy 解除待ち

	BCF	PORTA,RW	;R/W=0(Write)
	BCF	PORTA,RS	;RS=0(Command)

	MOVLW	0F0h		;PORTBの下位4ビットを
	ANDWF	PORTB,F		; クリア
	SWAPF	char,W		;上位
	ANDLW	0Fh		;4ビットを
	IORWF	PORTB,F		;PORTB(3-0)にセット(PORTB(7-4)はそのまま)
	BSF	PORTA,E		;LCDにデータ書き込み
	NOP
	BCF	PORTA,E

	MOVLW	0F0h		;PORTBの下位4ビットを
	ANDWF	PORTB,F		; クリア
	MOVF	char,W		;下位
	ANDLW	0Fh		;4ビットを
	IORWF	PORTB,F		;PORTB(3-0)にセット(PORTB(7-4)はそのまま)
	BSF	PORTA,E		;LCDにデータ書き込み
	NOP
	BCF	PORTA,E

	RETURN

;================= LCD Busy 解除待ち ========================
LCD_BF_wait
	BCF	PORTA,E
	BCF	PORTA,RS	;RS=0(Control)
	BSF	PORTA,RW	;R/W=1(Read) Busy Flag read

	BSF	STATUS,RP0	;■バンク1に切替え
	MOVLW	0FFh
	MOVWF	TRISB		;RB0-7は入力
	BCF	STATUS,RP0	;■バンク0に切替え
	BSF	PORTA,E		;LCD上位4ビット読み込み
	NOP
	BTFSS	PORTB,BUSY	;LCD Busy ?
	GOTO	LCD_BF_wait1	; No
	BCF	PORTA,E
	NOP
	BSF	PORTA,E		;LCD下位4ビット読み飛ばし
	NOP
	BCF	PORTA,E
	GOTO	LCD_BF_wait

LCD_BF_wait1
	BSF	PORTA,E		;LCD下位4ビット読み飛ばし
	NOP
	BCF	PORTA,E
	BSF	STATUS,RP0	;■バンク1に切替え
	MOVLW	0F0h		;RB0-3は出力
	MOVWF	TRISB
	BCF	STATUS,RP0	;■バンク0に切替え

	RETURN

;================= LCD初期化 ================================
LCD_init
	CALL	wait15ms	;15mS待つ
	BCF	PORTA,RW	;R/W=0
	BCF	PORTA,RS	;RS=0
	BCF	PORTA,E		;E=0

	MOVLW	0F0h		;PORTBの上位4ビットを
	ANDWF	PORTB,W		;取り出す(変更しないように)
	IORLW	03h		;下位4ビットに'3'をセット
	MOVWF	PORTB
	BSF	PORTA,E		;ファンクションセット(1回目)
	NOP
	BCF	PORTA,E
	CALL	wait5ms		;5mS待つ

	MOVLW	0F0h		;PORTBの上位4ビットを
	ANDWF	PORTB,W		;取り出す(変更しないように)
	IORLW	03h		;下位4ビットに'3'をセット
	MOVWF	PORTB
	BSF	PORTA,E		;ファンクションセット(2回目)
	NOP
	BCF	PORTA,E
	CALL	wait5ms		;5mS待つ

	MOVLW	0F0h		;PORTBの上位4ビットを
	ANDWF	PORTB,W		;取り出す(変更しないように)
	IORLW	03h		;下位4ビットに'3'をセット
	MOVWF	PORTB
	BSF	PORTA,E		;ファンクションセット(3回目)
	NOP
	BCF	PORTA,E
	CALL	wait5ms		;5mS待つ

	MOVLW	0F0h		;PORTBの上位4ビットを
	ANDWF	PORTB,W		;取り出す(変更しないように)
	IORLW	02h		;4ビットモード
	MOVWF	PORTB		;に
	BSF	PORTA,E		;設定
	NOP
	BCF	PORTA,E
	CALL	wait1ms		;1mS待つ

	MOVLW	028h		;4ビットモード,2行表示,7ドット
	CALL	LCD_command
	CALL	LCD_off		;ディスプレイOFF
	CALL	LCD_clear	;LCDクリア
	MOVLW	06h		;
	CALL	LCD_command	;カーソルモードセット (Increment)
	CALL	LCD_on		;ディスプレイON,カーソルOFF

	RETURN

;================= 15mS WAIT ================================
wait15ms
	MOVLW	d'3'
	MOVWF	CNT15mS
wait15ms_loop
	CALL	wait5ms
	DECFSZ	CNT15mS,F
	GOTO	wait15ms_loop
	RETURN

;================= 5mS WAIT =================================
wait5ms
	MOVLW	d'100'
	MOVWF	CNT5mS
wait5ms_loop
	CALL	wait50us
	DECFSZ	CNT5mS,F
	GOTO	wait5ms_loop
	RETURN

;================= 1mS WAIT =================================
wait1ms
	MOVLW	d'20'
	MOVWF	CNT1mS
wait1ms_loop
	CALL	wait50us
	DECFSZ	CNT1mS,F
	GOTO	wait1ms_loop
	RETURN

;================= 50μS WAIT ===============================
wait50us
	; 1サイクル(4クロック):0.2μS
	; 50μS=0.2μS×250サイクル

	MOVLW	d'82'		;1
	MOVWF	CNT50uS		;1
wait50us_loop
	DECFSZ	CNT50uS,F	;1
	GOTO	wait50us_loop	;2
	RETURN			;2+1

	END
; ========================== ここまで ==============================