前回までI2CでLCDやRTCの通信ができるようになりましたが、今回I2C対応EEPROMのデータ読み書きに挑戦してみました。

TMPZ84C015とI2Cとの受け渡しは、前回より使用しているPCA9564を使用します。
I2C対応EEPROMは、micrchipの24FC256(秋月電子で購入)を使用してみました。

EEPROM(24FC256)にはスレーブアドレスを変更できるA0-A2の設定端子がありますが、今回は3端子(A0-A2)ともLレベル(GND接続)にして、A0-A2=0のスレーブアドレス設定としました。
したがって、スレーブアドレスは0x50となります。

SDA,SCL端子は4.7KΩでプルアップ(他のI2Cデバイスでプルアップされていれば必要ありません。)しています。また、WP端子はGND(L)に接続し、書き込み可としています。

今回の作成したソフトはEEPROMに対して、読み書きアドレスを指定して、1バイトの読み書きを行います。

0xa000でモニターのCコマンドでコールすると、EEPROMのアドレスを聞いてくるので、4桁の16進で入力 (ここでは0x0120) します。続いて、指定したアドレスの1バイトのデータを読み込み表示(ここでは0xff)します。変更する場合続けて変更の1バイトの16進2桁を入力(ここでは0x77)します。

>c a000 y:
eeprom addr:0120 FF 77
>c a000 y:
eeprom addr:0120 77 01
>c a000 y:
eeprom addr:0120 01 ff
>c a000 y:
eeprom addr:0120 FF 

>c a000 y:
eeprom addr:0120 FF 

>

一部コードの中で、モニタのサブルーチンを読んでいるので、モニタバージョンに合わせる必要があります。(下記設定ではmonitor V0.71(SPI)となっています)

以下ソースを展開します。

        ;;TMPZ84C015 + PCA9564 on i2c >> EEPROM (microchip 24FC256) by pinecone 2019/08/23
	;;	  i2c-bus controller  PCA9564 
	;;
        ;; TMPZ84C015 cpu
        ;; rom 0000h -- 7fffh
	;; ram 8000h -- ffffh
        ;; External clock 20MHz
        ;;
        ;; 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)
        ;;
	;;
	;; i2c slave address
	;;    EEPROM i2c i/f  0x50 (A2=A1=A0:low)

        ;; assembler
        ;;  program a000H
        ;;  data    program_end +
        ;;
        ;; assemblers  ASxxxx and ASlink V5.10
        ;; file name tmpz84c015_i2c_eeprom.asm
        ;; $ asz80 -l -s -o itmpz84c015_i2c_eeprom.asm
        ;; $ aslink -i tmpz84c015_i2c_eeprom
        ;; $ monitor l command hex download tmpz84c015_i2c_eeprom.ihx

 
        .z80
 
        ;; dely timing set in 100uS
D100U   .equ    70      ;;clock in 20MHz set

 
 
I2CSTA  .equ    0x80    ;PCA9564 setting adress
I2CTO   .equ    0x80
I2CDAT  .equ    0x81
I2CADR  .equ    0x82
I2CCON  .equ    0x83

			;slave address setting
EEPROM_ADDRESS	.equ	0x50	;EEPROM i2c slave address

			;monitor V0.71(SPI) call address setting
hex_a_disp	.equ  	0x06a7
putchar		.equ  	0x06f3
cr		.equ  	0x0156
getchar		.equ	0x06ea
msgout		.equ	0x06e0
input_hl	.equ	0x0650
input_l		.equ	0x064b

; 			;monitor V0.71 call address setting
;hex_a_disp	.equ  	0x0318
;putchar	.equ  	0x0364
;cr		.equ  	0x014e
;getchar	.equ	0x035b
;msgout		.equ	0x0351
;input_hl	.equ	0x02c1
;input_l	.equ	0x02bc

        .area   TEST (ABS)
 
        .org    0xa000
start:						;; main program
 	call	i2c_init			;i2c init

main_loop:					;main

	call	eeprom_byte_read_write
	ret

eeprom_byte_read_write:
	ld	hl,eeprom_address_msg	;eeprom address message
	call	msgout
	call    input_hl   		;change eeprom memory address hl reg
        cp      0x00
        jr      z,eeprom_r01       	;no address hex code 
        ld      a,0x0d
        call    putchar
        ret	
eeprom_r01:
	ld	de,i2c_w_buff		;write buff set	de reg
	ld	a,h			;eeprom address h -> (de), l -> (dl+1)
	ld	(de),a
	inc	de
	ld	a,l
	ld	(de),a
	ld	hl,i2c_w_buff		;write buff set	hl reg
	ld	b,0x02			;2 byte write
	ld	c,EEPROM_ADDRESS	;eeprom slave address
	call	i2c_buff_write		;i2c write	
	ld	hl,i2c_r_buff		;read buff set hl reg
	ld	b,0x01			;1 byte read
	ld	c,EEPROM_ADDRESS	;eeprom slave address
	call	i2c_buff_read		;i2c read
	ld	a," "
	call	putchar
	ld	hl,i2c_r_buff
	ld	a,(hl)
	call	hex_a_disp		;eeprom read 1byte display
	ld	a," "
	call	putchar

	inc	de
	call    input_l        		;change eeprom memory address 
        cp      0x00
        jr      z,eeprom_w01       	;no address hex code 
        ld      a,0x0d
        call    putchar
        ret	
eeprom_w01:
	ld	a,l			;write data(1byte) buff set
	ld	(de),a
	ld	hl,i2c_w_buff		;write buff set	hl reg
	ld	b,0x03			;3 byte write
	ld	c,EEPROM_ADDRESS	;eeprom slave address
	call	i2c_buff_write		;i2c write
	ret

i2c_buff_read:				;;buff >> HL reg
					;;buff size >> B reg
					;;Slave Address C reg

        ld      a,0xe4                  ;;Master Receiver Mode
        out     (I2CCON),a              ;; AA=1 ENSIO=1 STA=1
i2c_br_si01:  
        in      a,(I2CCON)              ;; SI=1 ?
        bit     3,a     
        jr      z,i2c_br_si01
        in      a,(I2CSTA)              ;;Poll from transmission finished
        cp      0x08
        jp      nz,i2c_br_err
        in      a,(I2CDAT)
 
        ld      a,c                     ;read  slave address d reg 
        scf                             ;set read mode bit0=1
        RLA     
        out     (I2CDAT),a              ;set slave address
        ld      a,0xc4                  ;send data
        out     (I2CCON),a
i2c_br_si06:
        in      a,(I2CCON)
        bit     3,a                     ;SI=1 ?
        jr      z,i2c_br_si06


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

	dec	b
	jr	z,i2c_br_next_end

i2c_br_next:
        ld      a,0xc4                  ;Reset SI And AA bit
        out     (I2CCON),a              ;AA=0 ENSIO=1 STA=0 STO=0
i2c_br_si07:
        in      a,(I2CCON)
        bit     3,a                     ;SI=1 ?
        jr      z,i2c_br_si07

                                
        in      a,(I2CSTA)              ;Data has been received
        cp      0x50                    ;data-ACK has been returned
        jr      nz,i2c_br_err

        in      a,(I2CDAT)              ;Received Data read a reg
        ld      (HL),a
	inc	hl
	djnz	i2c_br_next

i2c_br_next_end:
       	ld      a,0x44                  ;Reset SI And AA bit
        out     (I2CCON),a              ;AA=0 ENSIO=1 STA=0 STO=0
i2c_br_si08:
        in      a,(I2CCON)
        bit     3,a                     ;SI=1 ?
        jr      z,i2c_br_si08
                                
        in      a,(I2CSTA)              ;Data has been received
        cp      0x58                   ;data-ACK has been returned
        jr      nz,i2c_br_err

        in      a,(I2CDAT)              ;Received Data read a reg
        ld      (HL),a

        ld      a,0xd4                  ;Generate STOP command
        out     (I2CCON),a              ;AA=1 ENSIO=1 STA=0 STO=1

i2c_br_stop_loop:
        in      a,(I2CCON)
        bit     4,a                     ;STO=0 ?
        jr      nz,i2c_br_stop_loop
        in      a,(I2CSTA)
        cp      0xf8                    ;reset or STOP command
        jr      nz,i2c_br_err
        xor     a
        ret
;
i2c_br_err:
        ld      a,0xff
        ret


err:	
	call	hex_a_disp					;; err 
	call	cr
	ld	a,"E"
	call	putchar
	ld	a,"r"
	call	putchar
	ld	a,"r"
	call	putchar
	call	cr
	ret

i2c_buff_write:				;;write buff data >> HL reg
					;;write buff size >> B reg
					;;slave address >> C reg

        ld      a,0xe4                  ;;Slave recciver mode
        out     (I2CCON),a              ;; AA=1 ENSIO=1 STA=1
i2c_bw_loop1:
  	in      a,(I2CCON)              ;; SI=1 ?
        bit     3,a    
        jr      z,i2c_bw_loop1
        in      a,(I2CSTA)              ;;Poll from transmission finished
        cp      0x08
        jp      nz,err
	in 	a,(I2CDAT)
	ld	a,c			;;Slave address set
	sla	a
        out     (I2CDAT),a
        ld      a,0xc4                  ;;Slave recciver mode
        out     (I2CCON),a              ;; AA=1 ENSIO=1 SI=0
i2c_bw_loop2:  
	in      a,(I2CCON)              ;; SI=1 ?
        bit     3,a
        jr      z,i2c_bw_loop2

        in      a,(I2CSTA)              ;;Poll from transmission finished
	cp	0x20			;;Write data N-ACK
	jr	z,data_bw_stop		;;go to Stop mode
        cp      0x18
        jr      nz,err
                                        ;; HL reg = buffer adress
i2c_bw_next:                                        ;; end buffer is "00
        ld	a,(hl)                  ;; write data Areg is I2CDAT
        out     (I2CDAT),a
	ld      a,0xc4                  ;;Slave recciver mode
        out     (I2CCON),a              ;; AA=1 ENSIO=1 SI=0
i2c_bw_loop3:
        in      a,(I2CCON)              ;; SI=1 ?
        bit     3,a
        jr      z,i2c_bw_loop3

        in      a,(I2CSTA)              ;;Poll from transmission finished
        cp      0x28
        jr      nz,err

	inc	hl
	djnz	i2c_bw_next

data_bw_stop:        
	ld      a,0xD4                  ;;Generate STOP mode
        out     (I2CCON),a              ;; AA=1 ENSIO=1 SI=0
D_bW_ST0:
        in      a,(I2CCON)              ;; STO=0 ?
        bit     4,a
        jr      nz,D_bW_ST0
	in	   a,(I2CSTA)
	cp	   0xf8
	jr	   nz,err
        ret

i2c_init:
        LD      A,0xff                  ;;Timout Register
        out     (I2CTO),a
        ld      a,0x64                  ;;Own Address
        out     (I2CADR),a
        ld      a,0x44                  ;;Enable Serial io
        out     (I2CCON),a
        call    dely500u                ;; 500u Wite
 ;       ld      a,0xc4                  ;;Slave recciver mode
 ;       out     (I2CCON),a              ;; AA=1 ENSIO=1 SI=0
	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


eeprom_address_msg:
	.str	"eeprom addr:"
	.db	0x00


 
	.org	0xff00
i2c_r_buff:
	.ds	0x03
i2c_w_buff:
	.ds	0x03
    .end
おすすめの記事