NEC ELECTRONICS NEC ELECTRONICS
NEC electronics NEC electronics NEC
ホーム
アプリケーション
製品情報
先端技術
サポート
WEBショップ
ニュース&イベント
会社案内
header
GO
詳細検索機能/特性検索
サイトマップ お問い合わせ

EEPROMの制御

目次

    
FAQ-ID = EEPROM-nnnn
0001: CSIによるSPIメモリの制御(78K0/Kx2他)
0002: 78K0/Kx2のCSIによるSPI・EEPROMの制御プログラム例(78K0/Kx2)
0003: 78K0S/Kx1+によるSPI・EEPROMの制御プログラム例(78K0S/Kx1+)
0004: CSIによるマイクロワイヤ(Microwire)メモリの制御(78K0/Kx2他)
0005: 78K0/Kx2のCSIによるマイクロワイヤ・EEPROMの制御プログラム例(78K0/Kx2)
0006: 78K0S/Kx1+の汎用ポートによるマイクロワイヤ・EEPROMの制御プログラム例(78K0S/Kx1+)
EEPROM
-0001
CSIによるSPIメモリの制御(78K0/Kx2他)
[はじめに]
SPIはモトローラ社(現フリースケール・セミコンダクタ社)が提唱したマスタ/スレイブ方式のインタフェースで、基本的なデータの転送は2本のデータ(入力と出力)及びクロックの3本の信号を用いて行なうクロック同期式のシリアル通信方式です。データは8ビットの固定長でやりとりされます。基本的にこの部分は78K0シリーズ他に搭載されたシリアル・インタフェース(CSI)と互換性があります。SPIでは、これ以外にチップ・セレクトによりデバイスを選択する機能がサポートされています。

[EEPROMとの接続]
SPIインタフェースをもつEEPROMとの接続例は以下のようになります。




EEPROMに対するチップ・セレクト信号はポートを用いて出力します。その他の信号は3線式シリアルの信号をそのまま使用します。なお、EEPROMにはこれ以外にステータス・レジスタへの書き込みを禁止するためのライト・プロテクト(WP)信号や、デバイスを選択中に動作を停止させるためのホールド(HOLD)信号があるデバイスもあります。ここではこれらの信号は使用しないので電源に接続しておきます。

[ステータス・レジスタ]
EEPROMはデバイスの状態を示すためのステータス・レジスタを内蔵しています。ビットの意味は以下の通りです。詳細は実際に使用するEEPROMのマニュアル等を参照してください。

ビット0:書き込み中かどうかを示すビット。1なら書き込み中で新たなアクセスはできない。0ならアクセス可能。

ビット1:書き込み許可ビット。後述のコマンドにより操作し、1なら書き込み可能を、0なら書き込み禁止。

ビット2,3:ブロックごとの書き込み禁止ビット。個々のデバイスで異なる。00であれば、全てのデータ領域に書き込みは可能(デバイスによっては3ビット以上のものもあるようです)。

ビット7:ステータス・レジスタへの書き込み禁止ビット。このビットが1でWP端子がロウ・レベルならステータス・レジスタへの書き込みは禁止される(デバイスによってはこの機能がないものもあるようです)。


[EEPROMのコマンド]
EEPROMにはいくつかのコマンドが定義されており、最初にこれを用いて動作を指定する必要があります。コマンドの詳細は個々のデバイスのマニュアルを参照していただくとして、簡単に説明します。

コード名 称動 作
0000 0110WREN書き込み許可ビットをセットして書き込み可能にする
0000 0100WRDI書き込み許可ビットをクリアして書き込み禁止状態にする
0000 0101RDSRステータス・レジスタの読み出し
0000 0001WRSRステータス・レジスタへの書き込み
0000 x011READデータの読み出し
0000 x010WRITEデータの書き込み

WREN:電源投入時には書き込み禁止状態になっているので、書き込みを行なうにはこのコマンドを発行します。

WRDI:デバイスへの書き込みを禁止するためのコマンドです。このコマンドを発行すると、データ及びステータス・レジスタへの書き込みができなくなります。

RDSR:ステータス・レジスタの読み出しを行ないます。コマンド発行の次のクロックからステータス・レジスタの内容がMSBから順に出力します。

WRSR:ステータス・レジスタへの書き込みを行ないます。コマンド発行の次のクロックからステータス・レジスタへ書き込むデータをMSBから順に入力します。

READ:EEPROMからデータを読み出します。コマンドに続いて、1バイトまたはメモリの容量によっては2バイトのアドレスを転送する必要があります。その後の転送クロックで、指定されたアドレスの内容を出力します。CSをハイ・レベルにすることで読み出しは完了となります。コマンドのビット3はアドレスが9ビット必要な場合のアドレスとして使用できます。

WRITE:EEPROMへデータを書き込みます。コマンドに続いて、1バイトまたはメモリの容量によっては2バイトのアドレスを転送する必要があります。その後の転送クロックで、指定されたアドレスへの書き込みデータを転送します。転送が完了してCSをハイ・レベルにすることで、実際の書き込みを行ないます。実際に書き込んでいる最中には、ステータス・レジスタのビット0が1となります。このビットが0になるまではステータス・レジスタのリード以外のコマンドは発行しない方がいいでしょう。


[EEPROMの制御方法]
EEPROMへのアクセスは全てコマンドから始まります。



チップ・セレクト信号(CS)をロウ・レベルにすることで、EEPROMが選択され、最初に転送される内容がコマンドとなります。上記の6つのコマンドを用いて、EEPROMへのアクセス制御を行ないます。書き込みの場合には、アクセス制御が完了したら、CSをハイ・レベルにすることで、EEPROMはコマンドで指定された書き込みを実行します。ステータス・レジスタはいつでも読み出すことができますので、ステータス・レジスタを読み出すことで、書き込みが完了したかどうかなど、EEPROMの状態を確認できます。

[78K0/Kx2での制御モード]
EEPROMとのシリアル通信は2.7V以上の電源電圧であれば、シリアル・クロックは5MHzまでになります。そこで、78K0/Kx2を高速内蔵発振器の8MHzで動作させ、CSI10のクロックにその半分の4MHzを使用することにします。
SPIではデータとクロック(SCK)の位相の関係で4つのモードがありますが、モード0と3の2つのモードに対応したEEPROMを対象とします。この2つのモードは共に、SCKの立下りでデータを出力し、SCKの立ち上がりでデータを入力するものです。
EEPROMのアクセス・タイミング例を以下に示します。



そこで、78K0/Kx2のCSIの転送タイプ1を使用します。これは、従来の3線式シリアル(SIO)と同じです。この場合、CSICI10には00(初期値と同じ)を設定して使用します。
CSIM10はMSBファーストの送受信モードに設定して使用します。



CSI10を用いて接続する場合の接続例を示します。CSI10ではP10〜12の端子を使用するので、CS信号用に連続したP13を使用します。(ここではEEPROMを1個接続していますが、2個目を接続する場合にはP14、3個目を接続する場合にはP15をそれぞれCS信号に使用してください。)

具体的な制御プログラムについては「78K0/Kx2のCSIによるSPI・EEPROMの制御プログラム例」を参照してください。

(2006/08)

この情報はお役にたちましたか?
back to top  
(2006/08)

EEPROM
-0002
78K0/Kx2のCSIによるSPI・EEPROMの制御プログラム例(78K0/Kx2)
[はじめに]
SPIの概要やSPIインタフェースのEEPROMについては「CSIによるSPIメモリの制御」を参照してください。ここでは下記の接続例に示したEEPROMを2個接続した場合に対応した具体的な制御プログラムについて説明します。また、制御プログラムの使い方についても簡単に触れておきます。



[78K0/Kx2の処理例]
78K0/Kx2でのEEPROMの制御処理は以下の部分で構成します。内部で使用するサブルーチン以外はC言語からの使用を意識して、名前と入出力パラメータ(引数と戻り値)を決めています。例えば引数として、読み出しや書き込みでは以下のパラメータを用います。
第1パラメータ(AX渡し):EEPROMのアドレス
第2パラメータ(スタック渡し):バッファ・メモリのアドレス
第3パラメータ(スタック渡し):転送データ数で1〜255及び0(256バイト)

(1)初期化部
ポート、CSI10、割り込みの初期化を行ないます。ここでは2.7VPOCを使用することで、リセット解除後にはそのまま動作させます。基本的にベクタ割り込みは使用しないので、割り込みは禁止状態とします。

(2)EEPROM選択処理
P13〜17をCSに使用することで、最大5つの中から一つを選択します。この処理では、単に作業領域に対象とするEEPROMの番号(Xレジスタ渡しで、1〜5の値)からCS信号に対応したビット・パターンをセットするのみで、その値をCS信号の制御で用いるだけです。

(3)CS信号出力処理
EEPROMへの実際のアクセス時にCS信号をONにしたり(ロウ・レベルにする)、OFF(ハイ・レベルにする)したりするための内部処理ルーチンです。P1の内容を読み出して、CS信号に該当するビットを反転させてP1に書き戻しています。

(4)ステータスの確認
EEPROMがデータ書き込み中かどうかをチェックします。内部でEEPROMへの書き込みやデータの読み出しを行なう前に使用します。

(5)書き込み許可
対象のEEPROMのCS信号をONにして、「WREN」コマンドを送ります。コマンド転送完了後CS信号をOFFにします。このコマンドによりEEPROMは書き込み可能状態になります。

(6)書き込み禁止
対象のEEPROMのCS信号をONにして、「WRDI」コマンドを送ります。コマンド転送完了後CS信号をOFFにします。このコマンドによりEEPROMは書き込み禁止状態になります。

(7)ステータス・レジスタの読み出し
対象のEEPROMのCS信号をONにして、「RDSR」コマンドを送り、ステータス・レジスタの状態を1バイトのデータで読み出します。読み出し完了後、CS信号をOFFにします。ステータス・レジスタのビットの意味は[ステータス・レジスタ]を参照してください。

(8)ステータス・レジスタへの書き込み
対象のEEPROMのCS信号をONにして、「WRSR」コマンドを送り、引き続いてステータス・レジスタにセットする1バイトのデータを書き込みます。書き込みデータの転送完了後CS信号をOFFにします。
通常はブロック毎のプロテクトの制御(ビット2,3)に使用します。

(9)データの読み出し1
512バイト以下の(従って、アドレスは1バイトでA8はコマンドで指定)容量のEEPROMから256バイト以下のデータを読み出します。EEPROMのステータスを確認し、書き込み中でなければ、指定されたパラメータでの読み出しを行ないます。

(10)データの読み出し2
1Kバイト以上の(ただし、アドレスは2バイト)容量のEEPROMから256バイト以下のデータを読み出します。EEPROMのステータスを確認し、書き込み中でなければ、指定されたパラメータでの読み出しを行ないます。

(11)データの書き込み1
512バイト以下の(従って、アドレスは1バイトでA8はコマンドで指定)容量のEEPROMに256バイト以下のデータを書き込みます。EEPROMのステータスを確認し、書き込み中でなければ、書き込み許可コマンドを発行し、指定されたパラメータでの書き込みを行ないます。
EEPROMへのデータ転送だけしか行なわないので、実際にEEPROMで書き込みが完了するまでは別の処理を並行して行なうことができます。なお、この間のEEPROMへのアクセスは、ステータス・レジスタの読み出し以外は行なわないようにしてください。

(12)データの書き込み2
1Kバイト以上の(ただし、アドレスは2バイト)容量のEEPROMに256バイト以下のデータを書き込みます。EEPROMのステータスを確認し、書き込み中でなければ、書き込み許可コマンドを発行し、指定されたパラメータでの書き込みを行ないます。
アドレス長が異なる以外は「データ書き込み1」と同じです。

(13)書き込み完了待ち
データ書き込み後に、実際にEEPROMでのデータ書き込み完了を待ちます。データ書き込みを行なった後はこの処理を実行するか、ステータス・レジスタを読み出して、ビット0が0になった(書き込みが完了した)ことを確認してください。

(14)バイト転送完了待ち
1バイトのデータ転送が完了したかを割り込み要求フラグをポーリングすることで待ち合わせます。転送が完了して、割り込み要求フラグがセットされたことを確認したら、フラグをクリアして戻ります。これは内部処理だけで使用します。

[アセンブラでのプログラム例]
このプログラム例では他のプログラムからこのプログラムの処理を使えるように、以下の10個のサブルーチンをパブリック宣言しています。これらは、アセンブラから使う場合やC言語のプログラムから使う場合も考慮しています。アセンブラから使用する場合には大文字の名前をEXTRN宣言してください。C言語のプログラムから使う場合には_で始まる名前をextern宣言(例えば、extern _selprom のように_を一つにして宣言)してください。
	PUBLIC	__selprom,SELPROM	; アクセスするEEPROMを選択
	PUBLIC	__writeenb,WRITEENB	; 書き込み許可にする
	PUBLIC	__writedis,WRITEDIS	; 書き込み禁止にする
	PUBLIC	__readst,READST		; ステータス・レジスタのリード
	PUBLIC	__writest,WRITEST	; ステータス・レジスタへのライト
;
	PUBLIC	__read_spi_block1,READBLOCK1
		; 512バイト以下のEEPROMからのデータ・リード
	PUBLIC	__read_spi_block2,READBLOCK2
		; 1Kバイト以上のEEPROMからのデータ・リード
	PUBLIC	__write_spi_block1,WRITEBLOCK1
		; 512バイト以下のEEPROMへのデータ・ライト
	PUBLIC	__write_spi_block2,WRITEBLOCK2
		; 1Kバイト以上のEEPROMへのデータ・ライト
;
	PUBLIC	__waitwt,WAITWT		; 書き込み完了待ち
また、内部で使用する作業領域の宣言や値の定義を前もって行なっています。
;
;	使用EEPROM数の定義
;
;	EEPROMは5個を最大としてP13から順にP17を
;	CS信号に割り当てるものとします。
;	ポートの有効利用のために使用する最大数を定義します。
;	接続するEEPROMの個数に合わせてROMNOの値を変更。
;
ROMNO	EQU	2		; ここでは2個としておく

;
;	EEPROMのコマンド
;
WRENC	EQU	00000110b	; 書き込み許可
WRDIC	EQU	00000100b	; 書き込み禁止
RDSRC	EQU	00000101b	; ステータス・レジスタのリード
WRSRC	EQU	00000001b	; ステータス・レジスタへの書き込み
READC	EQU	00000011b	; データ読み出し
WRITEC	EQU	00000010b	; データ書き込み

WDATA	DSEG    SADDR
CSFLAG:
	DS	1		; CS信号用データ

RxCOUNT:
	DS	1		; 受信データ用カウンタ

TxCOUNT:
	DS	1		; 送信データ用カウンタ
(1)初期化部
ポートやCSI10の動作モードを設定します。ここではベクタ割り込みを使用しないので、割り込みはマスクしておきます。
;
;       ポートやCSI10のイニシャライズ
;
        MOV     P1,#11111011b           ; 出力ラッチの設定
        MOV     PM1,#00000010b          ; SI10/P11以外は出力に
        MOV     CSIC10,#00000000b       ; 初期値と同じ
;                       |||||+++--------: シリアルクロックはfPRS/2
;                       |||++-----------: タイプ1
;                       +++-------------: 0に固定
        MOV     CSIM10,#01000000b       ; MSBファースト、送受信モード
;                       ||+|++++--------; 0に固定
;                       || +------------; MSBファースト
;                       |+--------------; 送受信モード
;                       +---------------; 動作禁止
;
        MOV     PCC,#0
        SET1    CSIMK10                 ; CSI10の割り込みマスク
        CLR1    CSIIF10                 ; 割り込み要求フラグのクリア
        SET1    CSIE10                  ; CSI10の動作許可
(2)EEPROM選択処理
Xレジスタで指定(1〜ROMNO)されたEEPROMに対応したCS信号のビット位置パターンを作成します。接続しているEEPROMの数をROMNOで定義しておくことで、それ以上が指定された場合にはエラーを戻します(なお、0はチェックしていません。)
最初にこのルーチンでEEPROMを選択することで、以降の処理でEEPROMの番号指定を省略します。EEPROMが1個のみの場合にはこの処理はなくても構いません。
(以降のプログラム例では外部から使用するサブルーチンはアセンブラで使用する場合(内部使用)に加えてC言語から使用する場合用に名前を2つ定義しています。)
;
;	EEPROMの選択
; <機能>
; 引数で指定されたEEPROMをアクセス対象に設定します。
;ここではCS用のビットイメージを抽出して作業領域に保存します。
;実際のCS信号出力はCSOUTサブルーチンで行ないます。
;
; <入力パラメータ(引数)> 
; X	:選択するROMの番号(1〜ROMNO)を引数とする
; <戻り値>
; CF	:エラーならキャリー・フラグをセットして戻る
;bit	_ selprom(unsigned char spi_adr)

__selprom:
SELPROM:
	MOV	A,#ROMNO	; 選択する番号を最大数と比較して、
	CMP	A,X		; 大きければキャリー・フラグをセット
	BC	$EXITS		; して処理を終了する。
	MOV	A,#00000100B	; CS信号ビットへの変換
SELLOOP:
	ROL	A,1		; CS信号を上位ビットへシフト
	DEC	X		; ROM番号を−1
	BNZ	$SELLOOP	; 目的のビット位置まで繰り返す
	MOV	CSFLAG,A	; CSフラグに結果を格納

EXITS:
	RET
(3)CS信号出力処理
EEPROMへのCS信号のON/OFF処理を行なうプログラムです。ここで、上記のEEPROM選択処理の結果のビット・パターンを使用して、P1を制御して、実際にCS信号の制御を行ないます。実際の処理はP1のビットの反転処理ですので、必ず初期状態が決まっている必要があります。
EEPROMが1個の場合には、P1を直接ビット操作した方が簡単です。
;
;	CS信号の出力
; <機能>
; 前もって作業領域に設定した内容に基づきCS信号出力の状態を
;反転します。
;
; <入力パラメータ(引数)> なし
; <戻り値> なし
;
CSOUT:
	MOV	A,P1		; ポートの状態をリード
	XOR	A,CSFLAG	; CSビットを反転
	MOV	P1,A		; ポートから出力
	RET
(4)ステータスの確認
EEPROMのステータス・レジスタを読み出すことで、書き込み動作中かをチェックします。EEPROMへのデータ転送開始時にEEPROMのステータス確認のために内部で使用します。
;
;	EEPROMが書き込み処理中かのチェック
;
; <機能>
; EEPROMのステータス・レジスタを確認し、書き込み処理中
;ならばキャリ・フラグをセットして戻る
;
; <入力パラメータ(引数)> なし
; <戻り値>
; CF	: 0 : 書き込み中ではない/ 1 : 書き込み中
;

CHKRDY:
	PUSH	BC		; レジスタをセーブ
	CALL	!READST		; ステータス・レジスタのチェック
	MOV	A,C
	POP	BC
	ROR	A,1		; 書き込み中フラグをキャリへ
	RET
(5)書き込み許可
対象のEEPROMに「WREN」コマンドを転送します。
;	書き込み許可コマンド発行
; <機能>
; 指定されているEEPROMを書き込み許可に設定します。
;
; <入力パラメータ(引数)> なし
; <戻り値> なし
;void	_writeenb(void)

__writeenb:
WRITEENB:
	CALL	!CSOUT		; 対象のEEPROMを選択
	MOV	SOTB10,#WRENC	; コマンドをセット

WRITEENBLOOP:			; 転送完了割り込みを待つ
	CALL	!CSIRDY		; コマンド転送完了待ち
				; コマンド完了でCSを解除
	BR	$CSOUT		; EEPROMの選択解除
(6)書き込み禁止
対象のEEPROMに「WRDI」コマンドを転送します。
;
;	書き込み禁止コマンド発行
; <機能>
; 指定されているEEPROMを書き込み禁止に設定します。
;
; <入力パラメータ(引数)> なし
; <戻り値> なし
;void	_writedis(void)

__writedis:
WRITEDIS:
	CALL	!CSOUT		; 対象のEEPROMを選択
	MOV	SOTB10,#WRDIC	; コマンドをセット
	BR	$WRITEENBLOOP	; 完了待ち処理へ
(7) ステータス・レジスタの読み出し
対象のEEPROMに「RDSR」コマンドを転送し、EEPROMからのステータス・レジスタの内容を受け取ります。
;
;	ステータス・レジスタのリード・コマンド
; <機能>
; 指定されているEEPROMのステータス・レジスタを読み出します。
;
; <入力パラメータ(引数)> なし
; <戻り値>
; C	: 戻り値として、読み出したステータスが入ります
;
;unsigned char _readst(void)

__readst:
READST:
	CALL	!CSOUT		; 対象のEEPROMを選択
	MOV	SOTB10,#RDSRC	; コマンドをセット
	CALL	!CSIRDY		; コマンド転送完了待ち
	MOV	SOTB10,#0FFH	; 受信起動用にダミー書き込み
	CALL	!CSIRDY		; ステータス転送完了待ち
	MOV	A,SIO10		; 受信データを読み出す
	MOV	C,A		; 戻り値をセット
	BR	$CSOUT		; CSを解除
(8) ステータス・レジスタへの書き込み
対象のEEPROMに「WRSR」コマンドを送り、引き続いてステータス・レジスタに設定する値を転送します。
;
;	ステータス・レジスタへの書き込みコマンド
; <機能>
; 引数で渡された値を、指定されているEEPROMのステータス・
;レジスタに書き込みます。
;
; <入力パラメータ(引数)>
; X	: 引数として書き込み値が入る
; <戻り値> なし
;void _writest(unsigned char st)

__writest:
WRITEST:
;	CALL	!WRITEENB	; 書き込み許可(一度設定すれば個別設定は不要)
	CALL	!CSOUT		; 対象のEEPROMを選択
	MOV	SOTB10,#WRSRC	; コマンドをセット
	CALL	!CSIRDY		; コマンド転送完了待ち
	MOV	A,X
	MOV	SOTB10,A	; ステータスの送信
	CALL	!CSIRDY		; ステータス転送完了待ち
	BR	$CSOUT		; CSを解除
(9)データの読み出し1
512バイト以下の容量のEEPROMから256バイト以下のデータを読み出します。
EEPROMが書き込み中でなければ、指定されたパラメータでの書き込みを行ないます。この際、指定されたEEPROMのアドレスが256番地より大きい場合にはリードコマンドのビット3をセットします。コマンドに引き続いて、アドレスを1バイト転送し、以降はEEPROMからのデータを読み出します。データの読み出しでは、ダミー・データとしてFFを書き込んで転送を起動します。読み出しが完了したら、CS信号をOFFにすることで、EEPROMに読み出しの完了を通知します。
;
;	データの読み出し1
;
; <機能>
; 512バイト以下の容量のEEPROMに対して、引数として渡された
;パラメータで読み出しを行ないます。
; EEPROMが書き込み動作中でなければ指定された読み出しを実行し
;キャリー・フラグをクリアして戻ります。
; EEPROMが書き込み動作中なら、読み出しは行なわず、キャリー・
;フラグをセットして戻ります。
;
; <入力パラメータ(引数)>
; AX	: 第1の引数 :EEPROM内のアドレス
; SP+2,3: 第2の引数 :バッファ・メモリのアドレス
; SP+4  : 第3の引数 :読み出しデータ数
;
; <戻り値>
; CF	: 0 : 正常終了/ 1 : 書き込み動作中で処理中止
;
;bit _read_spi_block1(int reg_adr, unsigned char *data, unsigned char size)

__read_spi_block1:
READBLOCK1:
	PUSH	HL
	PUSH	AX
	CALL	!CHKRDY		; 書き込み中でないかチェック
	BC	$BUSYEXIT	; 書き込み中なら処理を中止
	MOVW	AX,SP		; 2つ目以降の引数を取り出す準備
	MOVW	HL,AX		; ポインタをHLレジスタに設定
	CALL	!CSOUT		; CS信号を出力
	MOV	A,[HL+1]	; EEPROMのアドレス上位を読み出す
	AND	A,#1		; 256バイト以上かのチェック
	ROL	A,1
	ROL	A,1
	ROL	A,1		; A8をビット3に移動
	OR	A,#READC	; リードコマンドを生成する
	MOV	SOTB10,A	; コマンドを送信
	CALL	!CSIRDY		; コマンド転送完了待ち
READBLOCK:
	MOV	A,[HL]		; アドレス下位を取り出す
	MOV	SOTB10,A	; アドレスを送信
	MOV	A,[HL+8]	; 転送データ数を取り出す
	MOV	RxCOUNT,A	; データ数を作業領域にコピー
	MOV	A,[HL+6]	; バッファ・アドレス下位を取り出す
	MOV	X,A
	MOV	A,[HL+7]	; 上位アドレスを取り出す。
	MOVW	HL,AX		; HLレジスタにアドレスを設定
	CALL	!CSIRDY		; アドレス転送完了待ち(不要)
;
;	データ受信処理
;
READLOOP:
	MOV	SOTB10,#0FFH	; 受信用ダミー・データ書き込み
	CALL	!CSIRDY		; 受信完了待ち
	MOV	A,SIO10		; 受信データの読み出し
	MOV	[HL],A		; 受信データをバッファへ
	INCW	HL		; ポインタを更新
	DEC	RxCOUNT		; 残りデータ数カウント
	BNZ	$READLOOP	; データ数分繰り返す。
	CALL	!CSOUT		; CS信号をきる
	CLR1	CY		; エラー・フラグをクリア

BUSYEXIT:			; レジスタを復帰して戻る
	POP	AX
	POP	HL
	RET
(10)データの読み出し2
1Kバイト以上の容量のEEPROMから256バイト以下のデータを読み出します。
EEPROMが書き込み中でなければ、指定されたパラメータでの書き込みを行ないます。この際、リードコマンドに引き続いて、アドレスを上位から順に2バイト転送し、以降はEEPROMからのデータを読み出します(以降はデータ読み出し1と共通なので、プログラムも共通化)。
;
;	データの読み出し2
;
; <機能>
; 1kバイト以上の容量のEEPROMに対して、引数として渡された
;パラメータで読み出しを行ないます。
; EEPROMが書き込み動作中でなければ指定された読み出しを実行し
;キャリー・フラグをクリアして戻ります。
; EEPROMが書き込み動作中なら、読み出しは行なわず、キャリー・
;フラグをセットして戻ります。
;
; <入力パラメータ(引数)>
; AX	: 第1の引数 :EEPROM内のアドレス
; SP+2,3: 第2の引数 :バッファ・メモリのアドレス
; SP+4  : 第3の引数 :読み出しデータ数
;
; <戻り値>
; CF	: 0 : 正常終了/ 1 : 書き込み動作中で処理中止
;
;bit _read_spi_block2(int reg_adr, unsigned char *data, unsigned char size)

__read_spi_block2:
READBLOCK2:
	PUSH	HL
	PUSH	AX
	CALL	!CHKRDY		; 書き込み中でないかチェック
	BC	$BUSYEXIT	; 書き込み中なら処理を中止
	MOVW	AX,SP		; 2つ目以降の引数を取り出す準備
	MOVW	HL,AX		; ポインタをHLレジスタに設定
	CALL	!CSOUT		; CS信号を出力
	MOV	SOTB10,#READC	; リードコマンドを送信
	CALL	!CSIRDY		; コマンド転送完了待ち
	MOV	A,[HL+1]	; EEPROMのアドレス上位を読み出す
	MOV	SOTB10,A	; アドレスの上位を送信
	CALL	!CSIRDY		; アドレス転送完了待ち
	BR	$READBLOCK	; 下位アドレス送信以降のデータ受信処理へ
(11)データの書き込み1
512バイト以下の容量のEEPROMに256バイト以下のデータを書き込みます。EEPROMのステータスを確認し、書き込み中でなければ、書き込み許可コマンドを発行します。書き込むアドレスが256番地を超える場合には、コマンドのビット3をセットしたライトコマンドを発行し、続いて、EEPROMのアドレスを1バイト転送します。以降は指定されたパラメータでの書き込み(実際は転送)を行ないます。指定されたデータの転送が完了するとCS信号をOFFにして、EEPROMに転送完了を通知します。EEPROMはステータス・レジスタのビット0を1にして実際の書き込み動作を開始します。このプログラムでは、書き込み完了を待つ処理は行いません。従って、転送が完了し、EEPROMが書き込みを行なっているときに別の処理を行なうことができます。
;
;	データの書き込み1
;
; <機能>
; 512バイト以下の容量のEEPROMに対して、引数として渡された
;パラメータで書き込みを行ないます。
; EEPROMが書き込み動作中でなければ指定された書き込みを実行し
;キャリー・フラグをクリアして戻ります。
; EEPROMが書き込み動作中なら、書き込みは行なわず、キャリー・
;フラグをセットして戻ります。
;
; <入力パラメータ(引数)>
; AX	: 第1の引数 :EEPROM内のアドレス
; SP+2,3: 第2の引数 :バッファ・メモリのアドレス
; SP+4  : 第3の引数 :書き込みデータ数
;
; <戻り値>
; CF	: 0 : 正常終了/ 1 : 書き込み動作中で処理中止
;
;bit _write_spi_block1(int reg_adr, unsigned char *data, unsigned char size)

__write_spi_block1:
WRITEBLOCK1:
	PUSH	HL
	PUSH	AX
	CALL	!CHKRDY		; 書き込み中でないかチェック
	BC	$EXITWRITE	; 書き込み中なら処理を中止
;	CALL	!WRITEENB	; 書き込み許可(一度設定すれば個別設定は不要)
	MOVW	AX,SP		; 2つ目以降の引数を取り出す準備
	MOVW	HL,AX		; ポインタをHLレジスタに設定
	CALL	!CSOUT		; CS信号を出力
	MOV	A,[HL+1]	; EEPROMのアドレス上位を読み出す
	AND	A,#1		; 256バイト以上かのチェック
	ROL	A,1
	ROL	A,1
	ROL	A,1		; A8をビット3に移動
	OR	A,#WRITEC	; ライトコマンドを生成する
	MOV	SOTB10,A	; コマンドを送信
	CALL	!CSIRDY		; コマンド転送完了待ち
WRITEBLOCK:
	MOV	A,[HL]		; アドレス下位を取り出す
	MOV	SOTB10,A	; アドレスを送信
	MOV	A,[HL+8]	; 転送データ数を取り出す
	MOV	TxCOUNT,A	; データ数を作業領域にコピー
	MOV	A,[HL+6]	; バッファ・アドレス下位を取り出す
	MOV	X,A
	MOV	A,[HL+7]	; 上位アドレスを取り出す。
	MOVW	HL,AX		; HLレジスタにアドレスを設定
	CALL	!CSIRDY		; アドレス転送完了待ち(不要)
;
;	データ送信処理
;
WRITELOOP:
	MOV	A,[HL]		; 4:送信データの読み出し
	MOV	SOTB10,A	; 5:送信データ書き込み
	INCW	HL		; 4:ポインタを更新
	CALL	!CSIRDY		;  :受信完了待ち
	DEC	TxCOUNT		; 4:残りデータ数カウント
	BNZ	$WRITELOOP	; 6:データ数分繰り返す。
	CALL	!CSOUT		; CS信号をきる
	CLR1	CY		; エラー・フラグをクリア

EXITWRITE:
	POP	AX
	POP	HL
	RET
(12)データの書き込み2
1Kバイト以上の容量のEEPROMに256バイト以下のデータを書き込みます。EEPROMのアドレスが2バイトになるだけで、その後の処理はデータ書き込み1と同じです。
;
;	データの書き込み2
;
; <機能>
; 1Kバイト以上の容量のEEPROMに対して、引数として渡された
;パラメータで書き込みを行ないます。
; EEPROMが書き込み動作中でなければ指定された書き込みを実行し
;キャリー・フラグをクリアして戻ります。
; EEPROMが書き込み動作中なら、書き込みは行なわず、キャリー・
;フラグをセットして戻ります。
;
; <入力パラメータ(引数)>
; AX	: 第1の引数 :EEPROM内のアドレス
; SP+2,3: 第2の引数 :バッファ・メモリのアドレス
; SP+4  : 第3の引数 :書き込みデータ数
;
; <戻り値>
; CF	: 0 : 正常終了/ 1 : 書き込み動作中で処理中止
;
;bit _write_spi_block2(int reg_adr, unsigned char *data, unsigned char size)

__write_spi_block2:
WRITEBLOCK2:
	PUSH	HL
	PUSH	AX
	CALL	!CHKRDY		; 書き込み中でないかチェック
	BC	$BUSYEXIT	; 書き込み中なら処理を中止
;	CALL	!WRITEENB	; 書き込み許可(一度設定すれば個別設定は不要)
	MOVW	AX,SP		; 2つ目以降の引数を取り出す準備
	MOVW	HL,AX		; ポインタをHLレジスタに設定
	CALL	!CSOUT		; CS信号を出力
	MOV	SOTB10,#WRITEC	; ライトコマンドを送信
	CALL	!CSIRDY		; コマンド転送完了待ち
	MOV	A,[HL+1]	; アドレス上位を取り出す
	MOV	SOTB10,A	; アドレス上位を送信
	CALL	!CSIRDY		; 転送完了待ち
	BR	$WRITEBLOCK	; 下位アドレス以降の処理へ
(13)書き込み完了待ち
EEPROMのステータス・レジスタを読み出すことで、書き込み動作中かをチェックします。書き込みが完了していなければ、完了するまで確認処理を繰り返します。データ書き込み処理の後処理として使用します。
;
;	書き込み完了待ち
;
; <機能>
; EEPROMへのデータ転送後、CS信号が立ち上がると転送された
;データが実際に書き込みがおこなわれる。ここでは、完了するまで待つ。
;
; <入力パラメータ(引数)> なし
; <戻り値> なし
;
;void _waitwt(void)

__waitwt:
WAITWT:
	PUSH	BC		; レジスタをセーブ

WAITLOOP:
	CALL	!READST		; ステータス・レジスタのチェック
	MOV	A,C
	ROR	A,1		; 書き込み中フラグをキャリー・フラグへへ
	BC	$WAITLOOP	; 書き込み中ならループ
	POP	BC
	RET
(14) バイト転送完了待ち
1バイトのデータ転送が完了したかを割り込み要求フラグをポーリングすることで待ち合わせます。内部で転送完了の待ち合わせで使用します。
;
;	CSIの転送完了待ち
; <機能>
; CSIでの転送完了を割り込み要求フラグをポーリングして待ち、
; 転送完了したら、割り込み要求フラグをクリアして戻る。
; <入力パラメータ(引数)> なし
; <戻り値> なし
;

CSIRDY:
	NOP
	BF	CSIIF10,$CSIRDY
	CLR1	CSIIF10		; 割り込み要求フラグをクリア
	RET

[C言語でのプログラム例]
ここではC言語でプログラムを作成した場合のプログラム例を示します。大きな構成や外部のプログラムとのインタフェースなどはアセンブラ記述のプログラムと同じです。ただし、制御構造の記述の関係で変更した部分もあります。

(1)宣言及び定義部分
ここでは、関数のプロトタイプ宣言やSPIのコマンドの定義、変数の定義等を行なっています。
//
//		 このモジュールはSPIによるEEPROMの
//		制御関数の例です(C言語記述)です。
//
#pragma	SFR
#pragma	NOP
void putspi(unsigned char data);	// 1文字送信
unsigned char getspi(void);		// 1文字受信
bit selprom(unsigned char spi_adr);	// ROM選択
bit chkrdy(void);			// 書き込み完了チェック
void writeenb(void);			// 書き込み許可設定
void writedis(void);			// 書き込み禁止設定
unsigned char readst(void);		// ステータス・レジスタの読み出し
void writest(unsigned char st);	// ステータス・レジスタへの書き込み
bit read_spi_block1(int reg_adr, unsigned char *data, unsigned char size);
// 512バイト以下のEEROMからの読み出し
bit read_spi_block2(int reg_adr, unsigned char *data, unsigned char size);
// 1kバイト以上のEEROMからの読み出し
bit write_spi_block1(int reg_adr, unsigned char *data, unsigned char size);
// 512バイト以下のEEROMへの書き込み
bit write_spi_block2(int reg_adr, unsigned char *data, unsigned char size);
// 1kバイト以上のEEROMへの書き込み
void waitwt(void);			// 転送データの書き込み完了を待つ

/*------------------------------------------------------*/
/*                                                      */
/*      SPI関連のコマンド定義                           */
/*                                                      */
/*------------------------------------------------------*/

#define	WRENC	0b00000110	// 書き込み許可
#define	WRDIC	0b00000100	// 書き込み禁止
#define	RDSRC	0b00000101	// ステータス・レジスタのリード
#define	WRSRC	0b00000001	// ステータス・レジスタへの書き込み
#define	READC	0b00000011	// データ読み出し
#define	WRITEC	0b00000010	// データ書き込み

#define	ROMNO	2		// 接続したEEPROMの数


static sreg unsigned char	csflag;	// CS生成用データ
(2)1文字送信関数
内部で使用するための関数で1文字分のデータをシリアル・チャネルを介してEEPROMに転送します。転送完了は割り込み要求(CSIIF10)をポーリングして確認します。EEPROMへの送信は全てこの関数を介して行ないます。
/*------------------------------------------------------------*/
/*                                                            */
/*                      シリアル送信処理                      */
/*                                                            */
/*  <機能>                                                  */
/*  引数で渡された8ビットのデータをシリアルで転送します。    */
/*転送が完了したら戻ります。                                  */
/*                                                            */
/*  <入力パラメータ(引数)>                                */
/*      送信データ                                            */
/*  <戻り値>  なし                                          */
/*                                                            */
/*------------------------------------------------------------*/

void	putspi(unsigned char data)
{
	SOTB10 = data;			// データをシリアルで送信
	while(CSIIF10 == 0){		// 転送完了待ち
		NOP();
	}
	CSIIF10 = 0;			// 転送完了割り込みをクリア
}
(3) 1文字受信関数
この関数は、EEPROMからの1文字分のデータをシリアル・チャネル経由で受信します。
/*------------------------------------------------------------*/
/*                                                            */
/*                      シリアル受信処理                      */
/*                                                            */
/* <機能>                                                  */
/* 8ビットのデータをシリアルで転送(受信)します。          */
/*転送が完了したら受信データを持って戻ります。                */
/*                                                            */
/* <入力パラメータ(引数)>    なし                        */
/* <戻り値>                                                */
/*      受信データ                                            */
/*                                                            */
/*------------------------------------------------------------*/

unsigned char	getspi(void)
{
	unsigned char work;
	SOTB10 = 0xff;			// 受信のためのダミー・データ送信
	while(CSIIF10 == 0){		// 転送完了待ち
		NOP();
	}
	CSIIF10 = 0;			// 転送完了割り込みをクリア
	work = SIO10;			// 受信データの読み出し
	return work;
}
(4) EEPROMの選択関数
複数のEEPROMを接続した場合にどのEEPROMかを前もって設定するための関数です。1〜ROMNOの値を引数として関数をコールしてください。
/*--------------------------------------------------------------*/
/*                                                              */
/*                      EEPROMの選択                      */
/*                                                              */
/* <機能>                                                    */
/* 引数で指定されたEEPROMをアクセス対象に設定します。    */
/*ここではCS用のビットイメージを抽出して作業領域に保存します。*/
/*実際のCS信号出力はCSOUT関数で行ないます。                   */
/*                                                              */
/* <入力パラメータ(引数)>                                  */
/*      EEPROMの番号                                      */
/* <戻り値>                                                  */
/* エラーならフラグをセットして戻る                            */
/*                                                              */
/*--------------------------------------------------------------*/

bit	selprom(unsigned char spi_adr)
{
	unsigned char work;
	if(spi_adr > ROMNO)	return 1;
	work = 0b00000100;
	csflag = work << spi_adr;
}
(5) EEPROMが書き込み中かのチェック関数
EEPROMが書き込み中でないかをステータス・レジスタにより確認するための内部で使用する関数です。
/*--------------------------------------------------------------*/
/*                                                              */
/*              EEPROMが書き込み処理中かのチェック        */
/*                                                              */
/* <機能>                                                    */
/* EEPROMのステータス・レジスタを確認し、書き込み処理中  */
/*ならばフラグをセットして戻る                                  */
/*                                                              */
/* <入力パラメータ(引数)> なし                            */
/* <戻り値>                                                  */
/* 0 : 書き込み中ではない/ 1 : 書き込み中                     */
/*                                                              */
/*--------------------------------------------------------------*/
bit	chkrdy(void)
{
	unsigned char work;
	work = readst();		// ステータスレジスタの読み出し
	return work & 0b00000001;	// 結果を戻り値にセット
}
(6) CS信号の制御関数
EEPROMの選択関数で指定されたEEPROMに対するCS信号の出力を制御するための内部関数です。
/*--------------------------------------------------------------*/
/*                                                              */
/*                      CS信号の出力                          */
/* <機能>                                                    */
/* 前もって作業領域に設定した内容に基づきCS信号出力の状態を  */
/*反転します。                                                  */
/*                                                              */
/* <入力パラメータ(引数)> なし                            */
/* <戻り値> なし                                            */
/*                                                              */
/*--------------------------------------------------------------*/

void csout(void)
{
	P1 = P1 ^ csflag;		// 	CS 信号を反転
}
(7) 書き込み許可関数
選択されているEEPROMにWRENコマンドを転送します。EEPROMに書き込みを行なう場合には最初にこの処理を行なう必要があります。
/*--------------------------------------------------------------*/
/*                                                              */
/*                      書き込み許可コマンド発行                */
/* <機能>                                                    */
/* 指定されているEEPROMを書き込み許可に設定します。      */
/*                                                              */
/* <入力パラメータ(引数)> なし                            */
/* <戻り値> なし                                            */
/*                                                              */
/*--------------------------------------------------------------*/

void writeenb(void)
{
	P1 = P1 ^ csflag;		// CS 信号を反転
	putspi(WRENC);			// 書き込み許可コマンドを転送
	P1 = P1 ^ csflag;		// CS 信号を反転
}
(8) 書き込み禁止関数
選択されているEEPROMにWRDIコマンドを転送し、書き込み禁止にします。
/*--------------------------------------------------------------*/
/*                                                              */
/*                      書き込み禁止コマンド発行                */
/* <機能>                                                    */
/* 指定されているEEPROMを書き込み禁止に設定します。      */
/*                                                              */
/* <入力パラメータ(引数)> なし                            */
/* <戻り値> なし                                            */
/*                                                              */
/*--------------------------------------------------------------*/

void writedis(void)
{
	P1 = P1 ^ csflag;		// CS 信号を反転
	putspi(WRDIC);			// 書き込み禁止コマンドを転送
	P1 = P1 ^ csflag;		// CS 信号を反転
}
(9) ステータス・レジスタの読み出し関数
選択されているEEPROMからステータス・レジスタの内容を読み出します。ステータス・レジスタのビットの意味は[ステータス・レジスタ]を参照してください。
/*--------------------------------------------------------------*/
/*                                                              */
/*              ステータス・レジスタのリード                    */
/* <機能>                                                    */
/* 指定されているEEPROMのステータス・レジスタを読み出す  */
/*                                                              */
/* <入力パラメータ(引数)> なし                            */
/* <戻り値>                                                  */
/* 読み出したステータス                                        */
/*                                                              */
/*--------------------------------------------------------------*/

unsigned char readst(void)
{
	unsigned char work;
	P1 = P1 ^ csflag;		// CS 信号を反転
	putspi(RDSRC);			// コマンドを転送
	work = getspi();		// ステータスの読み出し
	P1 = P1 ^ csflag;		// CS 信号を反転
	return work;
}
(10) ステータス・レジスタへの書き込み関数
選択されているEEPROMのステータス・レジスタへの書き込みを行ないます。書き込むデータは個々のEEPROMで異なります。通常は、領域ごとのライト・プロテクトを設定するために使用します。
/*--------------------------------------------------------------*/
/*                                                              */
/*              ステータス・レジスタへの書き込み                */
/* 引数で渡された値を、指定されているEEPROMのステータス・*/
/*レジスタに書き込みます。                                      */
/*                                                              */
/* <入力パラメータ(引数)>                                  */
/*      :書き込み値                                             */
/* <戻り値> なし                                            */
/*                                                              */
/*--------------------------------------------------------------*/

void writest(unsigned char st)
{
//	writeenb();				// 書き込み許可に設定
	P1 = P1 ^ csflag;			// CS 信号を反転
	putspi(WRSRC);				// コマンドを転送
	putspi(st);				// 設定データを転送
	P1 = P1 ^ csflag;			// CS 信号を反転
}
(11) データ読み出し関数1
選択されているEEPROM(容量が512バイトまでのもの)からデータを読み出します。読み出すデータ数は最大256バイトまでです。デバイスの容量より多いデータ数を指定したときの動作はEEPROMに依存します。
/*----------------------------------------------------------------------*/
/*                                                                      */
/*                      データの読み出し1                              */
/*                                                                      */
/* <機能>                                                            */
/* 512バイト以下の容量のEEPROMに対して、引数として渡された    */
/*パラメータで読み出しを行ないます。                                    */
/* EEPROMが書き込み動作中でなければ指定された読み出しを実行し    */
/*エラー・フラグをクリアして戻ります。                                  */
/* EEPROMが書き込み動作中なら、読み出しは行なわず、エラー・      */
/*フラグをセットして戻ります。                                          */
/*                                                                      */
/* <入力パラメータ(引数)>                                          */
/* 第1の引数 :EEPROM内のアドレス                                 */
/* 第2の引数 :読み出したデータを格納するメモリのアドレス               */
/* 第3の引数 :読み出しデータ数                                         */
/*                                                                      */
/* <戻り値>                                                          */
/*  0 : 正常終了/ 1 : 書き込み動作中で処理中止                         */
/*                                                                      */
/*----------------------------------------------------------------------*/

bit read_spi_block1(int reg_adr, unsigned char *data, unsigned char size)
{
	unsigned char work;
	int count;				// 受信データ数のカウンタ
	if(chkrdy())	return 1;		// 書き込み中ならエラーで戻る
	P1 = P1 ^ csflag;			// CS 信号を反転
	if(reg_adr > 0xff){
		work = READC | 0b00001000;
	}else work = READC;
	putspi(work);				// コマンドを転送
	work = reg_adr & 0xff;			// 
	putspi(work);				// アドレスを転送
	if(size){
		count = size;
	}else count = 0x100;			// 入力が0なら100Hに
	do{
		work = getspi();		// データの受信
		*data++ = work;
	}while(--count);
	P1 = P1 ^ csflag;			// CS 信号を反転(選択解除)
}
(12) データ読み出し関数2
選択されているEEPROM(容量が1K〜64Kバイトまでのもの)からデータを読み出します。読み出すデータ数は最大256バイトまでです。デバイスの容量より多いデータ数を指定したときの動作はEEPROMに依存します。
/*----------------------------------------------------------------------*/
/*                                                                      */
/*                      データの読み出し2                              */
/*                                                                      */
/* <機能>                                                            */
/* 1kバイト以上の容量のEEPROMに対して、引数として渡された      */
/*パラメータで読み出しを行ないます。                                    */
/* EEPROMが書き込み動作中でなければ指定された読み出しを実行し    */
/*エラー・フラグをクリアして戻ります。                                  */
/* EEPROMが書き込み動作中なら、読み出しは行なわず、エラー・      */
/*フラグをセットして戻ります。                                          */
/*                                                                      */
/* <入力パラメータ(引数)>                                          */
/* 第1の引数 :EEPROM内のアドレス                                 */
/* 第2の引数 :バッファ・メモリのアドレス                               */
/* 第3の引数 :読み出しデータ数                                         */
/*                                                                      */
/* <戻り値>                                                          */
/*  0 : 正常終了/ 1 : 書き込み動作中で処理中止                         */
/*                                                                      */
/*----------------------------------------------------------------------*/

bit read_spi_block2(int reg_adr, unsigned char *data, unsigned char size)
{
	unsigned char work;
	int count;				// 受信データ数のカウンタ
	if(chkrdy())	return 1;		// 書き込み中ならエラーで戻る
	P1 = P1 ^ csflag;			// CS 信号を反転
	putspi(READC);				// コマンドを転送
	work = reg_adr / 0x100;			// 上位アドレスを抽出
	putspi(work);				// アドレスを転送
	work = reg_adr & 0xff;			// 下位アドレスを抽出
	putspi(work);				// アドレスを転送

	if(size){
		count = size;
	}else count = 0x100;			// 入力が0なら100Hに
	do{
		work = getspi();		// データの受信
		*data++ = work;
	}while(--count);
	P1 = P1 ^ csflag;			// CS 信号を反転(選択解除)
}
(13) データ書き込み関数1
選択されているEEPROM(容量が512バイトまでのもの)にデータを書き込みます。読み出すデータ数は最大256バイトまでです。デバイスの容量より多いデータ数を指定したときの動作はEEPROMに依存します。
/*----------------------------------------------------------------------*/
/*                                                                      */
/*                              データの書き込み1                      */
/*                                                                      */
/* <機能>                                                            */
/* 512バイト以下の容量のEEPROMに対して、引数として渡された    */
/*パラメータで書き込みを行ないます。                                    */
/* EEPROMが書き込み動作中でなければ指定された書き込みを実行し    */
/*エラー・フラグをクリアして戻ります。                                  */
/* EEPROMが書き込み動作中なら、書き込みは行なわず、エラー・      */
/*フラグをセットして戻ります。                                          */
/*                                                                      */
/* <入力パラメータ(引数)>                                          */
/* 第1の引数 :EEPROM内のアドレス                                 */
/* 第2の引数 :書き込みデータの格納されたバッファ・メモリのアドレス     */
/* 第3の引数 :書き込みデータ数                                         */
/*                                                                      */
/* <戻り値>                                                          */
/*  0 : 正常終了/ 1 : 書き込み動作中で処理中止                         */
/*                                                                      */
/*----------------------------------------------------------------------*/

bit write_spi_block1(int reg_adr, unsigned char *data, unsigned char size)
{
	unsigned char work;
	int count;				// 送信データ数のカウンタ
	if(chkrdy())	return 1;		// 書き込み中ならエラーで戻る
	P1 = P1 ^ csflag;			// CS 信号を反転
	if(reg_adr > 0xff){
		work = WRITEC | 0b00001000;
	}else work = WRITEC;
	putspi(work);				// コマンドを転送
	work = reg_adr & 0xff;			// 
	putspi(work);				// アドレスを転送

	if(size){
		count = size;
	}else count = 0x100;			// 入力が0なら100Hに
	do{
		putspi(*data++);		// 送信データ書き込み
	}while(--count);
	P1 = P1 ^ csflag;			// CS 信号を反転(選択解除)
}
(14) データ書き込み関数2
選択されているEEPROM(容量が1K〜64Kバイトまでのもの)にデータを書き込みます。読み出すデータ数は最大256バイトまでです。デバイスの容量より多いデータ数を指定したときの動作はEEPROMに依存します。
/*----------------------------------------------------------------------*/
/*                                                                      */
/*                              データの書き込み2                      */
/*                                                                      */
/* <機能>                                                            */
/* 1kバイト以上の容量のEEPROMに対して、引数として渡された      */
/*パラメータで書き込みを行ないます。                                    */
/* EEPROMが書き込み動作中でなければ指定された書き込みを実行し    */
/*エラー・フラグをクリアして戻ります。                                  */
/* EEPROMが書き込み動作中なら、書き込みは行なわず、エラー・      */
/*フラグをセットして戻ります。                                          */
/*                                                                      */
/* <入力パラメータ(引数)>                                          */
/* 第1の引数 :EEPROM内のアドレス                                 */
/* 第2の引数 : 書き込みデータの格納されたバッファ・メモリのアドレス    */
/* 第3の引数 :書き込みデータ数                                         */
/*                                                                      */
/* <戻り値>                                                          */
/*  0 : 正常終了/ 1 : 書き込み動作中で処理中止                         */
/*                                                                      */
/*----------------------------------------------------------------------*/

bit write_spi_block2(int reg_adr, unsigned char *data, unsigned char size)
{
	unsigned char work;
	int count;				// 送信データ数のカウンタ
	if(chkrdy())	return 1;		// 書き込み中ならエラーで戻る
	P1 = P1 ^ csflag;			// CS 信号を反転
	putspi(WRITEC);				// コマンドを転送
	work = reg_adr /0x100;			// 上位アドレスを抽出
	putspi(work);				// 
	work = reg_adr & 0xff;			// 
	putspi(work);				// アドレスを転送

	if(size){
		count = size;
	}else count = 0x100;			// 入力が0なら100Hに
	do{
		putspi(*data++);		// 送信データ書き込み
	}while(--count);
	P1 = P1 ^ csflag;			// CS 信号を反転(選択解除)
}
(15)書き込み完了待ち関数
EEPROMに書き込みを行なったときに書き込みが完了するまで待つための関数です。ステータス・レジスタを読み出して書き込みが完了するまでを待ちます。
/*----------------------------------------------------------------------*/
/*                                                                      */
/*                              書き込み完了待ち                        */
/*                                                                      */
/* <機能>                                                            */
/* EEPROMへのデータ転送後、CS信号が立ち上がると転送された      */
/*データが実際に書き込みがおこなわれる。ここでは、完了するまで待つ。    */
/*                                                                      */
/* <入力パラメータ(引数)> なし                                    */
/* <戻り値> なし                                                    */
/*                                                                      */
/*----------------------------------------------------------------------*/

void waitwt(void)
{
	while(readst() & 0b00000001);
}

[プログラム例の使用方法1]
ここでは、アセンブラ記述での使用方法の例を示します。

(1)宣言部
ここでは上で説明したプログラム例のサブルーチンを使用するための宣言を行ないます。また、データを格納するためのバッファ・メモリ領域も定義します。受信用はDS擬似命令で領域を確保し、送信用には固定データを準備しています。
;
;	 このプログラムはSPI制御ルーチンモジュールを使用して
;	EEPROMをアクセスする例を示します。
;
;	参照する制御サブルーチン
;
	EXTRN	SELPROM		; アクセスするEEPROMを選択
	EXTRN	WRITEENB	; 書き込み許可にする
	EXTRN	WRITEDIS	; 書き込み禁止にする
	EXTRN	READST		; ステータス・レジスタのリード
	EXTRN	WRITEST		; ステータス・レジスタへのライト
;
	EXTRN	READBLOCK1
		; 512バイト以下のEEPROMからのデータ・リード
	EXTRN	READBLOCK2
		; 1Kバイト以上のEEPROMからのデータ・リード
	EXTRN	WRITEBLOCK1
		; 512バイト以下のEEPROMへのデータ・ライト
	EXTRN	WRITEBLOCK2
		; 1Kバイト以上のEEPROMへのデータ・ライト
;
	EXTRN	WAITWT		; 書き込み完了待ち

;
;	作業領域の定義
;

	DSEG
RxBUFF1:				; 受信用データ・バッファ
	DS	16
RxBUFF2:
	DS	16
RxBUFF3:
	DS	16
;
;	送信テスト用データ
;
	CSEG
TxDATA1:
	DB	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
TxDATA2:
	DB	0,1,2,4,8,16,32,64,128,64,32,16,8,4,2,1
(2)読み出し処理
EEPROMからデータを読み出すにはEEPROMを選択し、必要なパラメータをスタックやレジスタにセットしてREADBLOCK1(512バイト以下のEEPROMの場合)またはREADBLOCK2(1K〜64KバイトのEEPROMの場合)をサブルーチン・コールします。エラー(EEPROMが書き込み中)の場合にはキャリー・フラグがセットされて戻ってくるので、エラー処理に分岐させてください。
	MOV	X,#1
	CALL	!SELPROM

;
;	512バイト以下のEEPROMの読み出し例
;
RxTEST:
	MOVW	AX,#16			; 読み出しデータ数セット
	PUSH	AX
	MOVW	AX,#RxBUFF1		; バッファ・アドレスをセット
	PUSH	AX
	MOVW	AX,#33H			; EEPROM内部アドレス
	CALL	!READBLOCK1
	POP	AX
	POP	AX
	BC	$ERRORLOOP		; エラーならエラー処理へ
(3)書き込み処理
EEPROMにデータを書き込むには最初にEEPROMを選択し、書き込みを許可状態にする必要があります。その後、必要なパラメータをスタックやレジスタにセットして、512バイト以下のEEPROMの場合にはWRITEBLOCK1を、1K〜64Kの場合にはWRITEBLOCK2をサブルーチン・コールします。サブルーチンから戻ってきた段階でエラーが発生していなければ、EEPROMは転送されたデータを実際に書き込んでいます。この間に必要に応じて、他の処理を行なってください。書き込みの完了はWAITWTをコールすることで、書き込み完了まで待ち合わせます。
	MOV	X,#1
	CALL	!SELPROM
	CALL	!WRITEENB		; 書き込み許可に
;
;	256〜512のEEPROMへの書き込み例
;
	MOVW	AX,#16			; データ数のセット(16バイト)
	PUSH	AX
	MOVW	AX,#TxDATA2		; バッファ・アドレスのセット
	PUSH	AX
	MOVW	AX,#0155H		; EEPROM内部アドレス
	CALL	!WRITEBLOCK1
	POP	AX
	POP	AX
	BC	$ERRORLOOP		; エラーならエラー処理へ

	ここに必要に応じて他の処理を入れる

	CALL	!WAITWT			; 書き込み完了待ち

[プログラム例の使用方法2]
ここでは、C言語記述での使用方法の例を示します。使用する制御プログラムがアセンブラ記述のものかC言語記述のものかは呼び出す関数の名前が異なるだけです。C言語記述の制御プログラムを使用する場合には、関数の名前の先頭にある'_'を削除するだけで上記のC言語記述の制御プログラム例を使用できます。

(1)宣言部
ここでは上で説明したプログラム例(アセンブラ記述分)のサブルーチンを使用するための宣言を行ないます。
#pragma	SFR
extern bit _selprom(unsigned char spi_adr);	// ROM選択
extern void _writeenb(void);			// 書き込み許可設定
extern void _writedis(void);			// 書き込み禁止設定
extern unsigned char _readst(void);		// ステータス・レジスタの読み出し
extern void _writest(unsigned char st);	// ステータス・レジスタへの書き込み
extern bit _read_spi_block1(int reg_adr, unsigned char *data, unsigned char size);
// 512バイト以下のEEROMからの読み出し
extern bit _read_spi_block2(int reg_adr, unsigned char *data, unsigned char size);
// 1kバイト以上のEEROMからの読み出し
extern bit _write_spi_block1(int reg_adr, unsigned char *data, unsigned char size);
// 512バイト以下のEEROMへの書き込み
extern bit _write_spi_block2(int reg_adr, unsigned char *data, unsigned char size);
// 1kバイト以上のEEROMへの書き込み
extern void _waitwt(void);			// 転送データの書き込み完了を待つ
これ以外に、このファイル中にある関数のプロトタイプ宣言や読み出しデータ用のバッファ・メモリや固定データを書き込む際のデータ・パターンなどを宣言しています。
void hdwinit(void);
bit rxtest(void);
bit	txtest(void);
unsigned char	eep_read_buf1[16];	// read buffer
unsigned char	eep_read_buf2[16];	// read buffer
unsigned char	eep_read_buf3[16];	// read buffer

typedef unsigned char data16[16];
const data16 txdata1 = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
const data16 txdata2 = {0,1,2,4,8,16,32,64,128,64,32,16,8,4,2,1};
(2)読み出し処理
ここではステータス・レジスタの読み出しと、データの読み出しの例を示します。ここではrxtestとして関数の形にしてあり、制御プログラムでエラーが発生した場合にはそのままエラーをもって戻るようになっています。
この例では、1番のEEPROMを選択し、ステータス・レジスタの内容を読み出し、その後に、256番地未満のアドレス(0x33)と256番地以上のアドレス(0x1cc)から16バイトのデータを読み出し、その後EEPROMを切り替えて、512番地以上(0x33aa)のアドレスから読み出しています。
bit rxtest(void)
{
	unsigned char work;
	if(_selprom(1) == 1) return 1;
	work = _readst();
	if(_read_spi_block1(0x33, eep_read_buf1, 16)) return 1;

	if(_read_spi_block1(0x1cc, eep_read_buf2, 16)) return 1;

	if(_selprom(2) == 1) return 1;
	if(_read_spi_block2(0x33cc, eep_read_buf3, 16)) return 1;
}
(3)書き込み処理
書き込みについても関数の形にしてあります。対象とするEEPROMを選択した後に、書き込み許可状態にして、データの書き込みを行なっています。
bit	txtest(void)
{
	if(_selprom(1) == 1) return 1;
	_writeenb();                                            // 書き込み許可
	if(_write_spi_block1(0xaa, txdata1, 16))return 1;

//	ここに他の処理を入れてもよい

	_waitwt();
	if(_write_spi_block1(0x155, txdata2, 16))return 1;

//	ここに他の処理を入れてもよい

	_waitwt();
	if(_selprom(2) == 1) return 1;
	_writeenb();                                            // 書き込み許可
	if(_write_spi_block2(0x55aa, txdata1, 16))return 1;

//	ここに他の処理を入れてもよい

	_waitwt();
}

(2006/08)

この情報はお役にたちましたか?
back to top  
(2006/08)

EEPROM
-0003
78K0S/Kx1+によるSPI・EEPROMの制御プログラム例(78K0S/Kx1+)
[はじめに]
SPIの概要やSPIインタフェースのEEPROMについては「CSIによるSPIメモリの制御」を参照してください。78K0S/Kx1+には3線式のシリアル機能が内蔵されていません。そこで、ポート2を用いて下記の接続例に示したようにEEPROMを接続して、ソフト的に制御する場合の具体的な制御プログラムについて説明します。また、制御プログラムの使い方についても簡単に触れておきます。



[78K0S/KY1+の処理例]
78K0S/KY1+(以下小ピンと呼ぶ)でのEEPROMの制御処理は以下の部分から構成します。内部で使用するサブルーチン以外はC言語からの使用を意識して、名前と入出力パラメータ(引数と戻り値)を決めています。例えば引数として、読み出しや書き込みでは以下のパラメータを用います。
 第1パラメータ(AX渡し):EEPROMのアドレス
 第2パラメータ(スタック渡し):バッファ・メモリのアドレス
 第3パラメータ(スタック渡し):転送データ数で1〜255及び0(256バイト)

(1)初期化部
ポート、割り込みの初期化を行ないます。基本的にベクタ割り込みは使用しないので、割り込みは禁止状態とします。また、8MHzで動作させたいので、電源電圧が4V以上になるまで待ちます。

(2)シリアル出力処理
小ピンにはCSIのようなシリアル機能がないので、ソフトウェアによるパラレル・シリアル変換と出力処理を行ないます。ソフト処理では通信速度が200kbps程度まで低下することが考えられます。ここでは、ループを回さないことでできるだけ速度の低下を少なくすることを考えます。

(3)シリアル入力処理
出力ポートを制御してSCKを出力しながら、入力ポートからシリアル・データを読み込み、パラレル・データに変換します。ここでもループを回さないことで通信速度の低下を防いでいます。

(4)ステータスの確認
EEPROMがデータ書き込み中かどうかをチェックします。内部でEEPROMへの書き込みやデータの読み出しを行なう前に使用します。

(5)書き込み許可
対象のEEPROMのCS信号をONにして、「WREN」コマンドを送ります。コマンド転送完了後CS信号をOFFにします。このコマンドによりEEPROMは書き込み可能状態になります。

(6)書き込み禁止
対象のEEPROMのCS信号をONにして、「WRDI」コマンドを送ります。コマンド転送完了後CS信号をOFFにします。このコマンドによりEEPROMは書き込み禁止状態になります。

(7)ステータス・レジスタの読み出し
対象のEEPROMのCS信号をONにして、「RDSR」コマンドを送り、ステータス・レジスタの状態を1バイトのデータで読み出します。読み出し完了後、CS信号をOFFにします。ステータス・レジスタのビットの意味は[ステータス・レジスタ]を参照してください。

(8)ステータス・レジスタへの書き込み
対象のEEPROMのCS信号をONにして、「WRSR」コマンドを送り、引き続いてステータス・レジスタにセットする1バイトのデータを書き込みます。書き込みデータの転送完了後CS信号をOFFにします。
通常はブロック毎のプロテクトの制御(ビット2,3)に使用します。

(9)データの読み出し1
512バイト以下の(従って、アドレスは1バイトでA8はコマンドで指定)容量のEEPROMから256バイト以下のデータを読み出します。EEPROMのステータスを確認し、書き込み中でなければ、指定されたパラメータでの読み出しを行ないます。

(10)データの読み出し2
1Kバイト以上の(ただし、アドレスは2バイト)容量のEEPROMから256バイト以下のデータを読み出します。EEPROMのステータスを確認し、書き込み中でなければ、指定されたパラメータでの読み出しを行ないます。

(11)データの書き込み1
512バイト以下の(従って、アドレスは1バイトでA8はコマンドで指定)容量のEEPROMに256バイト以下のデータを書き込みます。EEPROMのステータスを確認し、書き込み中でなければ、書き込み許可コマンドを発行し、指定されたパラメータでの書き込みを行ないます。
EEPROMへのデータ転送だけしか行なわないので、実際にEEPROMで書き込みが完了するまでは別の処理を並行して行なうことができます。なお、この間のEEPROMへのアクセスは、ステータス・レジスタの読み出し以外は行なわないようにしてください。

(12)データの書き込み2
1Kバイト以上の(ただし、アドレスは2バイト)容量のEEPROMに256バイト以下のデータを書き込みます。EEPROMのステータスを確認し、書き込み中でなければ、書き込み許可コマンドを発行し、指定されたパラメータでの書き込みを行ないます。
アドレス長が異なる以外は「データ書き込み1」と同じです。

(13)書き込み完了待ち
データ書き込み後に、実際にEEPROMでのデータ書き込み完了を待ちます。データ書き込みを行なった後はこの処理を実行するか、ステータス・レジスタを読み出して、ビット0が0になった(書き込みが完了した)ことを確認してください。

[アセンブラでのプログラム例]
このプログラム例では他のプログラムからこのプログラムの処理を使えるように、以下の10個のサブルーチンをパブリック宣言しています。これらは、アセンブラから使う場合やC言語のプログラムから使う場合も考慮しています。アセンブラから使用する場合には大文字の名前をEXTRN宣言してください。C言語のプログラムから使う場合には_で始まる名前をextern宣言(例えば、extern _writeenb のように_を一つにして宣言)してください。
	PUBLIC	__writeenb,WRITEENB	; 書き込み許可にする
	PUBLIC	__writedis,WRITEDIS	; 書き込み禁止にする
	PUBLIC	__readst,READST		; ステータス・レジスタのリード
	PUBLIC	__writest,WRITEST	; ステータス・レジスタへのライト
;
	PUBLIC	__read_spi_block1,READBLOCK1
		; 512バイト以下のEEPROMからのデータ・リード
	PUBLIC	__read_spi_block2,READBLOCK2
		; 1Kバイト以上のEEPROMからのデータ・リード
	PUBLIC	__write_spi_block1,WRITEBLOCK1
		; 512バイト以下のEEPROMへのデータ・ライト
	PUBLIC	__write_spi_block2,WRITEBLOCK2
		; 1Kバイト以上のEEPROMへのデータ・ライト
;
	PUBLIC	__waitwt,WAITWT		; 書き込み完了待ち
また、内部で使用する値の定義を前もって行なっています。
;
;	EEPROMのコマンド
;
WRENC	EQU	00000110b	; 書き込み許可
WRDIC	EQU	00000100b	; 書き込み禁止
RDSRC	EQU	00000101b	; ステータス・レジスタのリード
WRSRC	EQU	00000001b	; ステータス・レジスタへの書き込み
READC	EQU	00000011b	; データ読み出し
WRITEC	EQU	00000010b	; データ書き込み
(1)初期化部
オプション・バイトは以下のように設定し、高速内蔵発振クロックを使うように設定しておきます。
        @@OPTB  CSEG    AT      0080H
        DB      10011100b       ; オプション・バイト
;                || |||+-----:低速クロック停止可
;                || |++------:高速内蔵発振クロック使用
;                || +--------:RESET端子を使用
;                ++----------:発振安定時間は最短
;
        DB      11111111b       ; プロテクト・バイト
        END
ポートの動作モードを設定します。ここではベクタ割り込みを使用しないので、割り込みはマスクしておきます。
また、ソフトウェアでの変換処理のため、できるだけ高速で動作させるために、電源電圧が4V以上になるまで低電圧検出回路を用いて待ちます。
;
;	ポートや割り込みのイニシャライズ
;
	MOV	P2,#11111111b		; 出力ラッチの設定
	MOV	PM2,#11110010b		; P20、P22、P23は出力に
;
	MOV	MK0,#0FFH
	DI
;
;	電源の立ち上がり待ち
;
	MOV	LVIS,#00000000b		; VLI=4.0V
	MOV	LVIM,#10000000b		; 低電圧検出開始
	MOV	PCC,#00			; CPU clock is fx/4
	MOV	WDTM,#01110000b		; WDTを停止
	SET1	LSRSTOP			; 低速発振器停止
	MOV	A,#50
PONLOOP:
	DEC	A
	BNZ	$PONLOOP		; 0.2ms待つ

PONLOOP2:
	BT	LVIF,$PONLOOP2		; 電圧が4.0V以上まで待つ
	MOV	PPCC,#0			; CPU clock is fx=fR
(2) シリアル出力処理
記述を簡単にするため、以下のマクロを定義してこれを8回繰り返すことで、1バイトのデータをシリアルに変換してポートに出力します。受信側はSCKの立ち上がりで取り込むので、SCKの立ち下げとデータの出力を同時に行なうことで、処理速度をできるだけ落とさないようにしています。
;
;	シリアル出力処理(マクロ定義)
;
sout1	macro
	ROL	A,1		; 2:MSBよりCYにシフトアウトする
	MOV	X,A		; 4:
	AND	A,#00000001b	; 4:データ以外をマスク
	MOV	P2,A		; 4:SCK立ち下げとデータ出力を同時に
	MOV	A,X		; 4:
	SET1	P2.2		; 6:SCKを立ち上げる
	endm

;
;	1文字送信
; <機能>
; Aレジスタの内容をシリアルで送信する。
;
; <入力パラメータ(引数)>
; A : 送信データ
; <戻り値> なし
;

PUTSPI:
	sout1			;bit7出力
	sout1			;bit6出力
	sout1			;bit5出力
	sout1			;bit4出力
	sout1			;bit3出力
	sout1			;bit2出力
	sout1			;bit1出力
	sout1			;bit0出力
	RET
(3) シリアル入力処理
SCKを出力し、立ち上げたあとで、シリアル・データを読み込みAレジスタにシフトしながら蓄積することでデータを取り込みます。ループを回さないで処理する際の記述を簡単にするために以下のマクロを定義しておき、このマクロを8回実行させることで処理します。
;
;	シリアル入力処理(マクロ定義)
;
sin1	macro	bitno
	LOCAL	DATAis1
	MOV	P2,#11110011b	; 6:SCKを立ち下げる
	SET1	P2.2		; 6:SCKの立ち上げ
	BT	P2.1,$DATAis1	;10:
	CLR1	A.bitno		; 2:データが0ならデータを反転
DATAis1:
	endm

;
;	1文字受信
; <機能>
; シリアルからデータを受信する。
;
; <入力パラメータ(引数)> なし
; <戻り値>
; A : 受信データ
;

GETSPI:
	MOV	A,#11111111b	; 初期値として1を設定
	sin1	7		; MSBから順に受信処理
	sin1	6
	sin1	5
	sin1	4
	sin1	3
	sin1	2
	sin1	1
	sin1	0		; 最後にLSBを受信処理
	RET
(4)ステータスの確認
EEPROMのステータス・レジスタを読み出すことで、書き込み動作中かをチェックします。EEPROMへのデータ転送開始時にEEPROMのステータス確認のために内部で使用します。
;
;	EEPROMが書き込み処理中かのチェック
;
; <機能>
; EEPROMのステータス・レジスタを確認し、書き込み処理中
;ならばキャリー・フラグをセットして戻る
;
; <入力パラメータ(引数)> なし
; <戻り値>
; CF	: 0 : 書き込み中ではない/ 1 : 書き込み中
;

CHKRDY:
	PUSH	BC		; レジスタをセーブ
	CALL	!READST		; ステータス・レジスタのチェック
	MOV	A,C
	POP	BC
	ROR	A,1		; 書き込み中フラグをキャリー・フラグへ
	RET
(5)書き込み許可
対象のEEPROMに「WREN」コマンドを転送します。
;	書き込み許可コマンド発行
; <機能>
; 指定されているEEPROMを書き込み許可に設定します。
;
; <入力パラメータ(引数)> なし
; <戻り値> なし
;void	_writeenb(void)

__writeenb:
WRITEENB:
	MOV	A,#WRENC	; コマンドをセット

WRITEENBLOOP:			; 転送完了割り込みを待つ
	CLR1	P2.3		; CSを立ち下げる
	CALL	!PUTSPI		; コマンド転送
	SET1	P2.3		; コマンド完了でCSを解除
	RET
(6)書き込み禁止
対象のEEPROMに「WRDI」コマンドを転送します。コマンド以外は書き込み許可と同じなので、同じ処理を行ないます。
;
;	書き込み禁止コマンド発行
; <機能>
; 指定されているEEPROMを書き込み禁止に設定します。
;
; <入力パラメータ(引数)> なし
; <戻り値> なし
;void	_writedis(void)

__writedis:
WRITEDIS:
	MOV	A,#WRDIC	; コマンドをセット
	BR	$WRITEENBLOOP	; 完了待ち処理へ
(7) ステータス・レジスタの読み出し
対象のEEPROMに「RDSR」コマンドを転送し、EEPROMからのステータス・レジスタの内容を受け取ります。
;
;	ステータス・レジスタのリード・コマンド
; <機能>
; 指定されているEEPROMのステータス・レジスタを読み出します。
;
; <入力パラメータ(引数)> なし
; <戻り値>
; C	: 戻り値として、読み出したステータスが入ります
;
;unsigned char _readst(void)

__readst:
READST:
	CLR1	P2.3		; CSを立ち下げる
	MOV	A,#RDSRC	; コマンドをセット
	CALL	!PUTSPI		; コマンド転送
	CALL	!GETSPI		; データ受信
	MOV	C,A		; 戻り値をセット
	SET1	P2.3		; CSを解除
	RET
(8) ステータス・レジスタへの書き込み
対象のEEPROMに「WRSR」コマンドを送り、引き続いてステータス・レジスタに設定する値を転送します。
;
;	ステータス・レジスタへの書き込みコマンド
;
; <機能>
; 引数で渡された値を、指定されているEEPROMのステータス・
;レジスタに書き込みます。
;
; <入力パラメータ(引数)>
; X	: 引数として書き込み値が入る
; <戻り値> なし
;void _writest(unsigned char st)

__writest:
WRITEST:
	PUSH	AX		; ステータスをセーブ
	CLR1	P2.3		; CSを立ち下げる
	MOV	A,#WRSRC	; コマンドをセット
	CALL	!PUTSPI		; コマンド転送完了待ち
	POP	AX		; ステータスの復帰
	MOV	A,X
	CALL	!PUTSPI		; ステータス転送
	SET1	P2.3		; CSを解除
	RET
(9)データの読み出し1
512バイト以下の容量のEEPROMから256バイト以下のデータを読み出します。
EEPROMが書き込み中でなければ、指定されたパラメータでの書き込みを行ないます。この際、指定されたEEPROMのアドレスが256番地より大きい場合にはリード・コマンドのビット3をセットします。コマンドに引き続いて、アドレスを1バイト転送し、以降はEEPROMからのデータを読み出します。データの読み出しでは、ダミー・データとしてFFを書き込んで転送を起動します。読み出しが完了したら、CS信号をOFFにすることで、EEPROMに読み出しの完了を通知します。
;
;	データの読み出し1
;
; <機能>
; 512バイト以下の容量のEEPROMに対して、引数として渡された
;パラメータで読み出しを行ないます。
; EEPROMが書き込み動作中でなければ指定された読み出しを実行し
;キャリー・フラグをクリアして戻ります。
; EEPROMが書き込み動作中なら、読み出しは行なわず、キャリー・
;フラグをセットして戻ります。
;
; <入力パラメータ(引数)>
; AX	: 第1の引数 :EEPROM内のアドレス
; SP+2,3: 第2の引数 :バッファ・メモリのアドレス
; SP+4  : 第3の引数 :読み出しデータ数
;
; <戻り値>
; CF	: 0 : 正常終了/ 1 : 書き込み動作中で処理中止
;
;bit _read_spi_block1(int reg_adr, unsigned char *data, unsigned char size)

__read_spi_block1:
READBLOCK1:
	PUSH	HL
	PUSH	AX
	CALL	!CHKRDY		; 書き込み中でないかチェック
	BC	$BUSYEXIT	; 書き込み中なら処理を中止
	MOVW	AX,SP		; 2つ目以降の引数を取り出す準備
	MOVW	HL,AX		; ポインタをHLレジスタに設定
	PUSH	BC
	CLR1	P2.3		; CSを立ち下げる
	MOV	A,[HL+1]	; EEPROMのアドレス上位を読み出す
	AND	A,#1		; 256バイト以上かのチェック
	ROL	A,1
	ROL	A,1
	ROL	A,1		; A8をビット3に移動
	OR	A,#READC	; リード・コマンドを生成する
	CALL	!PUTSPI		; コマンド転送
READBLOCK:
	MOV	A,[HL]		; アドレス下位を取り出す
	CALL	!PUTSPI		; アドレスを送信
	MOV	A,[HL+8]	; 転送データ数を取り出す
	MOV	B,A		; データ数を作業領域にコピー
	MOV	A,[HL+6]	; バッファ・アドレス下位を取り出す
	MOV	X,A
	MOV	A,[HL+7]	; 上位アドレスを取り出す。
	MOVW	HL,AX		; HLレジスタにアドレスを設定
;
;	データ受信処理
;
READLOOP:
	CALL	!GETSPI		; 受信起動
	MOV	[HL],A		; 受信データをバッファへ
	INCW	HL		; ポインタを更新
	DBNZ	B,$READLOOP	; データ数分繰り返す。
	SET1	P2.3		; CSを解除
	POP	BC
	CLR1	CY		; エラー・フラグのクリア
BUSYEXIT:			; レジスタを復帰して戻る
	POP	AX
	POP	HL
	RET
(10)データの読み出し2
1Kバイト以上の容量のEEPROMから256バイト以下のデータを読み出します。
EEPROMが書き込み中でなければ、指定されたパラメータでの書き込みを行ないます。この際、リード・コマンドに引き続いて、アドレスを上位から順に2バイト転送し、以降はEEPROMからのデータを読み出します(以降はデータ読み出し1と共通なので、プログラムも共通化)。
;
;	データの読み出し2
;
; <機能>
; 1kバイト以上の容量のEEPROMに対して、引数として渡された
;パラメータで読み出しを行ないます。
; EEPROMが書き込み動作中でなければ指定された読み出しを実行し
;キャリー・フラグをクリアして戻ります。
; EEPROMが書き込み動作中なら、読み出しは行なわず、キャリー・
;フラグをセットして戻ります。
;
; <入力パラメータ(引数)>
; AX	: 第1の引数 :EEPROM内のアドレス
; SP+2,3: 第2の引数 :バッファ・メモリのアドレス
; SP+4  : 第3の引数 :読み出しデータ数
;
; <戻り値>
; CF	: 0 : 正常終了/ 1 : 書き込み動作中で処理中止
;
;bit _read_spi_block2(int reg_adr, unsigned char *data, unsigned char size)

__read_spi_block2:
READBLOCK2:
	PUSH	HL
	PUSH	AX
	CALL	!CHKRDY		; 書き込み中でないかチェック
	BC	$BUSYEXIT	; 書き込み中なら処理を中止
	MOVW	AX,SP		; 2つ目以降の引数を取り出す準備
	MOVW	HL,AX		; ポインタをHLレジスタに設定
	PUSH	BC
	CLR1	P2.3		; CSを立ち下げる
	MOV	A,#READC	; リード・コマンドをセット
	CALL	!PUTSPI		; コマンド転送
	MOV	A,[HL+1]	; EEPROMのアドレス上位を読み出す
	CALL	!PUTSPI		; アドレス転送
	BR	$READBLOCK	; 下位アドレス送信以降のデータ受信処理へ
(11)データの書き込み1
512バイト以下の容量のEEPROMに256バイト以下のデータを書き込みます。EEPROMのステータスを確認し、書き込み中でなければ、書き込み許可コマンドを発行します。書き込むアドレスが256番地を超える場合には、コマンドのビット3をセットしたライトコマンドを発行し、続いて、EEPROMのアドレスを1バイト転送します。以降は指定されたパラメータでの書き込み(実際は転送)を行ないます。指定されたデータの転送が完了するとCS信号をOFFにして、EEPROMに転送完了を通知します。EEPROMはステータス・レジスタのビット0を1にして実際の書き込み動作を開始します。このプログラムでは、書き込み完了を待つ処理は行いません。従って、転送が完了し、EEPROMが書き込みを行なっているときに別の処理を行なうことができます。
;
;	データの書き込み1
;
; <機能>
; 512バイト以下の容量のEEPROMに対して、引数として渡された
;パラメータで書き込みを行ないます。
; EEPROMが書き込み動作中でなければ指定された書き込みを実行し
;キャリー・フラグをクリアして戻ります。
; EEPROMが書き込み動作中なら、書き込みは行なわず、キャリー・
;フラグをセットして戻ります。
;
; <入力パラメータ(引数)>
; AX	: 第1の引数 :EEPROM内のアドレス
; SP+2,3: 第2の引数 :バッファ・メモリのアドレス
; SP+4  : 第3の引数 :書き込みデータ数
;
; <戻り値>
; CF	: 0 : 正常終了/ 1 : 書き込み動作中で処理中止
;
;bit _write_spi_block1(int reg_adr, unsigned char *data, unsigned char size)

__write_spi_block1:
WRITEBLOCK1:
	PUSH	HL
	PUSH	AX
	CALL	!CHKRDY		; 書き込み中でないかチェック
	BC	$EXITWRITE	; 書き込み中なら処理を中止
	MOVW	AX,SP		; 2つ目以降の引数を取り出す準備
	MOVW	HL,AX		; ポインタをHLレジスタに設定
	PUSH	BC
	CLR1	P2.3		; CSを立ち下げる
	MOV	A,[HL+1]	; EEPROMのアドレス上位を読み出す
	AND	A,#1		; 256バイト以上かのチェック
	ROL	A,1
	ROL	A,1
	ROL	A,1		; A8をビット3に移動
	OR	A,#WRITEC	; ライトコマンドを生成する
	CALL	!PUTSPI		; コマンド転送
WRITEBLOCK:
	MOV	A,[HL]		; アドレス下位を取り出す
	CALL	!PUTSPI		; アドレスを送信
	MOV	A,[HL+8]	; 転送データ数を取り出す
	MOV	B,A		; データ数を作業領域にコピー
	MOV	A,[HL+6]	; バッファ・アドレス下位を取り出す
	MOV	X,A
	MOV	A,[HL+7]	; 上位アドレスを取り出す。
	MOVW	HL,AX		; HLレジスタにアドレスを設定
;
;	データ送信処理
;
WRITELOOP:
	MOV	A,[HL]		; 送信データの読み出し
	MOV	X,A
	CALL	!PUTSPI		; データを送信
	INCW	HL		; ポインタを更新
	DBNZ	B,$WRITELOOP	; データ数分繰り返す。
	SET1	P2.3		; CSを解除
	POP	BC
	CLR1	CY		; エラー・フラグのクリア

EXITWRITE:
	POP	AX
	POP	HL
	RET
(12)データの書き込み2
1Kバイト以上の容量のEEPROMに256バイト以下のデータを書き込みます。EEPROMのアドレスが2バイトになるだけで、その後の処理はデータ書き込み1と同じです。
;
;	データの書き込み2
;
; <機能>
; 1Kバイト以上の容量のEEPROMに対して、引数として渡された
;パラメータで書き込みを行ないます。
; EEPROMが書き込み動作中でなければ指定された書き込みを実行し
;キャリー・フラグをクリアして戻ります。
; EEPROMが書き込み動作中なら、書き込みは行なわず、キャリー・
;フラグをセットして戻ります。
;
; <入力パラメータ(引数)>
; AX	: 第1の引数 :EEPROM内のアドレス
; SP+2,3: 第2の引数 :バッファ・メモリのアドレス
; SP+4  : 第3の引数 :書き込みデータ数
;
; <戻り値>
; CF	: 0 : 正常終了/ 1 : 書き込み動作中で処理中止
;
;bit _write_spi_block2(int reg_adr, unsigned char *data, unsigned char size)

__write_spi_block2:
WRITEBLOCK2:
	PUSH	HL
	PUSH	AX
	CALL	!CHKRDY		; 書き込み中でないかチェック
	BC	$BUSYEXIT	; 書き込み中なら処理を中止
	MOVW	AX,SP		; 2つ目以降の引数を取り出す準備
	MOVW	HL,AX		; ポインタをHLレジスタに設定
	PUSH	BC
	CLR1	P2.3		; CSを立ち下げる
	MOV	A,#WRITEC	; ライトコマンドをセット
	CALL	!PUTSPI		; コマンド転送
	MOV	A,[HL+1]	; アドレス上位を取り出す
	CALL	!PUTSPI		; 上位アドレスの転送
	BR	$WRITEBLOCK	; 下位アドレス以降の処理へ
(13)書き込み完了待ち
EEPROMのステータス・レジスタを読み出すことで、書き込み動作中かをチェックします。書き込みが完了していなければ、完了するまで確認処理を繰り返します。データ書き込み処理の後処理として使用します。
;
;	書き込み完了待ち
;
; <機能>
; EEPROMへのデータ転送後、CS信号が立ち上がると転送された
;データが実際に書き込みがおこなわれる。ここでは、完了するまで待つ。
;
; <入力パラメータ(引数)> なし
; <戻り値> なし
;
;void _waitwt(void)

__waitwt:
WAITWT:
	PUSH	BC		; レジスタをセーブ

WAITLOOP:
	CALL	!READST		; ステータス・レジスタのチェック
	MOV	A,C
	ROR	A,1		; 書き込み中フラグをキャリー・フラグへへ
	BC	$WAITLOOP	; 書き込み中ならループ
	POP	BC
	RET

[プログラム例の使用方法1]
上記のSPIの制御プログラム例をアセンブラ記述のプログラムから使用する方法の例を示します。

(1)宣言部
ここでは上で説明したプログラム例のサブルーチンを使用するための宣言を行ないます。また、データを格納するためのバッファ・メモリ領域も定義します。受信用はDS擬似命令で領域を確保し、送信用には固定データを準備しています。
;
;	 このプログラムはSPI制御ルーチンモジュールを使用して
;	EEPROMをアクセスする例を示します。
;
;	参照する制御サブルーチン
;
	EXTRN	WRITEENB	; 書き込み許可にする
	EXTRN	WRITEDIS	; 書き込み禁止にする
	EXTRN	READST		; ステータス・レジスタのリード
	EXTRN	WRITEST		; ステータス・レジスタへのライト
;
	EXTRN	READBLOCK1
		; 512バイト以下のEEPROMからのデータ・リード
	EXTRN	READBLOCK2
		; 1Kバイト以上のEEPROMからのデータ・リード
	EXTRN	WRITEBLOCK1
		; 512バイト以下のEEPROMへのデータ・ライト
	EXTRN	WRITEBLOCK2
		; 1Kバイト以上のEEPROMへのデータ・ライト
;
	EXTRN	WAITWT		; 書き込み完了待ち

;
;	作業領域の定義
;

	DSEG
RxBUFF1:				; 受信用データ・バッファ
	DS	16
RxBUFF2:
	DS	16
RxBUFF3:
	DS	16
;
;	送信テスト用データ
;
	CSEG
TxDATA1:
	DB	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
TxDATA2:
	DB	0,1,2,4,8,16,32,64,128,64,32,16,8,4,2,1
(2)読み出し処理
EEPROMからデータを読み出すには必要なパラメータをスタックやレジスタにセットしてREADBLOCK1(512バイト以下のEEPROMの場合)またはREADBLOCK2(1K〜64KバイトのEEPROMの場合)をサブルーチン・コールします。エラー(EEPROMが書き込み中)の場合にはキャリー・フラグがセットされて戻ってくるので、エラー処理に分岐させてください。
;
;	512バイト以下のEEPROMの読み出し例
;
RxTEST:
	MOVW	AX,#16			; 読み出しデータ数セット
	PUSH	AX
	MOVW	AX,#RxBUFF1		; バッファ・アドレスをセット
	PUSH	AX
	MOVW	AX,#33H			; EEPROM内部アドレス
	CALL	!READBLOCK1
	POP	AX
	POP	AX
	BC	$ERRORLOOP		; エラーならエラー処理へ
(3)書き込み処理
EEPROMにデータを書き込むには書き込みを許可状態にする必要があります。その後、必要なパラメータをスタックやレジスタにセットして、512バイト以下のEEPROMの場合にはWRITEBLOCK1を、1K〜64Kの場合にはWRITEBLOCK2をサブルーチン・コールします。サブルーチンから戻ってきた段階でエラーが発生していなければ、EEPROMは転送されたデータを実際に書き込んでいます。この間に必要に応じて、他の処理を行なってください。書き込みの完了はWAITWTをコールすることで、書き込み完了まで待ち合わせます。
	CALL	!WRITEENB		; 書き込み許可に
;
;	256〜512のEEPROMへの書き込み例
;
	MOVW	AX,#16			; データ数のセット(16バイト)
	PUSH	AX
	MOVW	AX,#TxDATA2		; バッファ・アドレスのセット
	PUSH	AX
	MOVW	AX,#0155H		; EEPROM内部アドレス
	CALL	!WRITEBLOCK1
	POP	AX
	POP	AX
	BC	$ERRORLOOP		; エラーならエラー処理へ

	ここに必要に応じて他の処理を入れる

	CALL	!WAITWT			; 書き込み完了待ち
[プログラム例の使用方法2]
ここでは、C言語記述での使用方法の例を示します。

(1)宣言部
ここでは上で説明したプログラム例(アセンブラ記述分)のサブルーチンを使用するための宣言を行ないます。
#pragma	SFR
extern void _writeenb(void);			// 書き込み許可設定
extern void _writedis(void);			// 書き込み禁止設定
extern unsigned char _readst(void);		// ステータス・レジスタの読み出し
extern void _writest(unsigned char st);	// ステータス・レジスタへの書き込み
extern bit _read_spi_block1(int reg_adr, unsigned char *data, unsigned char size);
// 512バイト以下のEEROMからの読み出し
extern bit _read_spi_block2(int reg_adr, unsigned char *data, unsigned char size);
// 1kバイト以上のEEROMからの読み出し
extern bit _write_spi_block1(int reg_adr, unsigned char *data, unsigned char size);
// 512バイト以下のEEROMへの書き込み
extern bit _write_spi_block2(int reg_adr, unsigned char *data, unsigned char size);
// 1kバイト以上のEEROMへの書き込み
extern void _waitwt(void);			// 転送データの書き込み完了を待つ
これ以外に、このファイル中にある関数のプロトタイプ宣言や読み出しデータ用のバッファ・メモリや固定データを書き込む際のデータ・パターンなどを宣言しています。
Void	hdwinit(void);
bit 	rxtest(void);
bit	txtest(void);
unsigned char	eep_read_buf1[16];	// read buffer
unsigned char	eep_read_buf2[16];	// read buffer
unsigned char	eep_read_buf3[16];	// read buffer

typedef unsigned char data16[16];
const data16 txdata1 = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
const data16 txdata2 = {0,1,2,4,8,16,32,64,128,64,32,16,8,4,2,1};
(2)読み出し処理
ここではステータス・レジスタの読み出しと、データの読み出しの例を示します。ここではrxtestとして関数の形にしてあり、制御プログラムでエラーが発生した場合にはそのままエラーをもって戻るようになっています。
この例では、1番のEEPROMを選択し、ステータス・レジスタの内容を読み出し、その後に、256番地未満のアドレス(0x33)と256番地以上のアドレス(0x1cc)から16バイトのデータを読み出し、その後EEPROMを切り替えて、512番地以上(0x33aa)のアドレスから読み出しています。
bit rxtest(void)
{
	unsigned char work;
	if(_selprom(1) == 1) return 1;
	work = _readst();
	if(_read_spi_block1(0x33, eep_read_buf1, 16)) return 1;

	if(_read_spi_block1(0x1cc, eep_read_buf2, 16)) return 1;

	if(_selprom(2) == 1) return 1;
	if(_read_spi_block2(0x33cc, eep_read_buf3, 16)) return 1;
}
(3)書き込み処理
書き込みについても関数の形にしてあります。対象とするEEPROMを選択した後に、書き込み許可状態にして、データの書き込みを行なっています。
bit	txtest(void)
{
	if(_selprom(1) == 1) return 1;
	_writeenb();                                            // 書き込み許可
	if(_write_spi_block1(0xaa, txdata1, 16))return 1;

//	ここに他の処理を入れてもよい

	_waitwt();
	if(_write_spi_block1(0x155, txdata2, 16))return 1;

//	ここに他の処理を入れてもよい

	_waitwt();
	if(_selprom(2) == 1) return 1;
	_writeenb();                                            // 書き込み許可
	if(_write_spi_block2(0x55aa, txdata1, 16))return 1;

//	ここに他の処理を入れてもよい

	_waitwt();
}

(2006/08)

この情報はお役にたちましたか?
back to top  
(2006/08)

EEPROM
-0004
CSIによるマイクロワイヤ(Microwire)メモリの制御(78K0/Kx2他)
[はじめに]
Microwireはナショナルセミコンダクタ社が提唱したマスタ/スレイブ方式のインタフェースで、基本的なデータの転送は2本のデータ(入力と出力)及びクロックの3本の信号を用いて行なうクロック同期式のシリアル通信方式です。これ以外に、チップ・セレクトとしてCSが使用され、合計4本で制御を行ないます。データは基本的に16ビットでやりとりされます。基本的にこの部分は78K0シリーズ他に搭載されたシリアル・インタフェース(CSI)と互換性があります。Microwireでは、データ以外に1ビットのスタート・ビットと2ビットのコマンドおよび、デバイスの容量によってビット長の異なるアドレスが使用されています。

[EEPROMとの接続]
MicrowireインタフェースをもつEEPROMとの接続例は以下のようになります。



EEPROMに対するチップ・セレクト信号はポートを用いて出力します。その他の信号は3線式シリアルの信号をそのまま使用します。なお、EEPROMにはこれ以外に書き込みを禁止するための(PREやPE)信号があるものもあります。ここではこれらの信号は使用しないので、それぞれGNDと電源に接続しておきます。

[信号のやり取りタイミング]
MicrowireインタフェースをもつEEPROMはCS信号がアクティブの状態で、シリアル・クロック(SK)の立下がりに同期して出力されたコマンドやデータを立ち上がりに同期して受け取ります。ところが、リードの場合にはSKの立ち上がりに同期してデータを出力するので、立下がりに同期して読み出す必要があります。これは、3線式シリアルやSPIとは異なる動作となるので注意が必要です。78KのCSIの場合には、送信(書き込み)方向ではタイプ4、受信(読み出し)方向ではタイプ3の通信フォーマットを使用します。



[スタート・ビットでの同期]
MicrowireインタフェースをもつEEPROMでは、その容量によってアドレスのビット数が異なります。そのため、アドレス転送までに必要なビット数がCSIのような8ビット固定では合わなくなります。そこで、スタート・ビットが定義されています。つまり、最初に受信した1のビットまではCSがアクティブになっていてもSKは無視されます。これを利用することで、全体の長さは8ビットになり、16ビットの倍数に合わせることができます。例えば、容量が256ワードの場合にはアドレスは8ビットになります。スタート・ビットとコマンドで3ビットですから、スタート・ビットの前に5ビットの0を付加すると全体で16ビットにすることができます。この例を下図に示します。



[EEPROMのコマンド]
EEPROMにはいくつかのコマンドが定義されており、最初にこれを用いて動作を指定する必要があります。デバイスによって、使用できるコマンドの種類が異なるようなので、コマンドの詳細は個々のデバイスのマニュアルを参照していただくとして、以下で簡単に説明します。

コード名 称動 作
00+00WDS書き込み禁止
00+01WRALL全空間に同じデータを書き込む
00+10ERAL全てのアドレスのデータを消去
00+11WEN書き込み許可
01WRITE指定されたアドレスに16ビットのデータを書き込む
10READ指定されたアドレスから順にデータを読み出す
11ERASE指定されたアドレスのデータを消去

WDS:デバイスへの書き込み禁止状態にします。コマンドが00で、アドレス部分の最初の2ビットが00のときにこのコマンドとなります。残りのアドレス部分は何でも構いません。
アドレスが8ビット時のスタート・ビット以降のビット・パターンを示します。

SI: 1 00 00xxxxxx

WRALL:デバイスの全てのアドレスに同じデータを書き込みます。コマンドが00で、アドレス部分の最初の2ビットが01のときにこのコマンドとなります。残りのアドレス部分は何でも構いません。
アドレスが8ビット時のスタート・ビット以降のビット・パターンを示します。

SI: 1 00 01xxxxxx D15〜D0

ERAL:デバイスの全てのアドレスのデータをクリアします。コマンドが00で、アドレス部分の最初の2ビットが10のときにこのコマンドとなります。残りのアドレス部分は何でも構いません。
デバイスによってはない場合もあるようです。
アドレスが8ビット時のスタート・ビット以降のビット・パターンを示します。

SI: 1 00 10xxxxxx

WEN:デバイスへの書き込みを可能状態にします。電源立ち上げ時にはデバイスは書込み禁止状態になっているので、書き込みを行なう場合には、必ずこのコマンドで書き込みを許可する必要があります。コマンドが00で、アドレス部分の最初の2ビットが11のときにこのコマンドとなります。残りのアドレス部分は何でも構いません。
アドレスが8ビット時のスタート・ビット以降のビット・パターンを示します。

SI: 1 00 11xxxxxx

WRITE:EEPROMへデータを書き込みます。コマンドに続いて、書き込みたいメモリのアドレスを転送します。その後、指定されたアドレスへの書き込みデータ(16ビット)を転送します。転送が完了して(次のSKの立ち上がりより前に)CSをロウ・レベルにすることで、実際の書き込みを行ないます。書き込んでいる最中には、再度CSをハイ・レベルにして、DO端子を確認することで、書き込みを完了したかどうかを知ることができます。0なら書き込み中で1になったら書き込みは完了です。なお、書き込み完了を確認する際にはSIはロウ・レベルにする必要があるようです。
アドレスが8ビット時のスタート・ビット以降のビット・パターンを示します。

SI: 1 01 A7〜A0 D15〜D0

READ:EEPROMからデータを読み出します。コマンドに続いて、アドレスを転送することで、その後のSKの立ち上がりで、指定されたアドレスの内容を出力します。引き続いてSKを入力することで、次のアドレスの内容を読み出すことができます。CSをロウ・レベルにすることで読み出しは完了となります。
アドレスが8ビット時のスタート・ビット以降のビット・パターンを示します。

SI: 1 10 A7〜A0

ERASE:EEPROMの指定したアドレスのデータをクリアします。このコマンドがないデバイスもあるようです。
アドレスが8ビット時のスタート・ビット以降のビット・パターンを示します。

SI: 1 11 A7〜A0

[78K0/Kx2での制御]
EEPROMは2.7V以上の電源電圧であれば、書き込みが可能で、シリアル・クロックはおよそ250kHzまでになります。そこで、78K0/Kx2を高速内蔵発振器の8MHzで動作させ、CSI10のクロックは125kHzを使用することにします。(クロック周波数の変動を考慮すると、250kHzのシリアル・クロックに対して250kHzの設定は問題があります。)
マイクロワイヤではデータとクロック(SK)の位相の関係で2つの状態があります。そのため、CSIの通信フォーマットを送信時と受信時で切り替える必要があります。そこで、送信時には78K0/Kx2のCSIの転送タイプ4を受信時にはタイプ3を使用します。なお、CSIM10はMSBファーストの送受信モードに設定して使用します。
EEPROMのアクセス・タイミング例を以下に示します。





CSI10を用いて接続する場合の接続例を示します。CSI10ではP10〜12の端子を使用するので、CS信号用に連続したP13を使用します。

具体的な制御プログラムについては「78K0/Kx2のCSIによるマイクロワイヤ・EEPROMの制御プログラム例」を参照してください。

[78K0S/Kx1+での制御]
78K0S/Kx1+にはCSI機能が内蔵されていないので、汎用ポートを用いてソフトウェアで制御します。P2を用いた場合の接続例を以下に示します。



具体的な制御プログラムについては「78K0S/Kx1+の汎用ポートによるマイクロワイヤ・EEPROMの制御プログラム例」を参照してください。

(2006/09)

この情報はお役にたちましたか?
back to top  
(2006/09)

EEPROM
-0005
78K0/Kx2のCSIによるマイクロワイヤ・EEPROMの制御プログラム例(78K0/Kx2)
[はじめに]
マイクロワイヤの概要やマイクロワイヤ・インタフェースのEEPROMについては「CSIによるマイクロワイヤメモリの制御」を参照してください。ここでは下記の接続例に示した場合に対応した具体的な制御プログラムについて説明します。また、制御プログラムの使い方についても簡単に触れておきます。



[78K0/Kx2の処理例]
78K0/Kx2でのEEPROMの制御処理は以下の部分から構成します。マイクロワイヤ方式では、それほどのスピードは要求されないことから、制御プログラムは全てC言語で記述します。制御関数は引数として、読み出しや書き込みでは以下のパラメータを用います。例えば、1ワード・データの読み出しでは第1引数で読み出すアドレスを指定します。1ワード・データの書き込みでは第1引数で書き込むアドレスを指定し、第2引数で書き込みデータを指定します。第3引数まで使用するのはブロック単位での読み書きの場合です。

 第1引数:EEPROMのアドレス
 第2引数:バッファ・メモリのアドレス/ワード書き込みのデータ
 第3引数:転送データ数で1〜255及び0(256バイト)

(1)初期化部
ポート、CSI10、割り込みの初期化を行ないます。ここでは2.7VPOCを使用することで、リセット解除後にはそのまま動作させます。基本的にベクタ割り込みは使用しないので、割り込みは禁止状態のままとします。

(2)EEPROMアドレス長選択処理
この制御プログラムでは、6ビット〜13ビットのアドレス長のEEPROMに対応できるようにアドレス長を指定する処理を付け加えてあります。これで指定したアドレス長に対応して以下で使用するコマンド及びアドレスは必要なだけ頭に0を追加して合計で16ビットになるようにします。

(3) 書き込み許可
EEPROMのCS信号をONにして、「WEN」コマンドを送ります。コマンド転送完了後CS信号をOFFにします。このコマンドによりEEPROMは書き込み可能状態になります。

(4)書き込み禁止
EEPROMのCS信号をONにして、「WDS」コマンドを送ります。コマンド転送完了後CS信号をOFFにします。このコマンドによりEEPROMは書き込み禁止状態になります。

(5) ワード・データの読み出し
第1引数で指定した(EEPROMの)アドレスから1ワードのデータを読み出し、戻り値で返します。

(6)ブロック・データ読み出し
第1引数で示した(EEPROMの)アドレスから第2の引数で示されたアドレスのバッファに第3の引数で示されたデータ数(ワード)のデータを読み出します。

(7)ワード・データ書き込み
第1引数で指定した(EEPROMの)アドレスに第2の引数で示されたワード・データを書き込みます。書き込み(転送)終了後にCSをOFFにするとEEPROMは実際の書き込みを開始します。実際に書き込みが完了するまでの待ち合わせは行いません。次にEEPROMに対して操作を行なう前には(9) 書き込み完了待ちを実行して実際の書き込みが完了したことを確認する必要があります。

(8)ブロック書き込み
第1引数で示した(EEPROMの)アドレスに第2の引数で示されたアドレスのバッファのデータを第3の引数で示されたデータ数(ワード)分書き込みます。EEPROMは1ワードの書き込みにしか対応していないので、ここでは、ワード・データの書き込みを必要な回数繰り返すことで必要な書き込みを行ないます。ワードごとに書込みコマンドを繰り返し発行する必要があるので、書込み完了待ちまで処理しています。

(9) 書き込み完了待ち
EEPROMは書き込みデータを転送後、CS信号をOFFすることで実際の書き込みを開始します。書き込みが完了したかどうかは再度CS信号をONにしてSO端子の状態をチェックしてハイ・レベルになることで確認できます。

(10) バイトデータ受信
CSI10を使って実際にEEPROMからバイトデータを受信します。(これは内部で使うだけです。)

(11) バイトデータ送信
CSI10を使ってEEPROMにコマンドやアドレス、バイトデータを送信します。(これは内部で使うだけです。)


[C言語でのプログラム例]
ここではC言語でプログラムを作成した場合のプログラム例を示します。

(0) 宣言及び定義部分
ここでは、関数のプロトタイプ宣言、EEPROMに対するコマンド(最も小さな6ビットのアドレスに対応した値)をディフォルト値として定義しています。また、第1引数のアドレス値をEEPROMのアドレスに丸めるためのマスクデータもビット長に応じて準備しています。
#pragma SFR
#pragma NOP

bit selrom(unsigned char leng);                 // アドレス長設定
void putmw(unsigned char data);                 // 1文字送信
unsigned char getmw(void);                      // 1文字受信
void writeenb(void);                            // 書き込み許可設定
void writedis(void);                            // 書き込み禁止設定
unsigned int read_mw(int reg_adr);              // ワード読み出し
void read_mw_block(int reg_adr, unsigned int *data, unsigned char size);
                                                // ブロック読み出し
void write_mw(int reg_adr, unsigned int data);  // ワード書き込み
void write_mw_block(int reg_adr, unsigned int *data, unsigned char size);
                                                // ブロック書き込み
void waitwt(void);                              // 書き込み完了待ち

/*------------------------------------------------------*/
/*                                                      */
/*      MW関連のコマンド定義                            */
/*                                                      */
/*------------------------------------------------------*/

#define READC   0b0000000110000000      // データ読み出し
#define WRITEC  0b0000000101000000      // データ書き込み
#define WENC    0b0000000100110000      // 書き込み許可
#define WDSC    0b0000000100000000      // 書き込み禁止

#define LENGTH  6                       // アドレスのビット長
#define Cssignal        P1.3            // CS信号の定義

static  unsigned char adrlen = LENGTH;  // アドレス長の保存用

typedef unsigned int mask[8];           // アドレス・マスクデータ
const mask mask1 = {0b0000000000111111,0b0000000001111111,
                    0b0000000011111111,0b0000000111111111,
                    0b0000001111111111,0b0000011111111111,
                    0b0000111111111111,0b0001111111111111};
(1) 初期化部
使用するポート及びCSIの初期化を行なう部分をhdwinit関数として記述した例を以下に示します。実際の通信を行なうときにCSIM10のビット7(CSIE10)をセットしてください。
Void    hdwinit(void)
{
        P1              = 0b11110011;           // 出力ラッチの設定
        PM1             = 0b00000010;           // SI10/P11以外は出力に
        CSIC10  = 0b00011101;                   // 
//                  |||||+++--------: シリアルクロックはfPRS/64
//                  |||++-----------: タイプ4
//                  +++-------------: 0に固定
        CSIM10  = 0b01000000;                   // MSBファースト、送受信モード
//                  ||+|++++--------; 0に固定
//                  || +------------; MSBファースト
//                  |+--------------; 送受信モード
//                  +---------------; 動作禁止
}
(2) EEPROMアドレス長選択処理
EEPROMのアドレス長を指定します。アドレス長は引数で指定し、6〜13ビットの範囲(これで、スタートビット〜アドレスを16ビットで処理できます)とします。この範囲以外はエラーとして処理します。ここでは単に変数に記録するだけです。
Bit     selrom(unsigned char length)
{
        if((length < 6) || (length > 13))       return 1;
        adrlen = length;
}
(3) 書き込み許可
CS信号をONして、アドレス長に合わせて「WEN」コマンドをシフトして頭の0の個数を調整し、EEPROMのコマンドを作成します。作成したコマンドを上位バイト、下位バイトの順で送信します。送信が完了したらCS信号をOFFして処理を終了します。
Void writeenb(void)
{
        unsigned int work;
        Cssignal = 1;                           // CS 信号をセット
        work = WENC << (adrlen-6);              // コマンドをデバイスに合わせる
        putmw(work / 0x100);                    // コマンドを転送
        putmw(work & 0x0ff);
        Cssignal = 0;                           // CS 信号をリセット
}
(4) 書き込み禁止
CS信号をONして、アドレス長に合わせて「WDS」コマンドをシフトして頭の0の個数を調整し、EEPROMのコマンドを作成します。作成したコマンドを上位バイト、下位バイトの順で送信します。送信が完了したらCS信号をOFFして処理を終了します。
Void writedis(void)
{
        unsigned int work;
        Cssignal = 1;                           // CS 信号をセット

        work = WDSC << (adrlen-6);              // コマンドをデバイスに合わせる
        putmw(work / 0x100);                    // コマンドを転送
        putmw(work & 0x0ff);

        Cssignal = 0;                           // CS 信号をリセット
}
(5) ワード・データの読み出し
引数として渡されたEEPROMのアドレスから必要な部分以外をマスクし、コマンドを必要なビットだけシフトさせてコマンド+アドレスを生成します。CS信号をONし、スタート・ビット〜アドレスを送信したら一旦CSIを停止します。動作モードをモード3に変更して再起動します。2バイトのデータを読み出したら、CS信号をOFFして通信モードを元に戻します。読み出した2バイトを結合してワードの戻り値とします。
Unsigned int read_mw(int reg_adr){
        unsigned int work;

        work = reg_adr & mask1[adrlen-6];       // アドレスの上位をマスク
        work |= (READC << (adrlen-6));          // コマンドを合成

        Cssignal = 1;                           // CS 信号をセット

        putmw(work / 0x100);                    // コマンドを転送
        putmw(work & 0x0ff);

        CSIE10 = 0;                             // CSIを動作停止
        CSIC10.3 = 0;                           // モード3を選択
        CSIE10 = 1;                             // CSI動作許可
        work = getmw();                         // 上位データの読み込み
        work = work << 8;                       // 上位にシフト
        work |= getmw() ;                       // 下位データの読み出し

        Cssignal = 0;                           // CS 信号をリセット

        CSIE10 = 0;                             // CSIを動作停止
        CSIC10.3 = 1;                           // モード4を選択
        CSIE10 = 1;                             // CSI動作許可

        return work;
}
(6