C言語(SDCC)を使用して、今回はZ80+SIO+PIO+PCA9564PWでのI2Cデバイスを使用してI2C EEPROMの読み書きを行っていきたいと思います。
使用するI2CEEPROMは、24FC1025-I/P(秋月電子)で1MbitのEEPROMとなります。
この24FC1025-I/Pのパッケージには512Kbitのチップが2個入った形になります。
1Pin(A0)および2Pin(A1)をLow(GND)にすると、i2Cアドレスが0x50と0x54になります。
(3Pin(A2)はVCC)
これまで使用してきた i2c_init.rel、i2c_addr.rel、i2c_read.rel、i2c_write.relを使用することで、EEPROMにアクセスできます。
バイトライトは次のようになります。
コントロールバイト + バイトアドレスH + バイトアドレスL + 書き込みするデータ
コントロールバイトにはI2Cアドレス+Wを指定します。
例として、バイトアドレスHには 0x20 バイトアドレスLには 0x00 書き込みデータとして0xe5を指定しました。
バイト書き込み後は、なぜかNACKが帰ってくるので、NACK待ちをしました。
//byte write
printf("byte write \n");
uint8_t byte_in[3]; //byte write buff
uint8_t byte_out[3];
byte_in[0]= 0x02; // byte write address H
byte_in[1]= 0x00; // byte write address H
byte_in[2]= 0xe5; // byte data
printf("write address %2x%2x data=%2x \n",byte_in[0],byte_in[1],byte_in[2]);
uint16_t *byte_in_buff = byte_in;
i2c_write(eeprom1_addr,3,byte_in_buff);
while(i2c_addr(eeprom1_addr) == 0x20) //nack
{
printf("*");
}
バイトリードも同様に
コントロールバイト + バイトアドレスH + バイトアドレスL
になりますので、バイトアドレスHには 0x20 バイトアドレスLには 0x00を指定して読み込みを行います。
//byte read
printf("byte read \n");
byte_in[0]= 0x02; // byte write address H
byte_in[1]= 0x00; // byte write address H
i2c_write(eeprom1_addr,2,byte_in_buff);
uint16_t *byte_out_buff = byte_out;
i2c_read(eeprom1_addr,1,byte_out_buff);
printf("read address %2x%2x data=%2x \n",byte_in[0],byte_in[1],byte_out[0]);
ページライトは、このデバイスでは、1ページ、128ビットの連続書き込みができます。
コントロールバイト + バイトアドレスH + バイトアドレスL +
書き込みするデータn + 書き込みするデータn+1 +・・・
・・・ +書き込みするデータn+127
ここでは書き込みデータとして、 0~ 0x7fの配列データを書き込みすることにします。
一気に書き込みするので、書き込み後、NACKが帰ってくるので、NACK待ちします。
//page write
printf("page write\n");
for (i=0;i <= 128;i++){
in_buff[i+2]= i;
}
for (i=0;i <= 7;i++){
for (j=0 ;j <= 15;j++){
printf("%2x ",in_buff[i*16+j+2]);
}
printf("\n");
}
printf("\n");
in_buff[0]=0; //write address H
in_buff[1]=0; //write address L
uint16_t *buff_in = in_buff;
i2c_write(eeprom1_addr,130,buff_in);
while(i2c_addr(eeprom1_addr) == 0x20) //nack
{
printf("*");
}
ページリードは、1ページ、128ビットのデータを一気読みします。
コントロールバイト + バイトアドレスH + バイトアドレスL を指定した後、
コントロールバイト + 1ページ(128bit)読み込みとなります。
//page read
printf("\npage read \n");
uint8_t read_addr_h=0;
uint8_t read_addr_l=0;
i2c_write(eeprom1_addr,1,&read_addr_h);
i2c_write(eeprom1_addr,1,&read_addr_l);
uint16_t *buff_out = out_buff;
i2c_read(eeprom1_addr,128,buff_out);
for (i=0;i <= 7;i++){
for (j=0 ;j <= 15;j++){
printf ("%2x ",out_buff[i*16+j]);
}
printf("\n");
}
全体のプログラム
// I2C(PCA9564) eeprom (Z80+SIO+PIO)]
#include <stdio.h>
#include <stdint.h>
extern void i2c_init(void);
extern uint8_t i2c_read(uint8_t,uint8_t,uint16_t *);
extern uint8_t i2c_write(uint8_t,uint8_t,uint16_t *);
extern uint8_t i2c_addr(uint8_t);
int main(){
uint8_t eeprom1_addr=0x50; //eeprom 24FC1025
uint8_t eeprom2_addr=0x54; //eeprom 24FC1025
uint8_t in_buff[127+2]; // page write buff
uint8_t out_buff[127]; // page read buff
uint8_t i=0,j=0;
// i2c init
i2c_init();
//byte write
printf("byte write \n");
uint8_t byte_in[3]; //byte write buff
uint8_t byte_out[3];
byte_in[0]= 0x02; // byte write address H
byte_in[1]= 0x00; // byte write address H
byte_in[2]= 0xe5; // byte data
printf("write address %2x%2x data=%2x \n",byte_in[0],byte_in[1],byte_in[2]);
uint16_t *byte_in_buff = byte_in;
i2c_write(eeprom1_addr,3,byte_in_buff);
while(i2c_addr(eeprom1_addr) == 0x20) //nack
{
printf("*");
}
printf("\n");
//byte read
printf("byte read \n");
byte_in[0]= 0x02; // byte write address H
byte_in[1]= 0x00; // byte write address H
i2c_write(eeprom1_addr,2,byte_in_buff);
uint16_t *byte_out_buff = byte_out;
i2c_read(eeprom1_addr,1,byte_out_buff);
printf("read address %2x%2x data=%2x \n",byte_in[0],byte_in[1],byte_out[0]);
//page write
printf("page write\n");
for (i=0;i <= 128;i++){
in_buff[i+2]= i;
}
for (i=0;i <= 7;i++){
for (j=0 ;j <= 15;j++){
printf("%2x ",in_buff[i*16+j+2]);
}
printf("\n");
}
printf("\n");
in_buff[0]=0; //write address H
in_buff[1]=0; //write address L
uint16_t *buff_in = in_buff;
i2c_write(eeprom1_addr,130,buff_in);
while(i2c_addr(eeprom1_addr) == 0x20) //nack
{
printf("*");
}
//page read
printf("\npage read \n");
uint8_t read_addr_h=0;
uint8_t read_addr_l=0;
i2c_write(eeprom1_addr,1,&read_addr_h);
i2c_write(eeprom1_addr,1,&read_addr_l);
uint16_t *buff_out = out_buff;
i2c_read(eeprom1_addr,128,buff_out);
for (i=0;i <= 7;i++){
for (j=0 ;j <= 15;j++){
printf ("%2x ",out_buff[i*16+j]);
}
printf("\n");
}
return(0x00);
}
コンパイルします。
$ sdcc -mz80 --out-fmt-ihx --code-loc 0xa000 --no-std-crt0 -o i2c_eeprom_write_main.ihx mycrt0.rel i2c_eeprom_write_main.c i2c_init.rel i2c_addr.rel i2c_write.rel i2c_read.rel putchar.rel
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
Conflicting flags in area _CODE
Conflicting flags in area _DATA
実行します。モニタのlコマンドで i2c_eeprom_write_main.ihxを読み込みます。
>c a000 y:
byte write
write address 2 0 data=e5
********
byte read
read address 2 0 data=e5
page write
0 1 2 3 4 5 6 7 8 9 a b c d e f
10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
********
page read
0 1 2 3 4 5 6 7 8 9 a b c d e f
10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
>