シリアル周辺装置インターフェース (Serial Peripheral Interface)
#include <spi.h>
用途 | 関数 | 説明 |
---|---|---|
オープン/クローズ | OpenSPIx | |
CloseSPIx | ||
送受信 | ReadSPIx (getcSPIx) | |
WriteSPIx (putcSPIx) | ||
getsSPIx | ||
putsSPIx | ||
ステータス | DataRdySPIx | |
割り込み | ConfigIntSPIx |
用途 | マクロ | 説明 |
---|---|---|
割り込み | EnableIntSPIx | |
DisableIntSPIx | ||
SetPriorityIntSPIx |
レジスタ | 説明 |
---|---|
SPIxCON | 制御レジスタ。モジュールの設定を行う |
SPIxSTAT | ステータス レジスタ |
SPIxBUF | 送受信バッファ レジスタ
(このアドレスはSPIxTXBとSPIxRXBの2つで共有される) |
SPIxSR※1 | シフト レジスタ。送受信のデータをシフトする(16ビット) |
区分 | 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 |
ピン | 説明 |
---|---|
SDIx (Serial Data Input) |
シリアルデータ入力 |
SDOx (Serial Data Output) |
シリアルデータ出力 |
SCKx (Shift ClocK) |
クロック出力またはクロック入力
(マスタならばクロック出力、スレーブならばクロック入力) |
SSx (Slave Select) |
スレーブ選択またはフレーム同期I/O |
SPIモジュールの動作 (マスターモード)
20.3.2.1 Master Mode (DS70067D)
- 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.
- The contents of SPIxTXB are moved to the shift register, SPIxSR, and the SPITBF bit is cleared by the module.
- 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.
- 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.
- 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.
- 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.
スレーブ選択 無効 |
スレーブ選択 有効 |
void OpenSPIx( unsigned int config1, // 制御レジスタ (SPIxCON) の値 unsigned int config2 // ステータス レジスタ (SPIxSTAT) の値 )
区分 | 定数 | 説明 |
---|---|---|
フレーム化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 |
区分 | 定数 | 説明 |
---|---|---|
モジュールの有効/無効 | SPI_ENABLE | SPIを有効 |
SPI_DISABLE | SPIを無効 | |
アイドルモード | SPI_IDLE_CON | アイドルモードでも動作を継続 |
SPI_IDLE_STOP | アイドルモードでは動作を停止 | |
受信オーバーフロー | SPI_RX_OVFLOW_CLR | 受信オーバーフローフラグをクリアする |
フレーム化SPIモードでは、SSピンを同期信号として送受信を開始します。このときSCKピンからは、つねにクロックを生成し続けます。
フレーム化SPIを使用しない通常モードではSSピンを使用せず、データを送受信するときのみSCKピンからクロックを生成します。
フレーム化SPI 無効 |
フレーム化SPI 有効 |
通信速度を決定するクロック周波数は、命令実行クロック (FCY) を基準に2つのプリスケーラの値から設定します。このときサポートされる周波数は、デバイスによって制限されることに留意する必要があります。たとえばdsPIC4012ではクロック周期が100ns以上※1でなくてはならないため、クロック周波数は10Mhz以下とします。
データは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 |
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 */