目次
前
次
IICバスEEPROM処理
無線サークルの知人から、表面実装のEEPROMを貰いました。
変換基板に半田付けして、2個使えるようにしています。
8ピンICソケットを並べて、それらにEEPROM基板を挿入。
IICバスを操作するには、PC5、PC4を使います。
PC5、PC4をSCL、SDAとして使います。
IICバスは4ピンで、IICバスデバイスと接続できるので
次のケーブルを用意しました。
ケーブルは、色でどの信号と接続しているのか
わかるようにしています。
- Red Vcc
- Yellow SCL
- Gray SDA
- Black GND
IICバスデバイスとの接続は、以下。
IICバスを扱うライブラリは、Wire.hがあります。
インクルードは、次の記述でOK。
#include <Wire.h>
IICバスを利用するには、setup()の中に
開始を宣言するコードを入れます。
/* enable IIC bus */
Wire.begin();
IICバスは、バスに最大8デバイスを接続できます。
8デバイスを区別するために、各デバイスには
A0からA2の3ピンを用意して、IICバスから見て
何番になっているのかを、物理的に固定。
EEPROMを2個使っているので、番号0、1を
与えるため、次のように半田付けしています。
各EEPROMにアクセスするためには、2つの
パラメータが必要になります。
ID、アドレスで、EEPROMでは次のように
指定が必要。
Control Code がIDで、0x50。
Chip Select Bitsは、バス上のアドレスで0x0から0x07。
合体させた0x50、0x51が各々のEEPROMのIICバス上
のアドレスになります。
次のようにアドレスが振られます。
ハードウエアの仕様が決まりました。
EEPROMにバイトごとにデータをライトする
バイトごとにデータを読み込むを考えます。
EEPROMのアクセス方法をタイミングチャートで
確認しておきます。
ライトでは、次のシーケンスを利用することで
指定アドレスに1バイトが格納されています。
- START conditionに設定
- Control Byte 転送
- 上位アドレス転送
- 下位アドレス転送
- 1バイト転送
- STOP conditionに設定
今回使うEEPROMは、8kバイトになるので
2個使うと、16kバイトまでライト可能。
ライブラリを利用して、1バイトライトする
関数は、次のように定義できます。
void put_eeprom(word xadr,byte xdat)
{
byte adh ;
byte adl ;
byte xx ;
boolean bflag ;
/* copy */
xx = xdat ;
/* set block number */
bflag = OFF ;
if ( xadr > 0x1fff ) { bflag = ON ; }
/* separate address */
adl = xadr & 0xff ;
adh = (xadr >> 8) & 0x1f ;
/* write 1 byte */
if ( bflag ) { Wire.beginTransmission(ROM_ADRS1); }
else { Wire.beginTransmission(ROM_ADRS ); }
Wire.write(adh); /* upper address */
Wire.write(adl); /* lower address */
Wire.write(xx ); /* data */
Wire.endTransmission();
/* wait 5ms */
delay(5);
}
8kバイトごとに、EEPROMデバイスが変わるので
与えられたアドレスから、どのEEPROMデバイスに
なっているのか判定します。
Wire.beginTransmissionで、START condition設定と
Control Byte転送が実行されています。
STOP condition設定は、Wire.endTransmission()を
使ってやればOK。
リードは、次のシーケンスを利用します。
- START conditionに設定
- Control Byte 転送
- 上位アドレス転送
- 下位アドレス転送
- START conditionに設定
- Control Byte 転送
- 1バイトをEEPROMから転送
- STOP conditionに設定
リードの場合は、シーケンシャル操作ができると
データシートに書かれています。
タイミングチャートは、以下。
シーケンシャルリードを担当する関数が用意されて
いるので、これを使って1バイトをリードする関数
を定義。
byte get_eeprom(word xadr)
{
byte adh ;
byte adl ;
byte result ;
boolean bflag ;
/* default */
result = 0 ;
/* set block number */
bflag = OFF ;
if ( xadr > 0x1fff ) { bflag = ON ; }
/* separate address */
adl = xadr & 0xff ;
adh = (xadr >> 8) & 0x1f ;
/* impress address */
if ( bflag ) { Wire.beginTransmission(ROM_ADRS1); }
else { Wire.beginTransmission(ROM_ADRS) ; }
Wire.write(adh); /* upper address */
Wire.write(adl); /* lower address */
Wire.endTransmission();
/* read 1 byte */
if ( bflag ) { Wire.requestFrom(ROM_ADRS1,1); }
else { Wire.requestFrom(ROM_ADRS ,1); }
if ( Wire.available() ) { result = Wire.read() ; }
return result ;
}
1バイトのリード、ライトができるようになったので
ArduinoにEEPROMを2個接続して、端末でアクセスする
スケッチを定義します。
コマンドインタプリタを入れて、使えるコマンドを
次のように決めました。
- ? help
- F fill
- A load data
- L load data
- S system status;
- D dummy set
コマンド'?'は、使えるコマンドのリストを
表示します。
コマンド'A'、'L'は、ほぼ同じ動作をします。
EEPROM内のデータを16進2桁で表示しますが
コマンド'L'は、0xffをスキップ。
コマンド'S'は、システム領域と定めたエリアの
6バイトを16進2桁で表示。
コマンド'D'は、システム領域の6バイトにデータ
を書き込みます。
TeraTermで操作すると、次のようになります。
コマンド'?'の処理
コマンド'S'の処理
コマンド'D'の処理
コマンド'A'の処理
0xffをスキップしないで、表示しています。
コマンド'L'の処理
0xffをスキップして、表示しています。
スケッチの内容は、以下。
/*
romtstz.ino
PORTB
PB5 (output) LED
PB4 (output) --
PB3 (output) --
PB2 (output) --
PB1 (output) --
PB0 (output) --
PORTC
PC5 (output) SCL
PC4 (output) SDA
PC3 (output) --
PC2 (output) --
PC1 (output) --
PC0 (output) --
*/
#include >Wire.h>
#define OFF 0
#define ON OFF+1
#define BSIZE 256
#define ROM_ADRS 0x50
#define ROM_ADRS1 0x51
#define LED_BIT 5
#define SYS_ADRS 0x3ff8
boolean uflag ;
boolean cflag ;
/* variables */
char sbuf[16] ;
byte sindex ;
byte cmd ;
byte ydat[32];
void update_trigger();
void show_help();
void rs_putchar(char x);
void rs_puts(char *ptr);
void crlf();
void put_eeprom(word xadr,byte xdat);
byte get_eeprom(word xadr);
void loadEEPROM();
char getASC(byte x);
byte getVal(char x);
void fillEEPROM();
void showSYSYDT();
void dummySet();
void setup()
{
Serial.begin(115200);
rs_puts("Hello !");
crlf();
crlf();
show_help();
/* port value */
PORTB = 0x00 ;
PORTC = 0x00 ;
PORTD = 0x00 ;
/* port direction */
DDRB = 0xff ;
DDRC = 0xf0 ;
DDRD = 0xfe ;
/* flags */
uflag = OFF ;
cflag = OFF ;
/* enable IIC bus */
Wire.begin();
}
void loop()
{
/* command interpreter */
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help(); }
/* load data from EEPROM */
if ( cmd == 'A' ) { cflag = OFF ; loadEEPROM(); }
/* load data from EEPROM */
if ( cmd == 'L' ) { cflag = ON ; loadEEPROM(); }
/* fill data EEPROM */
if ( cmd == 'F' ) { fillEEPROM(); }
/* show system date time */
if ( cmd == 'S' ) { showSYSYDT(); }
/* dummySet */
if ( cmd == 'D' ) { dummySet(); }
/* new line */
crlf() ;
}
}
void show_help()
{
rs_puts("? help") ; crlf();
rs_puts("F fill FF") ; crlf();
rs_puts("A load data") ; crlf();
rs_puts("L load data") ; crlf();
rs_puts("S system status"); crlf();
rs_puts("D dummy set") ; crlf();
}
void rs_putchar(char x)
{
Serial.write(x);
}
void rs_puts(char *ptr)
{
while ( *ptr ) {
rs_putchar( *ptr );
ptr++;
}
}
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
void put_eeprom(word xadr,byte xdat)
{
byte adh ;
byte adl ;
byte xx ;
boolean bflag ;
/* copy */
xx = xdat ;
/* set block number */
bflag = OFF ;
if ( xadr > 0x1fff ) { bflag = ON ; }
/* separate address */
adl = xadr & 0xff ;
adh = (xadr >> 8) & 0x1f ;
/* write 1 byte */
if ( bflag ) { Wire.beginTransmission(ROM_ADRS1); }
else { Wire.beginTransmission(ROM_ADRS ); }
Wire.write(adh); /* upper address */
Wire.write(adl); /* lower address */
Wire.write(xx ); /* data */
Wire.endTransmission();
/* wait 5ms */
delay(5);
}
byte get_eeprom(word xadr)
{
byte adh ;
byte adl ;
byte result ;
boolean bflag ;
/* default */
result = 0 ;
/* set block number */
bflag = OFF ;
if ( xadr > 0x1fff ) { bflag = ON ; }
/* separate address */
adl = xadr & 0xff ;
adh = (xadr >> 8) & 0x1f ;
/* impress address */
if ( bflag ) { Wire.beginTransmission(ROM_ADRS1); }
else { Wire.beginTransmission(ROM_ADRS) ; }
Wire.write(adh); /* upper address */
Wire.write(adl); /* lower address */
Wire.endTransmission();
/* read 1 byte */
if ( bflag ) { Wire.requestFrom(ROM_ADRS1,1); }
else { Wire.requestFrom(ROM_ADRS ,1); }
if ( Wire.available() ) { result = Wire.read() ; }
return result ;
}
void loadEEPROM()
{
long i ;
byte tmp ;
char msg[2] ;
for ( i = 0 ; i < 0x4000 ; i++ ) {
tmp = get_eeprom( i ) ;
/* separate */
*(msg+0) = getASC( (tmp >> 4) & 15 ) ;
*(msg+1) = getASC( tmp & 15 ) ;
/* judge */
if ( cflag == ON && tmp == 0xff ) {
*(msg+0) = ' ' ;
*(msg+1) = ' ' ;
}
/* show */
if ( *(msg + 0) != ' ' ) {
rs_putchar( *(msg+0) ) ;
rs_putchar( *(msg+1) ) ;
rs_putchar( ' ' );
}
/* new ling */
if ( (i & 0xf) == 15 ) { crlf(); }
/* delay */
delay(1);
}
}
char getASC(byte x)
{
char result ;
/* default */
result = '0' ;
/* judge */
if ( 0 <= x && x <= 9 ) { result = x + '0' ; }
if ( x > 9 ) { result = x - 10 + 'A' ; }
return result ;
}
byte getVal(char x)
{
byte result ;
/* default */
result = 0 ;
/* judge */
if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }
return result ;
}
void fillEEPROM()
{
word i ;
byte tmp ;
tmp = 0xff ;
for ( i = 0 ; i < SYS_ADRS ; i++ ) {
put_eeprom( i , tmp ) ;
rs_putchar('.');
if ( (i % 32) == 31 ) { crlf(); }
}
}
void showSYSYDT()
{
byte msg[6];
byte i ;
byte tmp ;
char dh ;
char dl ;
/* get system date and time */
for ( i = 0 ; i < 6 ; i++ ) {
*(msg+i) = get_eeprom( SYS_ADRS + i ) ;
}
/* show date and time */
for ( i = 0 ; i < 6 ; i++ ) {
tmp = *(msg+i);
/* separate */
dl = tmp & 15 ;
tmp >>= 4 ;
dh = tmp & 15 ;
/* upper */
rs_putchar( getASC( dh ) );
/* lower */
rs_putchar( getASC( dl ) );
/* space */
rs_putchar( ' ' );
/* */
delay(1);
}
crlf();
}
void dummySet()
{
word xadr ;
byte msg[6];
byte dh ;
byte dl ;
byte j ;
byte i ;
/* get information */
j = 1 ;
for ( i = 0 ; i < 6 ; i++ ) {
/* get */
dh = getVal( *(sbuf+j) ) ;
dl = getVal( *(sbuf+j+1) ) ;
/* */
*(msg+i) = (dh << 4) + dl ;
/* update */
j += 2 ;
}
/* system area entry */
xadr = SYS_ADRS ;
/* year month day weekday hh mm */
put_eeprom( xadr , *(msg+0) ); xadr++ ;
put_eeprom( xadr , *(msg+1) ); xadr++ ;
put_eeprom( xadr , *(msg+2) ); xadr++ ;
put_eeprom( xadr , *(msg+3) ); xadr++ ;
put_eeprom( xadr , *(msg+4) ); xadr++ ;
put_eeprom( xadr , *(msg+5) );
}
/* receive interrupt */
void serialEvent()
{
char ch;
if ( Serial.available() > 0 ) {
/* get 1 character */
ch = Serial.read();
/* store */
*(sbuf+sindex) = ch ;
/* increment */
sindex++ ;
/* judge */
if ( ch == '\r' ) {
sindex = 0 ;
uflag = ON ;
}
}
}
このスケッチを叩き台にして、次の32kバイトの
EEPROM基板をアクセスするスケッチも、作成して
あります。
32kバイトをアクセスするスケッチは以下。
/*
romtstm.ino
PORTB
PB5 (output) LED
PB4 (output) --
PB3 (output) --
PB2 (output) --
PB1 (output) --
PB0 (output) --
PORTC
PC5 (output) SCL
PC4 (output) SDA
PC3 (output) --
PC2 (output) --
PC1 (output) --
PC0 (output) --
*/
#include >Wire.h>
#define OFF 0
#define ON OFF+1
#define BSIZE 256
#define ROM_ADRS 0x50
#define ROM_ADRS1 0x51
#define ROM_ADRS2 0x52
#define ROM_ADRS3 0x53
#define LED_BIT 5
boolean uflag ;
/* variables */
char sbuf[4] ;
byte sindex ;
byte cmd ;
byte bnum ;
byte ydat[32];
byte zdat[BSIZE] ;
void update_trigger();
void show_help();
void rs_putchar(char x);
void rs_puts(char *ptr);
void crlf();
void put_eeprom(word xadr,byte xdat);
void get_page_eeprom(word xadr);
void loadEEPROM();
void saveEEPROM();
void putPage();
void getBlockNumber();
void showAll();
void showBuffer();
void generateData();
char getHex(byte x);
byte getVal(char x);
void setup()
{
Serial.begin(9600);
rs_puts("Hello !");
crlf();
show_help();
/* port value */
PORTB = 0x00 ;
PORTC = 0x00 ;
PORTD = 0x00 ;
/* port direction */
DDRB = 0xff ;
DDRC = 0xf0 ;
DDRD = 0xfe ;
/* flags */
uflag = OFF ;
/* */
bnum = 0 ;
/* enable IIC bus */
Wire.begin();
}
void loop()
{
/* command interpreter */
if ( uflag == ON ) {
/* clear flag */
uflag = OFF ;
/* get command */
cmd = *(sbuf+0) ;
/* help */
if ( cmd == '?' ) { show_help(); }
/* show all area */
if ( cmd == 'A' ) { showAll(); }
/* set block */
if ( cmd == 'B' ) { getBlockNumber(); }
/* show block number */
if ( cmd == 'b' ) { rs_putchar( bnum + '0' ); crlf(); }
/* show EEPROM context */
if ( cmd == 'D' ) { showBuffer(); }
/* show EEPROM context */
if ( cmd == 'F' ) { generateData(); }
/* load data from EEPROM */
if ( cmd == 'L' ) { loadEEPROM(); }
/* test transfer */
if ( cmd == 'S' ) { saveEEPROM(); }
/* new line */
crlf() ;
}
}
void show_help()
{
rs_puts("? help") ; crlf();
rs_puts("A show whole area") ; crlf();
rs_puts("B put block number") ; crlf();
rs_puts("b get block number") ; crlf();
rs_puts("D display buffer") ; crlf();
rs_puts("F fill value") ; crlf();
rs_puts("L load 256 data") ; crlf();
rs_puts("S save 256 data") ; crlf();
}
void rs_putchar(char x)
{
Serial.write(x);
}
void rs_puts(char *ptr)
{
while ( *ptr ) {
rs_putchar( *ptr );
ptr++;
}
}
void crlf()
{
rs_putchar('\r');
rs_putchar('\n');
}
void put_eeprom(word xadr,byte xdat)
{
byte adh ;
byte adl ;
byte xx ;
/* copy */
xx = xdat ;
/* separate address */
adl = xadr & 0xff ;
adh = (xadr >> 8) & 0x1f ;
/* write 1 byte */
switch ( bnum ) {
case 1 : Wire.beginTransmission(ROM_ADRS1); break;
case 2 : Wire.beginTransmission(ROM_ADRS2); break;
case 3 : Wire.beginTransmission(ROM_ADRS3); break;
default : Wire.beginTransmission(ROM_ADRS ); break;
}
Wire.write(adh); /* upper address */
Wire.write(adl); /* lower address */
Wire.write(xx ); /* data */
Wire.endTransmission();
/* wait 5ms */
delay(5);
}
void get_page_eeprom(word xadr)
{
byte adh ;
byte adl ;
/* separate address */
adl = xadr & 0xff ;
adh = (xadr >> 8) & 0x1f ;
/* write entry address */
switch ( bnum ) {
case 1 : Wire.beginTransmission(ROM_ADRS1); break;
case 2 : Wire.beginTransmission(ROM_ADRS2); break;
case 3 : Wire.beginTransmission(ROM_ADRS3); break;
default : Wire.beginTransmission(ROM_ADRS ); break;
}
Wire.write(adh); /* upper address */
Wire.write(adl); /* lower address */
Wire.endTransmission();
/* get 32 bytes */
switch ( bnum ) {
case 1 : Wire.requestFrom(ROM_ADRS1,32); break;
case 2 : Wire.requestFrom(ROM_ADRS2,32); break;
case 3 : Wire.requestFrom(ROM_ADRS3,32); break;
default : Wire.requestFrom(ROM_ADRS ,32); break;
}
/* copy */
if ( Wire.available() ) {
for ( adl = 0 ; adl < 32 ; adl++ ) { *(ydat+adl) = Wire.read(); }
}
/* show */
for ( adl = 0 ; adl < 32 ; adl++ ) {
adh = *(ydat+adl) ;
rs_putchar( getHex( (adh >> 4) & 15 ) );
rs_putchar( getHex( adh & 15 ) );
rs_putchar(' ');
if ( (adl % 16) == 15 ) { crlf(); }
}
}
void loadEEPROM()
{
byte i ;
byte j ;
word xad ;
for ( i = 0 ; i < 8 ; i++ ) {
xad = (i << 5) ;
get_page_eeprom( xad ) ;
/* store data to buffer */
for ( j = 0 ; j < 32 ; j++ ) { *(zdat + j + xad) = *(ydat + j) ; }
}
}
void saveEEPROM()
{
word ii ;
rs_puts("Start !");
crlf();
for ( ii = 0 ; ii < BSIZE ; ii++ ) {
put_eeprom( ii , *(zdat+ii) ) ;
rs_putchar('.');
if ( (ii & 15) == 15 ) { crlf(); }
}
rs_puts("Complete !");
crlf();
}
void putPage()
{
word i ;
word xad ;
/* EEPROM contexnt */
for ( i = 0 ; i < 256 ; i++ ) {
xad = (i << 5) ;
get_page_eeprom( xad ) ;
}
}
void getBlockNumber()
{
/* get block number */
bnum = getVal( *(sbuf+1) ) ;
/* judge */
if ( bnum > 3 ) { bnum = 0 ; }
/* show block number */
rs_putchar( bnum + '0' );
/* new line */
crlf();
}
void showAll()
{
byte i;
/* show */
for ( i = 0 ; i < 4 ; i++ ) {
/* block number */
if ( i == 0 ) { rs_puts("ROM_0"); }
if ( i == 1 ) { rs_puts("ROM_1"); }
if ( i == 2 ) { rs_puts("ROM_2"); }
if ( i == 3 ) { rs_puts("ROM_3"); }
/* new line */
crlf();
/* update block number */
bnum = i ;
/* show */
putPage();
}
/* default */
bnum = 0 ;
}
void showBuffer()
{
byte tmp ;
word ii ;
char msg[2] ;
for ( ii = 0 ; ii < BSIZE ; ii++ ) {
/* get */
tmp = *(zdat+ii) ;
/* lower */
*(msg+1) = getHex( tmp & 15 );
/* upper */
*(msg+0) = getHex( (tmp >> 4) & 15 );
/* impress */
rs_putchar( *(msg+0) );
rs_putchar( *(msg+1) );
rs_putchar( ' ' );
/* new line */
if ( (ii & 15) == 15 ) { crlf(); }
}
}
void generateData()
{
byte xx ;
/* get data from receive buffer */
xx = getVal( *(sbuf+1) ) ;
xx <<= 4 ;
xx += getVal( *(sbuf+2) ) ;
/* store */
for ( word i = 0 ; i < BSIZE ; i++ ) { *(zdat+i) = xx ; }
}
char getHex(byte x)
{
char result ;
/* default */
result = '0' ;
/* judge */
if ( 0 <= x && x <= 9 ) { result = x + '0' ; }
if ( x > 9 ) { result = x - 10 + 'A' ; }
return result ;
}
byte getVal(char x)
{
byte result ;
/* default */
result = 0 ;
/* judge */
if ( '0' <= x && x <= '9' ) { result = x - '0' ; }
if ( 'A' <= x && x <= 'F' ) { result = x - 'A' + 10 ; }
if ( 'a' <= x && x <= 'f' ) { result = x - 'a' + 10 ; }
return result ;
}
/* receive interrupt */
void serialEvent()
{
char ch;
if ( Serial.available() > 0 ) {
/* get 1 character */
ch = Serial.read();
/* store */
*(sbuf+sindex) = ch ;
/* increment */
sindex++ ;
/* judge */
if ( ch == '\r' ) {
sindex = 0 ;
uflag = ON ;
}
}
}
目次
前
次