SPI (Serial Peripheral Interface)

シリアル周辺装置インターフェース (Serial Peripheral Interface)

ライブラリ

#include <spi.h>

関数、マクロ

関数

用途 関数 説明
オープン/クローズ OpenSPIx  
CloseSPIx  
送受信 ReadSPIx (getcSPIx)  
WriteSPIx (putcSPIx)  
getsSPIx  
putsSPIx  
ステータス DataRdySPIx  
割り込み ConfigIntSPIx  
dsPIC30F/dsPIC33F/PIC24H/dsPIC33E/PIC24E SPI Peripheral Module Library Help

マクロ

用途 マクロ 説明
割り込み EnableIntSPIx  
DisableIntSPIx  
SetPriorityIntSPIx  

レジスタ (Register)

レジスタ 説明
SPIxCON 制御レジスタ。モジュールの設定を行う
SPIxSTAT ステータス レジスタ
SPIxBUF 送受信バッファ レジスタ

(このアドレスはSPIxTXBとSPIxRXBの2つで共有される)

SPIxSR※1 シフト レジスタ。送受信のデータをシフトする(16ビット)
※1 SPIxSRレジスタへは、ユーザーが直接書き込むことはできません。すべての書き込みはSPIxBUFレジスタを介して行います。
区分 SFR名 アドレス Bit 15 Bit 14 Bit 13 Bit 12 Bit 11 Bit 10 Bit 9 Bit 8 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0 リセット後の値
SPIxCON
(制御)
SPI1CON 0222 - FRMEN SPIFSD - DISSDO MODE16 SMP CKE SSEN CKP MSTEN SPRE2 SPRE1 SPRE0 PPRE1 PPRE0 0000 0000 0000 0000
SPI2CON 0228 - FRMEN SPIFSD - DISSDO MODE16 SMP CKE SSEN CKP MSTEN SPRE2 SPRE1 SPRE0 PPRE1 PPRE0 0000 0000 0000 0000
SPIxSTAT
(ステータス)
SPI1STAT 0220 SPIEN - SPISIDL - - - - - - SPIROV - - - - SPITBF SPIRBF 0000 0000 0000 0000
SPI2STAT 0226 SPIEN - SPISIDL - - - - - - SPIROV - - - - SPITBF SPIRBF 0000 0000 0000 0000
SPIxBUF
(バッファ)
SPI1BUF 0224 Transmit and Receive Buffer Address shared by SPI1TXB and SPI1RXB registers 0000 0000 0000 0000
SPI2BUF 022A Transmit and Receive Buffer Address shared by SPI2TXB and SPI2RXB registers 0000 0000 0000 0000
Table 20-3: SPI1 Register Map (DS70067D)

ブロック図

ピン
ピン 説明
SDIx
(Serial Data Input)
シリアルデータ入力
SDOx
(Serial Data Output)
シリアルデータ出力
SCKx
(Shift ClocK)
クロック出力またはクロック入力

(マスタならばクロック出力、スレーブならばクロック入力)

SSx
(Slave Select)
スレーブ選択またはフレーム同期I/O

動作モード

マスター (Master)

SPIモジュールの動作 (マスターモード)

  1. Once the module is set up for Master mode of operation and enabled, data to be transmitted is written to the SPIxBUF register. The SPITBF (SPIxSTAT<1>) bit is set.
  2. The contents of SPIxTXB are moved to the shift register, SPIxSR, and the SPITBF bit is cleared by the module.
  3. A series of 8/16 clock pulses shifts out 8/16 bits of transmit data from the SPIxSR to the SDOx pin and simultaneously shifts in the data at the SDIx pin into the SPIxSR.
  4. When the transfer is complete, the following events will occur:
    • The interrupt flag bit, SPIxIF, is set. SPI interrupts can be enabled by setting the interrupt enable bit SPIxIE. The SPIxIF flagis not cleared automatically by the hardware.
    • Also, when the ongoing transmit and receive operation is completed, the contents of the SPIxSR are moved to the SPIxRXB register.
    • The SPIRBF (SPIxSTAT<0>) bit is set by the module, indicating that the receive buffer is full. Once the SPIxBUF register is read by the user code, the hardware clears the SPIRBF bit.
  5. If the SPIRBF bit is set (receive buffer isfull) when the SPI module needs to transfer data from SPIxSR to SPIxRXB, the module will set the SPIROV (SPIxSTAT<6>) bit, indicating an overflow condition.
  6. Data to be transmitted can be written to SPIxBUF by the user software at any time as long as the SPITBF (SPIxSTAT<1>) bit is clear. The write can occur while SPIxSR is shifting out the previously written data, allowing continuous transmission.
20.3.2.1 Master Mode (DS70067D)

スレーブ (Slave)


スレーブ選択 無効

スレーブ選択 有効

オープン、クローズ

オープン (OpenSPI)

void OpenSPIx(
  unsigned int config1,  // 制御レジスタ (SPIxCON) の値
  unsigned int config2   // ステータス レジスタ (SPIxSTAT) の値
  )
config1の定数 (SPIxCON)
区分 定数 説明
フレーム化SPI FRAME_ENABLE_ON フレーム化SPIを有効
FRAME_ENABLE_OFF フレーム化SPIを無効
フレームパルス方向 FRAME_SYNC_INPUT 入力 (スレーブ側)
FRAME_SYNC_OUTPUT 出力 (マスタ側)
SDOピンの用途 DISABLE_SDO_PIN 汎用I/O用
ENABLE_SDO_PIN SPI用
通信時のデータ幅 SPI_MODE16_ON Word (16ビット) 幅で通信
SPI_MODE16_OFF Byte (8ビット) 幅で通信
データ入力サンプルの位相 SPI_SMP_ON 出力時間の終了時に入力
SPI_SMP_OFF 出力時間の中間時に入力
(スレーブ モードではこちらを選択)
クロックエッジの選択 SPI_CKE_ON 出力データは、クロックがアクティブからアイドルへの変化で出力
(アクティブ、アイドル状態はクロック極性選択で定義される)
SPI_CKE_OFF 出力データは、クロックがアイドルからアクティブへの変化で出力
(フレーム化SPIモードでは、こちらを選択)
スレーブ選択 SLAVE_ENABLE_ON スレーブ選択を有効
SLAVE_ENABLE_OFF スレーブ選択を無効
クロック極性選択 CLK_POL_ACTIVE_LOW クロックがLowレベルでアクティブ状態、アイドル状態はその逆
CLK_POL_ACTIVE_HIGH クロックがHighレベルでアクティブ状態、アイドル状態はその逆
モード選択 MASTER_ENABLE_ON マスタ モード
MASTER_ENABLE_OFF スレーブ モード
第2プリスケーラ選択 SEC_PRESCAL_1_1 クロック周波数のプリスケーラ
SEC_PRESCAL_2_1
SEC_PRESCAL_3_1
SEC_PRESCAL_4_1
SEC_PRESCAL_5_1
SEC_PRESCAL_6_1
SEC_PRESCAL_7_1
SEC_PRESCAL_8_1
第1プリスケーラ選択 PRI_PRESCAL_1_1
PRI_PRESCAL_4_1
PRI_PRESCAL_16_1
PRI_PRESCAL_64_1
config2の定数 (SPIxSTAT)
区分 定数 説明
モジュールの有効/無効 SPI_ENABLE SPIを有効
SPI_DISABLE SPIを無効
アイドルモード SPI_IDLE_CON アイドルモードでも動作を継続
SPI_IDLE_STOP アイドルモードでは動作を停止
受信オーバーフロー SPI_RX_OVFLOW_CLR 受信オーバーフローフラグをクリアする

フレーム化SPIモード (Framed SPI Modes)

フレーム化SPIモードでは、SSピンを同期信号として送受信を開始します。このときSCKピンからは、つねにクロックを生成し続けます。

フレーム化SPIを使用しない通常モードではSSピンを使用せず、データを送受信するときのみSCKピンからクロックを生成します。


フレーム化SPI 無効

フレーム化SPI 有効

クロック周波数 (Clock Frequency)

通信速度を決定するクロック周波数は、命令実行クロック (FCY) を基準に2つのプリスケーラの値から設定します。このときサポートされる周波数は、デバイスによって制限されることに留意する必要があります。たとえばdsPIC4012ではクロック周期が100ns以上※1でなくてはならないため、クロック周波数は10Mhz以下とします。

クロック周波数 = FCY / ( 第1プリスケーラ × 第2プリスケーラ )

データは1クロックで1ビットの周期で伝送されるため、たとえばクロックが20MHzならば20Mbpsの通信速度となります。

※1 データシート DS70135C TABLE 24-32より
プリスケーラ値とクロック周波数の関係
FCY = 20,000kHz 第1プリスケーラ
1:1 4:1 16:1 64:1
第2プリスケーラ 1:1 20,000 5,000 1,250 313
2:1 10,000 2,500 625 156
3:1 6,667 1,667 417 104
4:1 5,000 1,250 313 78
5:1 4,000 1,000 250 63
6:1 3,333 833 208 52
7:1 2,857 714 179 45
8:1 2,500 625 156 39
※周波数の単位はkHz

クローズ (CloseSPI)

void CloseSPIx( void )

送受信

送信と受信では共通のバッファ (SPIxBUF) を使用するため、それぞれ同じバッファから読み書きします。送受信されるデータ幅は、SPIxCONの設定により1Byteまたは2Byteのいずれかです。

送信

バッファ (SPIxBUF) へデータを書き込みます。

void WriteSPIx( unsigned int data )

よって、

SPIxBUF = data;

としても同じことです。

送信の完了は、送信バッファの状態または割り込みで確認します。

連続した送信

void putsSPIx(
  unsigned int length,
  unsigned int *wrptr
  )

受信

受信バッファのオーバーフローが発生すると、それ以降の受信データはすべて破棄され、バッファ (SPIxBUF) には格納されなくなります。よってバッファから読み込むときには、先に受信オーバーフローフラグ (SPIxSTAT<SPIROV>) がセットされていないか確認する必要があります。なお受信オーバーフローフラグは、_SPIROVを取得することで確認できます。

バッファ (SPIxBUF) からデータを読み込みます。

unsigned int ReadSPIx( void )

これも送信と同様に、

unsigned int data = SPIxBUF;

のように、バッファからの読み込みに書き換えられます。ただし受信バッファがフルかどうかによって、この2つは別の結果を返します。SPIxBUFからの読み込みはつねにバッファの値を返しますが、ReadSPIxはバッファがフルではない場合0xFFFFを返します

連続した受信

unsigned int getsSPIx(
  unsigned int length,
  unsigned int *rdptr,
  unsigned int spi_data_wait
  )

バッファ ステータス

バッファフル ステータス
対象 関数 関与する変数
送信バッファ --- SPIxSTATbits.SPITBF
受信バッファ DataRdySPIx SPIxSTATbits.SPIRBF

送信バッファ

送信バッファフルステータスビット (SPIxSTAT<SPITBF>)で、送信バッファがフルかどうかを確認できます。

if( SPI1STATbits.SPITBF )
{
    // 送信バッファはフル
}
else
{
    // 送信バッファはフルではない
}

マクロが定義されているため、これは

if( _SPITBF )

のようにも記述できます。よって、

while( _SPITBF );

とすることで、送信の完了を待つことができます。しかし可能ならば、送信の完了は割り込みによって処理すべきです。

なおこのステータスビットは、バッファからシフトレジスタ (SPIxSR) へデータが転送されると、ハードウェアにより自動でクリアされます。

受信バッファ

char DataRdySPIx( void )

受信バッファにデータがあれば1が、さもなくば0が返されます。

この関数は、受信バッファフルステータスビット (SPIxSTAT<SPIRBF>) の状態を返すだけです。よって関数を呼び出さなくとも、

if( _SPIRBF )

としても同じです。

なおこのステータスビットはバッファからデータが読み込まれると、ハードウェアで自動的にクリアされます。

受信バッファ オーバーフロー

SPIモジュールが受信バッファにデータを転送しなければならないとき、受信バッファフルステータスビットがセットされていると、受信オーバーフローフラグがセットされます。このフラグは自動的にクリアされることはないため、明示的にクリアする必要があります。

受信オーバーフローフラグは、

_SPIROV = 0;

でクリアできます。

割り込み

マスタモードおよびスレーブモードとも、送信または受信が完了すると割り込みフラグ (SPIxIF) がセットされます。

受信オーバーフローフラグ (SPIxSTAT<SPIROV>) がセットされると、それ以降の受信データはすべて破棄され、受信による割り込みが発生しなくなります。

許可、禁止

機能 マクロ
割り込みを許可 EnableIntSPIx
割り込みを禁止 DisableIntSPIx
/* Macros to  Enable/Disable interrupts and set Interrupt priority of SPI1 in 22F*/
#define EnableIntSPI1                    _SPI1IE = 1
#define DisableIntSPI1                   _SPI1IE = 0

割り込み優先順位

#define SetPriorityIntSPI1(priority)     _SPI1IP = priority

設定

void ConfigIntSPIx( unsigned int config )
/* SPI Interrupt defines */
#define  SPI_INT_EN             0xffff  /* SPI Interrupt Enable     */
#define  SPI_INT_DIS            0xfff7  /* SPI Interrupt Disable    */

#define  SPI_INT_PRI_0          0xfff8  /* SPI Interrupt Prior Level_0 */
#define  SPI_INT_PRI_1          0xfff9  /* SPI Interrupt Prior Level_1 */
#define  SPI_INT_PRI_2          0xfffa  /* SPI Interrupt Prior Level_2 */
#define  SPI_INT_PRI_3          0xfffb  /* SPI Interrupt Prior Level_2 */
#define  SPI_INT_PRI_4          0xfffc  /* SPI Interrupt Prior Level_4 */
#define  SPI_INT_PRI_5          0xfffd  /* SPI Interrupt Prior Level_5 */
#define  SPI_INT_PRI_6          0xfffe  /* SPI Interrupt Prior Level_6 */
#define  SPI_INT_PRI_7          0xffff  /* SPI Interrupt Prior Level_7 */

参考

  • Section 20. Serial Peripheral Interface (SPI) (DS70067D)
  • dsPIC30Fファミリー リファレンスマニュアル (DS70046B_JP)
    20章「シリアル周辺装置インターフェース(SPI)」
  • セクション18. シリアル ペリフェラル インターフェイス(SPI) (DS70569C_JP)
    (dsPIC33E/PIC24Eファミリ リファレンス マニュアル)