今回は、LCDキャラクタ・ディスプレーを接続、メッセージを表示したいと思います。
LCDには、Z80でも使用していた、「KKHMF DC 5V 1602 LCD ディスプレイモジュール 16×2キャラクタ LCDブルーブラックライト」 (amazonで購入)を使用しました。

LCDは4bitモードで使用します。また、R/WはWrite(Lowレベル)に固定しました。STC12C2052のP1ポートに接続しましたが、使用していないP1.0及びP1.1は出力設定となっていますので抵抗1Kでプルダウンしています。
書き込み時P1.0及びP1.1をLowレベルに落とさないといけませんので1KΩでのプルダウンとしました。

LCDを接続した回路は次のようになります。

まずポートの設定を行います。PIMO及びP1M1レジスタに設定することで出力タイプ及び入力に設定できます。今回は8051コンパチの設定にしました。

	mov	P1M0,0b00000000		;output 
	mov	P1M1,0b00000000		;P1.0 - P1.7 output

LCDに接続するポートを設定します。

LCD_PORT	.equ	P1
LCD_RS		.equ	P1.2
LCD_E		.equ	P1.3

LCDを初期化します。

lcdinit:				;LCD init(4bit mode)
	mov	a,#0x03
	lcall	lcd4bitwrite
	mov	a,#5			;5ms delay
	lcall	delayms
	mov	a,#0x03
	lcall	lcd4bitwrite	
	mov	a,#0x03
	lcall	lcd4bitwrite

	mov	a,#0x02			;4bit mode
	lcall	lcd4bitwrite

	mov	a,#0x28			;function set
	lcall	lcd8bitwrite		;4bit bus, 2 line, 1 line=8

	mov	a,#0x0c			;disp on,under cursor off,block cursor off
	lcall	lcd8bitwrite
	mov	a,#0x01			;disp clr
	lcall	lcd8bitwrite
	mov	a,#02			;2 ms delay
	lcall	delayms

	mov	a,#0x06			;disp address incrmant on,disp shift off
	lcall	lcd8bitwrite

	mov	a,#0x02			;cursor home set
	lcall	lcd8bitwrite

	mov	a,#02			;2 ms delay
	lcall	delayms

	ret

4ビットモードでの書き込みと8ビット単位での書き込みのサブルーチンをコマンド用及びデータ用に作成します。

lcd8bitwrite:			;command mode 8bit data LCD output
	mov	r1,a
	lcall	llcd4bitwrite
	mov	a,r1
	lcall	lcd4bitwrite
	ret

lcd4bitwrite:
	rl	a		;command mode 4bit data LCD output
	rl	a		;4bit data upper 4bit set
	rl	a
	rl	a
llcd4bitwrite:
	ANL	a,#0xf0		;LCD RS or E Low 
	mov	LCD_PORT,a	;LCD PORT output
	lcall	delay100us
	setb	LCD_E		;LCD E Hi
	lcall	delay100us
	clr	LCD_E
	lcall	delay100us
	ret

datalcd8bitwrite:			;data mode 8bit data LCD output
	mov	r1,a
	lcall	ldatalcd4bitwrite
	mov	a,r1
	lcall	datalcd4bitwrite
	ret

datalcd4bitwrite:
	rl	a		;data mode 4bit data LCD output
	rl	a		;4bit data upper 4bit set
	rl	a
	rl	a
ldatalcd4bitwrite:
	ANL	a,#0xf0		;LCD RS or E Low 
	mov	LCD_PORT,a	;LCD PORT output
	lcall	delay100us
	setb	LCD_RS		;LCD RS Hi
	lcall	delay100us
	setb	LCD_E		;LCD E Hi
	lcall	delay100us	
	clr	LCD_E
	lcall	delay100us
	clr	LCD_RS
	lcall	delay100us		
	ret

時間稼ぎのdelayルーチンを作成します。100μSの基準となるカウント値をD100Uに設定します。delayルーチンでは R0,R1,R2レジスタを使用しています。

D100U		.equ	0x88

delayms:				;a reg ms delay
	mov	r2,a
delaymloop:
	lcall	delay1ms
	djnz	r2,delaymloop
	ret

delay1ms:
	lcall	delay500us
	lcall	delay500us
	ret

delay500us:
	mov	r1,#0x05
delay500uloop:
	lcall	delay100us
	djnz	r1,delay500uloop
	ret


delay100us:
	mov	r0,#D100U
delay1:
	djnz	r0,delay1
	ret

実際のLCDにの表示には、DPTRレジスタに文字列の先頭アドレスを設定し、0x00で終端をチェックしています。

	mov	DPTR,	#lcd_msg
main_msg1_loop:
	clr	a
	movc	a,@a+DPTR
	jz	main_msg2
	inc	DPTR	
	lcall	datalcd8bitwrite
	sjmp	main_msg1_loop
main_msg2:
	mov	a,#0xc0			;0x80 +0x40(2line top address)
	lcall	lcd8bitwrite

	mov	DPTR,	#lcd_msg2
main_msg2_loop:
	clr	a
	movc	a,@a+DPTR
	jz	loop
	inc	DPTR
	lcall	datalcd8bitwrite
	sjmp	main_msg2_loop

lcd_msg:
    .db    'H
    .db    'e
    .db    'l
    .db    'l
    .db    'o
    .db    '8
    .db    '0
    .db    '5
    .db    '1
    .db    0xba  ;コ
    .db    0xb1  ;ア
    .db    'W
    .db    'o
    .db    'r
    .db    'l
    .db    'd
    .db	   0x00
  
 lcd_msg2:
    .db    'S
    .db    'T
    .db    'C
    .db    '1
    .db    '2
    .db    'C
    .db    '2
    .db    '0
    .db    '5
    .db    '2
    .db    0xc6 ;ニ
    .db    0xd3 ;モ
    .db    0xb4 ;エ
    .db    0xc0 ;タ
    .db    0xb2 ;イ
    .db    '!

    .db    0x00

全体的なソフトは次ようようになります。

サブルーチンを多用しているので、スタックポインタの設定と表示後は、無限ロープとなっています。


表示は1行目に Hello8051コアWorld 2行目にSTC12C2052ニモエタイ! と表示されます。

; STC12C2052  LCD Character Display Test  Pinecone 2019/11/29
;
; STC12C2052 cpu
; Flash ROM 2Kbyte
; RAM       256byte
; External clock -
;
; assembler
;  program start 000H 0000H-07ffH
;  main          100H
;
; assemblers  ASxxxx and ASlink V5.10
; file name 2052_lcd01.asm
; $ as8051 -l -s -o 2052_lcd01.asm
; $ aslink -i 2052_lcd01
; $ program download  stcgl 2052_lcd01.ixh  
;       

D100U		.equ	0x88

LCD_PORT	.equ	P1
LCD_RS		.equ	P1.2
LCD_E		.equ	P1.3


P1M0	.equ	0x91
P1M1	.equ	0x92

	.area	TEST(ABS)

	.org	0x0000

	ljmp	main

	.org	0x0100
main:
	mov	sp,#0x3f
	mov	P1M0,0b00000000		;output 
	mov	P1M1,0b00000000		;P1.0 - P1.7 output

	mov	a,#15			;15ms delay
	lcall	delayms

	lcall	lcdinit
	mov	DPTR,	#lcd_msg
main_msg1_loop:
	clr	a
	movc	a,@a+DPTR
	jz	main_msg2
	inc	DPTR	
	lcall	datalcd8bitwrite
	sjmp	main_msg1_loop
main_msg2:
	mov	a,#0xc0			;0x80 +0x40(2line top address)
	lcall	lcd8bitwrite
	mov	DPTR,	#lcd_msg2
main_msg2_loop:
	clr	a
	movc	a,@a+DPTR
	jz	loop
	inc	DPTR
	lcall	datalcd8bitwrite
	sjmp	main_msg2_loop
	
loop:	sjmp	loop

lcdinit:				;LCD init(4bit mode)
	mov	a,#0x03
	lcall	lcd4bitwrite
	mov	a,#5			;5ms delay
	lcall	delayms
	mov	a,#0x03
	lcall	lcd4bitwrite	
	mov	a,#0x03
	lcall	lcd4bitwrite

	mov	a,#0x02			;4bit mode
	lcall	lcd4bitwrite

	mov	a,#0x28			;function set
	lcall	lcd8bitwrite		;4bit bus, 2 line, 1 line=8

	mov	a,#0x0c			;disp on,under cursor off,block cursor off
	lcall	lcd8bitwrite
	mov	a,#0x01			;disp clr
	lcall	lcd8bitwrite
	mov	a,#02			;2 ms delay
	lcall	delayms

	mov	a,#0x06			;disp address incrmant on,disp shift off
	lcall	lcd8bitwrite

	mov	a,#0x02			;cursor home set
	lcall	lcd8bitwrite

	mov	a,#02			;2 ms delay
	lcall	delayms

	ret

lcd8bitwrite:			;command mode 8bit data LCD output
	mov	r1,a
	lcall	llcd4bitwrite
	mov	a,r1
	lcall	lcd4bitwrite
	ret

lcd4bitwrite:
	rl	a		;command mode 4bit data LCD output
	rl	a		;4bit data upper 4bit set
	rl	a
	rl	a
llcd4bitwrite:
	ANL	a,#0xf0		;LCD RS or E Low 
	mov	LCD_PORT,a	;LCD PORT output
	lcall	delay100us
	setb	LCD_E		;LCD E Hi
	lcall	delay100us
	clr	LCD_E
	lcall	delay100us
	ret

datalcd8bitwrite:			;data mode 8bit data LCD output
	mov	r1,a
	lcall	ldatalcd4bitwrite
	mov	a,r1
	lcall	datalcd4bitwrite
	ret

datalcd4bitwrite:
	rl	a		;data mode 4bit data LCD output
	rl	a		;4bit data upper 4bit set
	rl	a
	rl	a
ldatalcd4bitwrite:
	ANL	a,#0xf0		;LCD RS or E Low 
	mov	LCD_PORT,a	;LCD PORT output
	lcall	delay100us
	setb	LCD_RS		;LCD RS Hi
	lcall	delay100us
	setb	LCD_E		;LCD E Hi
	lcall	delay100us	
	clr	LCD_E
	lcall	delay100us
	clr	LCD_RS
	lcall	delay100us		
	ret
delayms:				;a reg ms delay
	mov	r2,a
delaymloop:
	lcall	delay1ms
	djnz	r2,delaymloop
	ret

delay1ms:
	lcall	delay500us
	lcall	delay500us
	ret

delay500us:
	mov	r1,#0x05
delay500uloop:
	lcall	delay100us
	djnz	r1,delay500uloop
	ret


delay100us:
	mov	r0,#D100U
delay1:
	djnz	r0,delay1
	ret

lcd_msg:
    .db    'H
    .db    'e
    .db    'l
    .db    'l
    .db    'o
    .db    '8
    .db    '0
    .db    '5
    .db    '1
    .db    0xba  ;コ
    .db    0xb1  ;ア
    .db    'W
    .db    'o
    .db    'r
    .db    'l
    .db    'd
    .db	   0x00
  
 lcd_msg2:
    .db    'S
    .db    'T
    .db    'C
    .db    '1
    .db    '2
    .db    'C
    .db    '2
    .db    '0
    .db    '5
    .db    '2
    .db    0xc6 ;ニ
    .db    0xd3 ;モ
    .db    0xb4 ;エ
    .db    0xc0 ;タ
    .db    0xb2 ;イ
    .db    '!

    .db    0x00

    .end
    
おすすめの記事