最近、格安のLCDをAmazonで見つけたので、Z80(Z180)につないでみましたぁ^^
使用したLCDは 「KKHMF DC 5V 1602 LCD ディスプレイモジュール 16×2キャラクタ LCDブルーブラックライト」と「EasyWordMall 1602 LCD ブラック IIC/I2C/TWI/SPI シリアル インタフェース ボード モジュール」です。
2つ合わせても 約350円とお買い得です。この組み合わせでI2C経由で表示できるのには驚きですよね~
だけど、表示するまでにはちょっと苦労がつきものですね^^
でも、先人の方の情報をもとに無事、表示することができましたので、忘れないようメモしたいと思います。
ハード面の確認からしていきます。
LCDは動作電圧は5V仕様なので、i2cは5V系になります。
LCDとI2Cインターフェイスモジュールは別々のモジュールなので半田付けが必要になります。
また、 I2Cインターフェイスモジュール を取り付ける際はLCDの液晶を固定している金具のツメが接触する恐れがありますので、I2Cインターフェイスモジュールの半田面には、絶縁テープを張った方が安全です。さらにツメが当たらないように少し浮かして半田付けしました。
i2cの接続はJ1のコネクターで、シルク表示で GND、Vcc、SDA、SCLの順番になっています。
半固定ボリュームはLCDの輝度調整用で、真ん中あたりにしておきます。
LEDと表示されているジャンパーを抜くとバックライトが消えるようです。
I2Cインターフェイスモジュール のスレーブアドレスは、
PCF8574T では、0x27
PCF8574ATでは、0x3fとなるようです。
アマゾンのレビューをみると2種類のデバイスが出荷されているよう
なのでついているデバイスの確認が必要です。
(ともに A0/A1/A2がオープンの時)
今回購入したものは、PCF8574Tで、0x27 となっていますので以下スレーブアドレスは、0x27の設定となっています。
ハードの準備ができましたので、ソフトの設定を行っていきます。
Z8S180側のI2Cインターフェイスはこれまでに使用してきているPCA9564を使用しますので、アドレスの設定を行います。
また、LCDの制御のために、RS/RW/EN/LEDの各端子のビット位置を設定します。ちなみに LCDへのデータ転送は、4BitモードになっていますのでD7~D4までの4Bitで設定します。また、スレーブアドレスの設定を行います
;; lcd 1602 port
;;
;; D0 > RS
;; D1 > R/W
;; D2 > E
;; D3 > LED on/off
;; D4 > DB4
;; D5 > DB5
;; D6 > DB6
;; D7 > DB7
I2CSTA .equ 0x80 ;PCA9564 setting adress
I2CTO .equ 0x80
I2CDAT .equ 0x81
I2CADR .equ 0x82
I2CCON .equ 0x83
RS .equ 0 ;command >0 :data transfer >1
RW .equ 1 ;write >0 : read >1
EN .equ 2 ;positive pulse
LED .equ 3 ;back light off >0 : on >1
ADDRES .equ 0x27 ;i2c slave address
まずは、I2C PCA9564の初期設定を行います。
続いて、LCDの初期化を行います。
16文字づつ2行を表示するメッセージを出力します。
.area TEST (ABS)
.org 0xa000
start: ;; main program
call i2c_init ;i2c init
call dely100u
call lcd_init ;LCD init
ld hl,lcd_msg ;msg output
ld b,16
main_loop:
ld a,(hl)
call data_lcd8bitwrite
inc hl
djnz main_loop
ld a,0xc0 ;0x80 + 0x40(2 line top address)
call lcd8bitwrite ; 2 line set
ld hl,lcd_msg2 ;msg output
ld b,16
main_loop2:
ld a,(hl)
call data_lcd8bitwrite
inc hl
djnz main_loop2
ret
LCDの初期化は、4bitモードで初期化をします。
lcd_init: ;LCD init(4bit mode)
ld a,0x03
call lcd4bitwrite
ld b,0x05 ;;5ms dely
call delym
ld a,0x03
call lcd4bitwrite
ld a,0x03
call lcd4bitwrite
ld a,0x02 ;;4 bit mode
call lcd4bitwrite
ld a,0x28 ;function set
call lcd8bitwrite ;4bit bus,2 line ,1 line=8
ld a,0x0c ;disp on,under cursor off,block cursor off
call lcd8bitwrite
ld a,0x01 ;disp clr
call lcd8bitwrite
ld b,0x02 ;;2mS dely
call delym
ld a,0x06 ;disp address incrmant on,disp shift off
call lcd8bitwrite
ld a,0x02 ;cursor home set
call lcd8bitwrite
ld b,0x02 ;;2ms dely
call delym
ret
LCDへの書き込みは4ビットごとに書き込みします。
書き込みには、コマンドデータと表示用データの書き込みの2種類があります。
モードの切り替えは RS端子で行います。
コマンドデータ >> RS=0
表示用データ >> RS=1
書き込みと読み出しのモード切替はRW端子で行います。
読み出し >> RW=1
書き込み >> RW=0
今回の場合は、読み出しは行わないので、RW端子は常に 0のままです。
実際の書き込みタイミングは、ENを正論理でパルスを送ります。
つまり、 EN >> 0>1>0のタイミングの1発だけのパルスを生成します。
バックライトは常にONにしています
パックライトON >> LED=1
バックライトOFF>> LED=0
コマンドデータの4ビットの書き込みは下記のようになりました
lcd4bitwrite: ;command mode 4bit data LCD output
rlca ;4bit data upper 4bit set
rlca
rlca
rlca
res RS,a ;LCD Command mode
res RW,a ;LCD Write mode
res EN,a ;LCD EN low
set LED,a ;LCD back light LED ON
push af
ld d,a ;i2c write data set
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
pop af
set EN,a ;LCD EN high
push af
ld d,a
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
pop af
res EN,a ;LCD EN low
ld d,a
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
ret
同じような手順で、表示データの4ビットの書き込みは下記のようになります。
コマンドデータの書き込みと統合するとプログラムは短くなりますが、あえてわかりやすいように(ちょっと言い訳)分けてみました
data_lcd4bitwrite: ;data mode 4bit data LCD output
rlca
rlca
rlca
rlca
set RS,a ;LCD RS data mode
res RW,a ;LCD write mode
res EN,a ;LCD EN low
set LED,a ;LCD back light LED ON
push af
ld d,a ;i2c write data set
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
pop af
set EN,a ;LCD EN high
push af
ld d,a ;i2c write data set
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
pop af
res EN,a ;LCD EN low
ld d,a ;i2c write data set
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
ret
8ビット単位の書き込みは、上位4ビットを書き込み続いて下位4ビットを書き込みしています。
コマンド書き込みと表示データ書き込みは次のようになります。
lcd8bitwrite: ;command mode 8bit data LCD output
push af ;
rrca ;8bit data upper 4bit data LED output
rrca
rrca
rrca
call lcd4bitwrite ;command mode 4bit data LCD output
pop af ;8bit data low 4bit data LED output
call lcd4bitwrite ;command mode 4bit data LCD output
ret
data_lcd8bitwrite: ;data mode 8bit data LCD output
push af
rrca ;8bit data upper 4bit data LED output
rrca
rrca
rrca
call data_lcd4bitwrite ;command mode 4bit data LCD output
pop af ;8bit data low 4bit data LED output
call data_lcd4bitwrite ;command mode 4bit data LCD output
ret
I2Cでの書き込みは、
書き込みデータ >> Dレジスター
スレーブアドレス>> Eレジスターに設定してサブルーチンI2C_writeを呼びます。
何らかのエラーが発生した場合は、端末上で[err」と表示します。
プログラムは、最後のところで一挙にまとめていますのでそちらを参考にしてください。
プログラム全体
実際にプログラムを実行した結果は下記のようになります。
;;z180 i/o port on i2c >> i2c LCD (KKHMF 1602 LCD +EasyWordMall 1602 LCD i2c i/F))
;;
;; Z8S180 cpu
;; 0000h -- 7fffh
;; External clock 16MHz
;;
;; i2c-bus controller PCA9564
;;
;; i/o address
;; I2CSTA i/o 0x80(r)
;; I2CTO i/o 0x80(w)
;; I2CDTA i/o 0x81(r/w)
;; I2CADR i/o 0x82(r/w)
;; I2CCON i/o 0x83(r/w)
;;
;; lcd 1602 port
;;
;; D0 > RS
;; D1 > R/W
;; D2 > E
;; D3 > LED on/off
;; D4 > DB4
;; D5 > DB5
;; D6 > DB6
;; D7 > DB7
;; assembler
;; program a000H
;; data a000H
;;
;; assemblers ASxxxx and ASlink V5.10
;; file name i2c_lcd12.asm
;; $ asz80 -l -s -o i2c_lcd12.asm
;; $ aslink -i i2c_lcd12
;; $ monitor l command hex download i2c_lcd12.ihx
.z180
;; dely timing set in 100uS
D100U .equ 65 ;;clock in 16MHz set
;D100U .equ 26 ;;clock in 8MHz set
;D100U .equ 138 ;;clock in 32MHz set
CNTLA0 .equ 0x00
CCR .equ 0x1f
CMR .equ 0x1e
I2CSTA .equ 0x80 ;PCA9564 setting adress
I2CTO .equ 0x80
I2CDAT .equ 0x81
I2CADR .equ 0x82
I2CCON .equ 0x83
RS .equ 0 ;command >0 :data transfer >1
RW .equ 1 ;write >0 : read >1
EN .equ 2 ;positive pulse
LED .equ 3 ;back light off >0 : on >1
putchar .equ 0x07fe ;monitor putchar
cr .equ 0x016d ;monitor CR
ADDRES .equ 0x27 ;i2c slave address
.area TEST (ABS)
.org 0xa000
start: ;; main program
call i2c_init ;i2c init
call dely100u
call lcd_init ;LCD init
ld hl,lcd_msg ;msg output
ld b,16
main_loop:
ld a,(hl)
call data_lcd8bitwrite
inc hl
djnz main_loop
ld a,0xc0 ;0x80 + 0x40(2 line top address)
call lcd8bitwrite ; 2 line set
ld hl,lcd_msg2 ;msg output
ld b,16
main_loop2:
ld a,(hl)
call data_lcd8bitwrite
inc hl
djnz main_loop2
ret
lcd_init: ;LCD init(4bit mode)
ld a,0x03
call lcd4bitwrite
ld b,0x05 ;;5ms dely
call delym
ld a,0x03
call lcd4bitwrite
ld a,0x03
call lcd4bitwrite
ld a,0x02 ;;4 bit mode
call lcd4bitwrite
ld a,0x28 ;function set
call lcd8bitwrite ;4bit bus,2 line ,1 line=8
ld a,0x0c ;disp on,under cursor off,block cursor off
call lcd8bitwrite
ld a,0x01 ;disp clr
call lcd8bitwrite
ld b,0x02 ;;2mS dely
call delym
ld a,0x06 ;disp address incrmant on,disp shift off
call lcd8bitwrite
ld a,0x02 ;cursor home set
call lcd8bitwrite
ld b,0x02 ;;2ms dely
call delym
ret
i2c_init:
LD A,0xff ;;Timout Register
out0 (I2CTO),a
ld a,0x64 ;;Own Address
out0 (I2CADR),a
ld a,0x44 ;;Enable Serial io
out0 (I2CCON),a
call dely500u ;; 500u Wite
ld a,0xc4 ;;Slave recciver mode
out0 (I2CCON),a ;; AA=1 ENSIO=1 SI=0
ret
lcd8bitwrite: ;command mode 8bit data LCD output
push af ;
rrca ;8bit data upper 4bit data LED output
rrca
rrca
rrca
call lcd4bitwrite ;command mode 4bit data LCD output
pop af ;8bit data low 4bit data LED output
call lcd4bitwrite ;command mode 4bit data LCD output
ret
lcd4bitwrite: ;command mode 4bit data LCD output
rlca ;4bit data upper 4bit set
rlca
rlca
rlca
res RS,a ;LCD Command mode
res RW,a ;LCD Write mode
res EN,a ;LCD EN low
set LED,a ;LCD back light LED ON
push af
ld d,a ;i2c write data set
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
pop af
set EN,a ;LCD EN high
push af
ld d,a
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
pop af
res EN,a ;LCD EN low
ld d,a
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
ret
data_lcd8bitwrite: ;data mode 8bit data LCD output
push af
rrca ;8bit data upper 4bit data LED output
rrca
rrca
rrca
call data_lcd4bitwrite ;command mode 4bit data LCD output
pop af ;8bit data low 4bit data LED output
call data_lcd4bitwrite ;command mode 4bit data LCD output
ret
data_lcd4bitwrite: ;data mode 4bit data LCD output
rlca
rlca
rlca
rlca
set RS,a ;LCD RS data mode
res RW,a ;LCD write mode
res EN,a ;LCD EN low
set LED,a ;LCD back light LED ON
push af
ld d,a ;i2c write data set
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
pop af
set EN,a ;LCD EN high
push af
ld d,a ;i2c write data set
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
pop af
res EN,a ;LCD EN low
ld d,a ;i2c write data set
ld e,ADDRES ;i2c slave address set
call i2c_write ;i2c write
ret
i2c_write:
ld a,0xe4 ;;Slave recciver mode
out0 (I2CCON),a ;; AA=1 ENSIO=1 STA=1
loop1: in0 a,(I2CCON) ;; SI=1 ?
bit 3,a
jr z,loop1
in0 a,(I2CSTA) ;;Poll from transmission finished
cp 0x08
jp nz,err
in a,(I2CDAT)
ld a,e ;;Slave address set
sla a
out0 (I2CDAT),a
ld a,0xc4 ;;Slave recciver mode
out0 (I2CCON),a ;; AA=1 ENSIO=1 SI=0
loop2: in0 a,(I2CCON) ;; SI=1 ?
bit 3,a
jr z,loop2
loop3:
in0 a,(I2CSTA) ;;Poll from transmission finished
cp 0x18
jr nz,err
;; DE reg = buffer adress
;; end buffer is "00"
data_write:
ld a,d ;; write data Areg is I2CDAT
out0 (I2CDAT),a
ld a,0xc4 ;;Slave recciver mode
out0 (I2CCON),a ;; AA=1 ENSIO=1 SI=0
data_w1:
in0 a,(I2CCON) ;; SI=1 ?
bit 3,a
jr z,data_w1
data_w2:
in0 a,(I2CSTA) ;;Poll from transmission finished
cp 0x28
jr nz,err
ld a,0xD4 ;;Generate STOP mode
out0 (I2CCON),a ;; AA=1 ENSIO=1 SI=0
D_W_ST0:
in0 a,(I2CCON) ;; STO=0 ?
bit 4,a
jr nz,D_W_ST0
in a,(I2CSTA)
cp 0xf8
jr nz,err
ret
err: ;; err
call cr
ld a,"E"
call putchar
ld a,"r"
call putchar
ld a,"r"
call putchar
call cr
ret
delym: ;; B reg set *1mS dely
push bc
delyml: call dely1m
djnz delyml
pop bc
ret
dely1m: ;; 1mS dely
push bc
call dely500u
call dely500u
pop bc
ret
dely500u: ;; 500uS dely
push bc
ld b,5
dd5: call dely100u
djnz dd5
pop bc
ret
dely100u: ;; 100uS dely
push bc
ld b,D100U
l100u: djnz l100u
pop bc
ret
;; data
lcd_msg:
.db 'H
.db 'e
.db 'l
.db 'l
.db 'o
.db 0x20
.db 'Z
.db '8
.db '0
.db 0x20
.db 'W
.db 'o
.db 'r
.db 'l
.db 'd
.db '!
lcd_msg2:
.db '*
.db '*
.db '*
.db 0x20
.db 'Z
.db '8
.db '0
.db 0xc6 ;ニ
.db 0xd3 ;モ
.db 0xb4 ;エ
.db 0xc0 ;タ
.db 0xb2 ;イ
.db 0x20
.db '*
.db '*
.db '*
.end
ちゃんと表示されてほっとしましたwww
