Renesas Synergy™

FAQ 1006551 : 78K0S/Kx1+によるSPI・EEPROMの制御プログラム例(78K0S/Kx1+)

[はじめに]
SPIの概要やSPIインタフェースのEEPROMについては「FAQ 1006544 : 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();
}
他にご質問がございましたら、リクエストを送信してください