SPIモジュール(Serial Peripheral InterfaceModule)の使い方

【S08SPIV3】

SPIは8ビットシフトレジスタを使って、メモリーやコンバータなどと接続する事により、少ない配線で双方向同期通信を行うためのモジュールです。
二つのデバイス間をマスターとスレーブとして、マスターがクロックを発生してデータを送ったり、受けたりする事が出来ます。
標準CMOS ICのシフトレジスタ74HC595や74HC165とシリアル通信でデータのやり取りが出来ます。
8ビットバスなど多くのバスラインを必要とせず、最小2本で双方向通信する事も出来ます。
使用する端子は以下の4つです。

SPIの使い方として以下の方式が考えられます。各方式について解説して行きましょう。

【MOSI,MISOピンで入出力同時同期通信方式】

下図のように左側と右側でデータが同時に転送される方式です。

下図のように同じマイコンをそれぞれマスターとスレーブに設定して接続した例で解説します。

SPIでのデータの送受信はSPIxDレジスタにデータを代入するだけで、後は8ビットの送受信が完了するまで自動的に行われます。
送受信完了はそれぞれのフラグが用意されているので、フラグをチェックして知る事が出来ます。
送信完了をwhile文でSPI送信バッファー・エンプティー・フラグ(SPIS_SPTEF)がセットされるのを待つか、
または、割込み処理を用意して他のプログラムを実行しても構いません。
割込み処理は受信データレジスタSPIDの値を用意したレジスタに代入するだけです。下の例ではRX_BUFです。
SS端子はマスター側を設定した時点、つまりSPI制御レジスタのSPIC1_MSTRに”1”を代入した時点でLowになります。
例えば、Cソースで以下のようにSPIDレジスタにB3 hexを代入する記述をすると
SPID = 0xB3;     // S08QG QE SHシリーズの場合
while(SPIS_SPTEF) // 送信完了待ち
SPID = RX_BUF;   // 受信データをRX_BUFに格納
@1行目でSPIデータレジスタ(SPID)に8ビットデータ10110011がセットされます。
ASPIDレジスタからSPIシフトレジスタにデータが代入され、SPI送信バッファー・エンプティー・フラグ(SPIS_SPTEF)がクリアされます。
BデータのMSB(LSBに設定する事も出来る)がMOSI端子に現れます。今回の例では10110011の最上位の1が出力します。
 この時スレーブ側でも最初のデータがMISOに現われています。
Cクロックが定常状態LowからHiに変化します。(設定によりクロックの極性は逆にも設定できる)
DクロックがHiからLowに変化した時にスレーブ側のMOSIがラッチされ、MSBのデータ”1”が確定します。
B〜Dを8ビット分繰り返し、最後にSPI送信バッファー・エンプティー・フラグ(SPIS_SPTEF)がセットされます。
E8ビット分のデータを受信したので、SPIリードバッファ・フル・フラグがセットされます。
以上の動作を図で表すと以下になります。

【出力と入力を別々に行う同期通信方式】

下図はシフトレジスタ74HC595/74HC165を使った8ビットパラレル入出力回路例です。
74HC595は8ビットシリアル転送した後、SL端子をLowにするとA-Hにデータがパラレルに出力されます。
74HC595はA-Hの8ビットパラレルデータをSL端子をLowにするとシリアルバッファにコピーされるので、そのでーたを
シリアル転送して取り込む事が出来ます。SL端子制御するパルスをLoad Pulseと呼ぶ事もあります。
データの出力はSPIDレジスタに書き込む事で1バイトのデータ転送を行い、転送終了後PTA0 をLowにしてラッチします。
データを受信する時はPTA1をLowにしてシリアル側にデータをラッチしてから、SOIDにダミーデータを書き込みます。
クロックが1バイト分発生してSPIDレジスタに受信データが取り込まれますので、設定した変数レジスタにコピーします。

受信するだけでもクロック発生の為にSPIDにダミーデータを書き込む事がポイントとなります。
74HC595はSL端子がLowにならないとラッチしないのでダミーデータを送っても、ラッチする事は無く、前のデータを維持します。
クロックは送受信共用になります。

74HC165も595もシリアル端子はカスケードに接続できるので、直列に接続して何バイトでもシリアル転送する事が出来ます。
74HC165/595などの標準ロジックICの他にも、LEDドライバや電子ボリュームなどSPI入出力機能を持つデバイスは多数存在します。
各デバイスのデータシートを良く呼んで、通信を実現してください。

【MOSIピンのみで双方向同期通信方式】

SPIxC2レジスタのSPC0ビットを1にすると、双方向データ転送が行えます。
マスターではMOSIピン、スレーブならMISOピンが双方向通信に利用されます。
入出力の方向を決定するのは同じSPIxC2レジスタのBIDROEビットです。
このビットを1に設定すると出力、0に設定すれば入力になります。
SPIC2_SPC0 = 1;   // 双方向SPIデータ転送に設定
SPIC2_BIDIROE = 1; // SPI出力に設定
SPID = 0xB3;     // S08QG QE SHシリーズの場合
while(SPIS_SPTEF) // 送信完了待ち
SPIC2_BIDIROE = 1; // SPI入力に設定
SPID = 0x00;     // ダミーデータ送信
while(SPIS_SPTEF) // 送信完了待ち
SPID = RX_BUF;   // 受信データをRX_BUFに格納

【複数のマイコンがマスターになる同期通信方式】

SSピンをモードフォルト入力に設定する事で複数のマスターによる送受信が可能となる。
一つのマイコンがマスターとなった時点でSSピンがLowとなり、他のマイコンはMOSIの出力ドライバをディスエーブルします。

 SPI関連レジスタ

以下の5つのレジスタがSPI設定に関連します。SPIが複数あるマイコンではx部分に数値が入ります。
SPIが一つの場合、x部分は省略されます。

7 6 5 4 3 2 1 0
SPIxC1 SPIE SPE SPITE MSTR CPOL CPHA SSOE LSBFE
SPIxC2 - - - MODFEN BIDIROE - SPISWAI SPC0
SPIxBR - SPPR2 SPPR1 SPPR0 - SPR2 SPR1 SPR0
SPIxS SPRF - SPTEF MODF - - - -
SPIxD bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0



【SPIXC1】SPI制御レジスタ1(SPI Control Register 1)

7 6 5 4 3 2 1 0
SPIxC1 SPIE SPE SPTIE MSTR CPOL CPHA SSOE LSBFE
R/W R/W R/W R/W R/W R/W R/W R/W R/W
RESET 0 0 0 0 0 1 0 0
bit 7[SPIE]SPI割込みイネーブル(SPRFとMODF用)(SPI Interrupt Enable)
SPI受信バッファ・フル(SPRF)とモード・フォルト(MODF)のイベントに対する割込みイネーブルです。
0 = SPRFおよびMODF による割込みは禁止されます(ポーリングを使用します)。
1 = SPRFまたはMODF が1 なら、ハードウェア割込みを要求します。

記述例
/***** 初期設定 *****/
SPIC1_SPIE = 1;   // モードフォルト割込みを許可
bit 6[SPE]SPI システム・イネーブル(SPI System Enable)
SPIモジュールの有効/無効を選択します。
SPI をディセーブルにすると、処理中の転送が停止し、内部ステート・マシンが初期化されます。各ピンはI/Oポートとして利用されます。
0 = SPIシステムを停止します。
1 = SPIシステムをイネーブルします。
記述例
/***** 初期設定 *****/
SPIC1_SPE = 1;   // SPIシステムをイネーブルに設定
bit 5[SPITE]SPI 送信割込みイネーブル(SPI Transmit Interrupt Enable)
SPI 送信バッファ・エンプティ(SPTEF)に対する割込みイネーブル・ビットです。
0 = SPTEFによる割込みは禁止されます(ポーリングを使用します)。
1 = SPTEFが1 ならハードウェア割込みが要求されます。
記述例
/***** 初期設定 *****/
SPIC1_SPITE = 1;   // SPI送信完了で割込み発生を許可
bit 4[MSTR]マスタ/ スレーブ・モード選択(Master/Slave Mode Selec)
0 = SPIモジュールをスレーブSPI デバイスに設定します。
1 = SPIモジュールをマスタSPI デバイスに設定します。
記述例
/***** 初期設定 *****/
SPIC1_MSTR = 1;   // SPIをマスターに設定
bit 3[CPOL]クロック極性(Clock Polarity)
マスタSPI からのクロック信号またはスレーブSPI デバイスへのクロック信号に対して、このビットによりクロックの極性を選択します。
0 = SPIクロックの立上りでデータが変化します。クロックの立下りでデータをラッチします。アクティブHigh です(アイドルはLow)。
1 = SPIクロックの立下りでデータが変化します。クロックの立上りでデータをラッチします。アクティブLow です(アイドルはHigh)。
記述例
/***** 初期設定 *****/
SPIC1_CPOL = 0;   // SPIクロックはアイドル時Low(Hiアクティブ)に設定
bit 2[CPHA]クロック・フェーズ(Clock Phase)
さまざまな同期シリアル・ペリフェラル・デバイスで使用するクロック・フォーマットを2 つの中から選択します。
0 = SPSCKの最初のエッジは、8 サイクル・データ転送の最初のサイクルの中央で発生します。
1 = SPSCKの最初のエッジは、8 サイクル・データ転送の最初のサイクル先頭で発生します。
記述例
/***** 初期設定 *****/
SPIC1_CPHA = 1;   // SPIクロックは8 サイクル・データ転送の最初のサイクル先頭で発生
bit 1[SSOE]スレーブ選択出力イネーブル(Slave Select Output Enable)
このビットは、SPIxC2 のモード・フォルト・イネーブル(MODFEN)ビットおよびマスタ/ スレーブ(MSTR)制御ビットとの組み合わせにより、下表に示すSS ピンの機能を決定します。
MODFEN SSOE マスタモード スレーブモード
0 0 GPIO(SPIでは使用しない) スレーブ選択入力
0 1 GPIO(SPIでは使用しない) スレーブ選択入力
1 0 モードフォルト時のSS入力 スレーブ選択入力
1 1 自動SS 出力 スレーブ選択入力
bit 0[LSBFE]LSB 先頭(シフタの方向)(LSB First)
0 = SPIシリアル・データ転送は最上位ビットから開始します。
1
= SPIシリアル・データ転送は最下位ビットから開始します。
記述例
/***** 初期設定 *****/
SPIC1_LSBFE = 0;   // SPIはMSBファーストに設定

【SPIxC2】SPI 制御レジスタ2(SPI Control Register 2)

7 6 5 4 3 2 1 0
SPIxC2 --- --- --- MODFEN BIDIROE --- SPISWAI SPC0
R/W R R R R/W R/W R R/W R/W
RESET 0 0 0 0 0 0 0 0
bit 4[MODFEN]マスタ・モード・フォルト機能イネーブル(Master Mode-Fault Function Enable)
このビットは、SPI がスレーブ・モードに設定されていると意味がありません (SS ピンはスレーブ選択入力です)。 マスタ・モードでは、このビットでSS ピンの用途が決まります。
0 = モード・フォルト機能はディセーブルで、SS ピンは汎用I/O の機能に戻りSPI では制御されません。
1 = モード・フォルト機能はイネーブルで、SS ピンはモード・フォルト入力またはスレーブ選択出力として動作します。
記述例
/***** 初期設定 *****/
SPIC2_MODFEN = 1;   // SSピンはモードフォルト入力に設定
bit 3[BIDIROE]双方向モード出力イネーブル(Bidirectional Mode Output Enable)
SPI ピン制御0(SPC0)= 1 で双方向モードがイネーブルなら、このビットよってSPIデータ出力ドライバが双方向SPI I/O ピンに対してイネーブルかどうかが決まります。 対象となるピンは、SPI の設定がマスタならMOSI(MOMI)ピン、スレーブならMISO(SISO)ピンです。 SPC0 = 0 なら、このビットは意味がなく効果はありません。
0 = 出力ドライバはディセーブルで、SPI データI/O ピンは入力として動作します。
1 = SPI I/Oピンは出力としてイネーブルです。
記述例
/***** 初期設定 *****/
SPIC2_BIDIROE = 1;   // 双方向SPIピンは出力に設定
bit 1[SPISWAI]ウェイト・モードでのSPI 停止(SPI Stop in Wait Mode)
0 = SPIクロックは、ウェイト・モードで動作を継続します。
1 = SPIクロックは、MCU がウェイト・モードに移行すると停止します。
記述例
/***** 初期設定 *****/
SPIC2_SPISWAI = 1;   // SPIはウェイトモード時停止に設定
bit 0[SPC0]SPI ピン制御0(SPI Pin Control 0)
このビットは、シングルワイヤ双方向モードを選択します。 MSTR = 0(スレーブ・モード)なら、SPIは双方向SPI データ転送にMISO(SISO)ピンを使用します。 MSTR = 1(マスタ・モード)なら、SPI は双方向SPI データ転送にMOSI(MOMI)ピンを使用します。 SPC0 = 1 なら、双方向SPI I/O ピンに対する出力ドライバのイネーブルまたはディセーブルはBIDIROE で決まります。
0 = SPIは、データ入力とデータ出力で個別のピンを使用します。
1 = SPIは、シングルワイヤの双方向動作に設定されます。
記述例
/***** 初期設定 *****/
SPIC2_SPC0 = 1;   // SPIは双方向モードに設定

【SPIxBR】SPI ボーレート・レジスタ(SPI Baud Rate Register)

7 6 5 4 3 2 1 0
SPIxBR --- SPPR --- SPR
R/W R R/W R/W R/W R R/W R/W R/W
RESET 0 0 0 0 0 0 0 0
bit 6-4[SPPR]SPI ボーレート・プリスケール分周値(SPI Baud Rate Prescale Divisor)
この3 ビット・フィールドで、SPI ボーレート・プリスケーラに対する8 つの分周値の1 つを選択します(下表参照)。 このプリスケーラへの入力はバス・レート・クロック(BUSCLK)です。
このプリスケーラの出力で、SPI ボーレート分周器の入力がドライブされます。
記述例
/***** 初期設定 *****/
SPI1BR_SPPR = 4;   // SPIプリスケーラ分周値を4に設定
SPPR2:SPPR1:SPPR0 0:0:0 0:0:1 0:1:0 0:1:1 1:0:0 1:0:1 1:1:0 1:1:1
プリスケーラ分周値 1 2 3 4 5 6 7 8
bit 2-0[SPR]SPI ボーレート分周値(SPI Baud Rate Divisor)
この3 ビット・フィールドで、SPI ボーレート分周器に対する8 つの分周値の1 つを選択します(下表参照)。
この分周器への入力はSPI ボーレート・プリスケーラです。
この分周器の出力は、マスタ・モードのSPI ビット・レート・クロックです。
SPR2:SPR1:SPR0 0:0:0 0:0:1 0:1:0 0:1:1 1:0:0 1:0:1 1:1:0 1:1:1
レート分周値 2 4 8 16 32 64 128 256
記述例
/***** 初期設定 *****/
SPI1BR_SPR = 0;   // SPIレート分周値を2に設定

【SPIxS】SPI ステータス・レジスタ(SPI Status Register)

7 6 5 4 3 2 1 0
SPIxS SPRF --- SPTEF MODF --- --- --- ---
R/W R R R R R R R R
RESET 0 0 1 0 0 0 0 0
bit 7[SPRF]SPI リード・バッファ・フル・フラグ(SPI Read Buffer Full Flag)
このビットは、SPI 転送の完了時にセットされて、SPI データ・レジスタ(SPIxD)から受信データをリードできることを示します。
SPRF をクリアするには、セットされているSPRF をリードしてからSPI データ・レジスタをリードします。
0 = 受信データ・バッファには有効なデータはありません。
1 = 受信データ・バッファに有効なデータがあります。
記述例
/***** 受信処理 *****/
if (
SPI1S_SPRF)  // SPI受信フラグチェック
{
RX_DATA = SPI1D; // SPI受信データをRXレジスタに格納。同時にSPI受信フラグクリア
}
bit 5[SPTEF]SPI 送信バッファ・エンプティ・フラグ(SPI Transmit Buffer Empty Flag)
このビットは、送信データ・バッファに空き領域がある場合にセットされます。
クリアするには、SPTEF がセットされているときにSPIxS をリードして、SPIxD の送信バッファにデータ値をライトします。
SPIxS のリードは、SPTEF = 1 のときにSPIxD にデータをライトする前に行う必要があります。手順を誤るとSPIxDへのライトは無視されます。
SPIxC1 のSPTIE ビットも同時にセットされている場合は、SPTEF に基づいて割込み要求が生成されます。
SPTEF は、送信バッファから転送シフト・レジスタにデータが転送される際にも自動的にセットされます。
SPI がアイドル(送信バッファやシフト・レジスタにデータがなく処理中の転送もない)の場合、SPIxD にライトされるデータは即座にシフタに転送されてSPTEF が2 バス・サイクル以内にセットされるため、次の8 ビット・データ値を送信バッファにキュー登録できます。
シフト・レジスタにある値の転送が完了すると、キュー登録された値が送信バッファから自動的にシフタに転送され、SPTEF がセットされて、送信バッファに次のデータの空き領域があることが示されます。
送信バッファの空きを待っているデータがなければ、SPTEF はセットされたままで、バッファからシフタへのデータ転送は行われません。
0 SPI送信バッファはエンプティ(空き)ではありません。
1 SPI送信バッファはエンプティ(空き)です。
記述例
/***** 送信処理 *****/
if (
SPI1S_SPITEF)  // SPI送信バッファ空きフラグチェック
{
SPI1D = TX_DATA;  // SPIデータレジスタに格納。
}
bit 4[MODF]マスタ・モード・フォルト・フラグ(Master Mode Fault Flag)
このビットは、SPI がマスタに設定されているときにスレーブ選択入力がLow になり、他のSPI デバイスもマスタに設定されていることが指示されるとセットされます。
SS ピンは、MSTR = 1、MODFEN = 1、およびSSOE = 0 であるときにのみモード・フォルト・エラー入力として動作します。
それ以外でセットされることはありません。 MODF をクリアするには、MODF が1 であるときにリードしてからSPI 制御レジスタ1(SPIxC1)へのライトを行います。
0 = モード・フォルト・エラーはありません。
1 = モード・フォルト・エラーが検出されました。
記述例
/***** 受信チェック処理 *****/
if (
SPI1S_MODF)   // 他のデバイスの送信要求チェック
{
SPIC2_BIDIROE = 0; // 双方向SPIピンは入力に設定。
while(SPI1S_SPRF) // 受信待ち。
RX_DATA = SPI1D; // 受信データ格納。
}

【SPIxD】SPI データ・レジスタ(SPI Data Register)

7 6 5 4 3 2 1 0
SPIxD bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
R/W R/W R/W R/W R/W R/W R/W R/W R/W
RESET 0 0 0 0 0 0 0 0
bit 7-0[SPIxD]SPI データ・レジスタ(SPI Data Register)
このレジスタをリードすると、受信データ・バッファから読み込まれたデータが返ります。 このレジスタにライトすると、データは送信データ・バッファにライトされます。
SPI がマスタに設定されていれば、送信データ・バッファへのデータのライトによりSPI 送信が開始します。
送信データ・バッファへのデータのライトは、SPI 送信バッファ・エンプティ・フラグ(SPTEF)がセットされていて、送信バッファに次の送信バイトをキュー登録する空きがあることが示される場合以外は行わないでください。
SPIxD からのデータのリードは、SPRF がセットされた後で次の転送が完了する前ならいつでも可能です。
次の転送が完了する前に受信データ・バッファからのデータのリードを行わないと、受信オーバラン条件が発生して新たに転送されたデータは失われます。
記述例
/***** 送信処理 *****/
if (
SPI1S_SPITEF)  // SPI送信バッファ空きフラグチェック
{
SPI1D = TX_DATA;  // SPIデータレジスタに格納。

/***** 受信処理 *****/
if (
SPI1S_SPRF)  // SPI受信フラグチェック
{
RX_DATA = SPI1D; // SPI受信データをRXレジスタに格納。同時にSPI受信フラグクリア

}

TOP BACK NEXT