最近、格安の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

おすすめの記事