;
; 16x2 LCDに表示してみる
;                                      2001/11/16
;
; 秋月アセンブラ用



;              ----__----
;       RA2 1-|*         |-18 RA1
;       RA3 2-|          |-17 RA0
; RA4 TOCKI 3-|          |-16 OSC1 CLKIN
;     /MCLR 4-|          |-15 OSC2 CLKOUT
;       Vss 5-| PIC16C84 |-14 Vdd
;   RB0 INT 6-|          |-13 RB7
;       RB1 7-|          |-12 RB6
;       RB2 8-|          |-11 RB5
;       RB3 9-|          |-10 RB4
;              ----------

;	I/Oポートの割り当て
; PORT A
LCD_E		equ		0	; RA0 - LCD E
LCD_RS		equ		1	; RA1 - LCD RS

; PORT B
LCD_DB4		equ		4	; RB4 - LCD DB4
LCD_DB5		equ		5	; RB5 - LCD DB5
LCD_DB6		equ		6	; RB6 - LCD DB6
LCD_DB7		equ		7	; RB7 - LCD DB7

;	LCDの余ったピンの処理
;	LCD DB0  - GND
;	LCD DB1  - GND
;	LCD DB2  - GND
;	LCD DB3  - GND
;	LCD R/~W - GND (常時ライト)



	.16c84				; デバイスの設定（省略できません）
	.osc	HS			; 発振タイプの設定
	.wdt	off			; ウォッチドックタイマの有効・無効の設定
	.pwrt	on			; パワーアップタイマの有効・無効の設定
	.protect	off		; プロテクトの設定

; -----------------------------------------------------------------------------

;	システムレジスタにラベル付け
STATUS		equ		03h		; ステータスレジスタ(BANK0)
RP0			equ		5		; STATUS,RP0 RAMのバンク切り替え
PORTA		equ		05h		; I/OポートA(BANK0)
PORTB		equ		06h		; I/OポートB(BANK0)
TRISA		equ		05h		; ポートA出力/入力設定 0:出力 1:入力(BANK1)
TRISB		equ		06h		; ポートB出力/入力設定 0:出力 1:入力(BANK1)
OPTION		equ		01h		; オプションレジスタ(BANK1)
RBPU		equ		7		; OPTION,RBPU ポートBのプルアップ 0:行う 1:行わない

CONST_WAIT_MS	equ		200	; ms 単位のウェイト用定数
							; CONST_WAIT_MS = (動作クロック[MHz]/4)*100
							; 10MHz 時 250
							;  8MHz 時 200
							;  6MHz 時 100

; -----------------------------------------------------------------------------

;	変数を宣言
		org		0ch
temp1		ds		1		; 0ch から 1 バイト分のメモリを確保し、
							; ラベル“temp1”を付ける（変数temp1）汎用一時変数
temp2		ds		1		; 汎用一時変数
temp3		ds		1		; 汎用一時変数
wait_count1	ds		1		; ウエイトルーチンで使うカウンタ
wait_count2	ds		1		; ウエイトルーチンで使うカウンタ

; -----------------------------------------------------------------------------

		org		000h		; リセット時は 000h からプログラムがスタート
		goto	start

		org		004h		; 割り込み時 004h にジャンプしてくる
		retfie

start
;	I/Oポートの設定
;	ポートA
		bsf		STATUS,RP0	; bank1
		movlw	11100000b
		;		   ||||+----- LCD_E			out
		;		   |||+------ LCD_RS		out
		;		   +++------- RA2-RA4 未使用
		movwf	TRISA		; 設定レジスタに書き込み

;	ポートB
		movlw	00000000b	;
		;		||||++++----- RB0-RB3 未使用
		;		|||+--------- LCD_DB4		out
		;		||+---------- LCD_DB5		out
		;		|+----------- LCD_DB6		out
		;		+------------ LCD_DB7		out
		movwf	TRISB		; 設定レジスタに書き込み
		bcf		STATUS,RP0	; bank0
		



;	LCDの初期化

		bcf		PORTA,LCD_E

		movlw	15
		call	wait			; 15ms 待つ

		bcf		PORTA,LCD_RS	;  RS DB7 DB6 DB5 DB4
		movlw	00110000b		;  0   0   0   1   1
		call	lcd_write4

		movlw	5
		call	wait			; 5ms 待つ

		movlw	00110000b
		call	lcd_write4

		movlw	1
		call	wait			; 1ms 待つ

		movlw	00110000b
		call	lcd_write4

		movlw	00100000b		;  DB7 DB6 DB5 DB4
		call	lcd_write4		;   0   0   1   0
								; 4ビットモードに設定

		movlw	00101000b		; 4bit, 1/16duty, 5x7
		call	lcd_write

		movlw	00000001b		; 表示クリア
		call	lcd_write

		movlw	2				; クリアには少し時間がかかるので
		call	wait			; 2ms 待つ

		movlw	00000110b		; エントリーモードセット
		call	lcd_write		; （カーソルの進み方の設定）

		movlw	00001110b		; 表示オン／オフコントロール
		call	lcd_write		; 表示オン, カーソル表示あり, ブリンクなし





; -----------------------------------------------------------------------------

;	ためしに“Hello”と表示させてみる

		bsf		PORTA,LCD_RS		; RS を 1
		
		movlw	048h				; H
		call	lcd_write

		movlw	065h				; e
		call	lcd_write

		movlw	06ch				; l
		call	lcd_write

		movlw	06ch				; l
		call	lcd_write

		movlw	06fh				; o
		call	lcd_write


loop
		goto	loop





; -----------------------------------------------------------------------------

;	LCDへの書き込み
;	wレジスタの内容をLCDに書き込む

lcd_write
		movwf	temp1		; temp1=w
		call	lcd_write4	; 上位4ビットの書き込み

		swapf	temp1,0		; temp1 の上位4ビットと下位4ビットを入れ替えて
							; wレジスタに代入

		call	lcd_write4	; 下位4ビットの書き込み

		return


;
;	書き込みサブルーチンのサブルーチン
;	wレジスタの上位4ビットだけを書き込む

;	ポートBの下位4ビットは変化しない

lcd_write4
		andlw	11110000b	; w = w & 11110000b
		movwf	temp2		; 書き込むデータの上位4ビットのみを退避

		movf	PORTB,0		; w=PORTB
		andlw	00001111b	; w=w&00001111b
							; ポートBの下位4ビットのみを取り出し

		iorwf	temp2,0		; w = w | temp2
		movwf	PORTB		; ボートBの下位4ビットとデータの上位4ビットを
							; 合成してポートBに出力

		bsf		PORTA,LCD_E	; イネーブル信号を出力
		nop
		bcf		PORTA,LCD_E

		movlw	1
		call	wait		; 少し待つ

		return





; -----------------------------------------------------------------------------

;	wレジスタの値に応じて ms 単位のウェイトを入れる

;	例、約2ms待つ
;	1:	movlw	2
;	2:	call	wait

;	メモ
;	使用クロックに応じて、定数 CONST_WAIT_MS を定義してください

;	CONST_WAIT_MS = (動作クロック[MHz]/4)*100

;	例、8Mhz時
;	CONST_WAIT_MS	equ	200

wait
		movwf	wait_count1		; wait_count1=w
wait_loop1
			movlw	CONST_WAIT_MS
			movwf	wait_count2		; wait_count2=CONST_WAIT_MS
wait_loop2
				nop
				nop
				nop
				nop
				nop
				nop
				nop
				decfsz	wait_count2,1		; wait_count2=wait_count2-1
				goto	wait_loop2	; if wait_count2!=0 goto wait_loop2
			decfsz	wait_count1,1		; wait_count1=wait_count1-1
			goto	wait_loop1	; if wait_count1!=0 goto wait_loop1
		retfie				; else return
