前回で、無事LCDでの表示ができましたので、RTCから時刻を読み込んで表示させたいと思います。

ハードはすでに出来上がってるので、I2CにRTCとLCDをつなぐことで完成です(並列接続)。

ソフト面では、RTCとLCD表示の重複部分を取り去り、RTCからの読み取りデータを端末への表示からLCDへの表示に切り替えます。

メインプログラムでは、まず、I2Cの初期化、続いて、LCDの初期を行っています。
メインループの中で、時刻を呼び出し表示を、200msごとに繰り返します。

.org    0xa000
start:                                  ;; main program
call    i2c_init                ;i2c init
call    dely100u
call    lcd_init                ;LCD init

main_loop:
call    time_disp
ld      b,200                   ;200ms dely
call    delym
jr      main_loop

時刻の呼び出しでは、RTCの情報をいったんバッファーに呼び出し記憶させます。
このバッファから、表示に必要な、 月/日/時/分/秒を抜き出し,LCDに表示させます。
年は16文字に収めることができなかったので、今回は割愛してます^^;

バッファーに読み込んだ後、LCDでの1行目の先頭を指定しています。
1文字書き込みの都度、表示位置は右に移動していきますので、端末に表示する動作と同じになります。
実際の1文字表示は、data_lcd8bitwriteを呼び出ししています。

time_disp:
ld      d,0x51                  ;i2c slave address set d reg
ld      b,0x00
ld      hl,rtc_buff             ;i2c receive data in buff set
loop:                                   ;rtc 8564 read register 0x00 to 0x0f
ld      e,b                     ;i2c slave register set e reg
call    i2c_read                ;i2c slave receive call
cp      0xff                    ;a reg 0xff receive err
jr      z,i2c_err_disp
ld      (hl),e                  ;i2c slave data in e reg
inc     hl
inc     b
ld      a,b
cp      0x10                    ;end rtc 8564 register
jr      nz,loop

call    lcd_1line_set

ld      a," "
call    data_lcd8bitwrite       ;LCD putchar up data
;        ld      a,0x20                  ;Years 20 set
;        call    bcd2
;        ld      a,(rtc_buff+0x08)       ;Years ?? i2c read data set
;        call    bcd2
;        ld      a,"/"
;       call    data_lcd8bitwrite       ;LCD putchar up data
ld      a,(rtc_buff+0x07)       ;Months ?? i2c read data set
and     0x1f
call    bcd2
ld      a,"/"
call    data_lcd8bitwrite       ;LCD putchar up data
ld      a,(rtc_buff+0x05)       ;Days ?? i2c read data set
and     0x3f
call    bcd2
ld      a," "
call    data_lcd8bitwrite       ;LCD putchar up data
ld      a,(rtc_buff+0x04)       ;Hours  ?? i2c  read data set
and     0x3f
call    bcd2
ld      a,":"
call    data_lcd8bitwrite       ;LCD putchar up data
ld      a,(rtc_buff+0x03)       ;Minutes ?? i2c read data set
and     0x7f
call    bcd2
ld      a,":"
call    data_lcd8bitwrite       ;LCD putchar up data
ld      a,(rtc_buff+0x02)       ;Seconds ?? i2c read data set
and     0x7f
call    bcd2
call    cr
ret

サブルーチンbcd2の中でも表示を端末表示から、LCD表示に変更します。

bcd2:                                   ;bcd to putchar
push    af                      ; up bcd (7:4)
rlca
rlca
rlca
rlca
and     0x0f
or      0x30
call    data_lcd8bitwrite       ;LCD putchar up data
pop     af
and     0x0f                    ;down data (3:0)
or      0x30
call    data_lcd8bitwrite       ;LCD putchar down data
ret

LCDの表示行の指定は1行目は 0x80を 2行目は 0xc0を指定することで行っています。

lcd_1line_set:                          ;a reg:output char
ld      a,0x80                          ;0x80 + 0x00(1 line top address)
call    lcd8bitwrite                    ; 1 line set
ret
lcd_2line_set:
ld      a,0xc0                          ;0x80 + 0x40(2 line top address)
call    lcd8bitwrite                    ; 2 line set
ret

全体のプログラムは次のようになります。

;;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_lcd_time01.asm
;; $ asz80 -l -s -o i2c_lcd_time01.asm
;; $ aslink -i i2c_lcd_time01
;; $ monitor l command hex download i2c_lcd_time01.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

ADDRES  .equ    0x27    ;lcd_i2c slave address

disp_a_hex      .equ    0x07b1
putchar         .equ    0x07fe
cr              .equ    0x016d

.area   TEST (ABS)

.org    0xa000
start:                                  ;; main program
call    i2c_init                ;i2c init
call    dely100u
call    lcd_init                ;LCD init

main_loop:
call    time_disp
ld      b,200                   ;200ms dely
call    delym
jr      main_loop

time_disp:
ld      d,0x51                  ;i2c slave address set d reg
ld      b,0x00
ld      hl,rtc_buff             ;i2c receive data in buff set
loop:                                   ;rtc 8564 read register 0x00 to 0x0f
ld      e,b                     ;i2c slave register set e reg
call    i2c_read                ;i2c slave receive call
cp      0xff                    ;a reg 0xff receive err
jr      z,i2c_err_disp
ld      (hl),e                  ;i2c slave data in e reg
inc     hl
inc     b
ld      a,b
cp      0x10                    ;end rtc 8564 register
jr      nz,loop

call    lcd_1line_set

ld      a," "
call    data_lcd8bitwrite       ;LCD putchar up data
;        ld      a,0x20                  ;Years 20 set
;        call    bcd2
;        ld      a,(rtc_buff+0x08)       ;Years ?? i2c read data set
;        call    bcd2
;        ld      a,"/"
;       call    data_lcd8bitwrite       ;LCD putchar up data
ld      a,(rtc_buff+0x07)       ;Months ?? i2c read data set
and     0x1f
call    bcd2
ld      a,"/"
call    data_lcd8bitwrite       ;LCD putchar up data
ld      a,(rtc_buff+0x05)       ;Days ?? i2c read data set
and     0x3f
call    bcd2
ld      a," "
call    data_lcd8bitwrite       ;LCD putchar up data
ld      a,(rtc_buff+0x04)       ;Hours  ?? i2c  read data set
and     0x3f
call    bcd2
ld      a,":"
call    data_lcd8bitwrite       ;LCD putchar up data
ld      a,(rtc_buff+0x03)       ;Minutes ?? i2c read data set
and     0x7f
call    bcd2
ld      a,":"
call    data_lcd8bitwrite       ;LCD putchar up data
ld      a,(rtc_buff+0x02)       ;Seconds ?? i2c read data set
and     0x7f
call    bcd2
;       call    cr
ret

i2c_err_disp:                           ;i2c err disp
call    cr
ld      a,"e"
call    putchar
ld      a,"r"
call    putchar
ld      a,"r"
call    putchar
call    cr
ret
bcd2:                                   ;bcd to putchar
push    af                      ; up bcd (7:4)
rlca
rlca
rlca
rlca
and     0x0f
or      0x30
call    data_lcd8bitwrite       ;LCD putchar up data
pop     af
and     0x0f                    ;down data (3:0)
or      0x30
call    data_lcd8bitwrite       ;LCD putchar down data
ret

lcd_1line_set:                          ;a reg:output char
ld      a,0x80                          ;0x80 + 0x00(1 line top address)
call    lcd8bitwrite                    ; 1 line set
ret
lcd_2line_set:
ld      a,0xc0                          ;0x80 + 0x40(2 line top address)
call    lcd8bitwrite                    ; 2 line set
ret

i2c_read:
ld      a,0xe4                  ;;Master Receiver Mode
out0    (I2CCON),a              ;; AA=1 ENSIO=1 STA=1
i2c_r_si01:
in0     a,(I2CCON)              ;; SI=1 ?
bit     3,a
jr      z,i2c_r_si01
in0     a,(I2CSTA)              ;;Poll from transmission finished
cp      0x08
jp      nz,i2c_r_err
in0     a,(I2CDAT)
ld      a,d                     ;set slave addres set a reg
sla     a                       ;carry flag set at write mode
;slave address + write
out0    (I2CDAT),a              ;sleve address set
ld      a,0xc4                  ;;Slave recciver mode
out0    (I2CCON),a              ;; AA=1 ENSIO=1 SI=0

i2c_r_si02:
in0     a,(I2CCON)              ;; SI=1 ?
bit     3,a
jr      z,i2c_r_si02

in0     a,(I2CSTA)              ;;Address+W has been trasimited
cp      0x18                    ;;ACK has been received
jr      nz,i2c_r_err

ld      a,e                     ;;read slave register set
out0    (I2CDAT),a
ld      a,0xc4                  ;;Slave recciver mode
out0    (I2CCON),a              ;; AA=1 ENSIO=1 SI=0
i2c_r_si04:
in0     a,(I2CCON)              ;; SI=1 ?
bit     3,a
jr      z,i2c_r_si04

in0     a,(I2CSTA)              ;;Poll from transmission finished
cp      0x28                    ;ACK has been received
jr      nz,i2c_r_err

ld      a,0xe4                  ;not stop signal is startting
out0    (I2CCON),a              ; AA=1 ENSIO=1 STA=1 STO=0
i2c_r_si05:
in0     a,(I2CCON)              ;SI=1 ?
bit     3,a
jr      z,i2c_r_si05
ld      a,d                     ;read  slave address d reg
scf                             ;set read mode bit0=1
RLA
out0    (I2CDAT),a              ;set slave address
ld      a,0xc4                  ;send data
out0    (I2CCON),a
i2c_r_si06:
in0     a,(I2CCON)
bit     3,a                     ;SI=1 ?
jr      z,i2c_r_si06

in0     a,(I2CSTA)              ;Address+R has been transmitted
cp      0x40                    ;ACK has been received
jr      nz,i2c_r_err

ld      a,0x44                  ;Reset SI And AA bit
out0    (I2CCON),a              ;AA=0 ENSIO=1 STA=0 STO=0
i2c_r_si07:
in0     a,(I2CCON)
bit     3,a                     ;SI=1 ?
jr      z,i2c_r_si07

in0     a,(I2CSTA)              ;Data has been received
cp      0x58                    ;NACK has been returned
jr      nz,i2c_r_err

in0     a,(I2CDAT)              ;Received Data read a reg
ld      e,a
ld      a,0xd4                  ;Generate STOP command
out     (I2CCON),a              ;AA=1 ENSIO=1 STA=0 STO=1

i2c_stop_loop:
in0     a,(I2CCON)
bit     4,a                     ;STO=0 ?
jr      nz,i2c_stop_loop
in0     a,(I2CSTA)
cp      0xf8                    ;reset or STOP command
jr      nz,i2c_r_err
xor     a
ret
;
i2c_r_err:
ld      a,0xff
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       ;data mode 4bit data LCD output
pop     af                      ;8bit data low 4bit data LED output
call    data_lcd4bitwrite       ;data 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

rtc_buff:
.ds     16

.end

実際に動作させて表示を確認して見ました。

おすすめの記事