概要
SPI (Serial Peripheral Interface) は、マスター・スレーブ方式を採用するシリアル通信インターフェースの一種であり、主にマイコンとペリフェラル (周辺機器) 間の通信に使用される。
同期式通信で、マスターがクロック信号を生成する。
全二重 (双方向) 通信が可能であり、少ないピン数で高速なデータ通信を実現することができる。
SPIの主な特徴を以下に示す。
- マスター・スレーブ方式
- マスター・スレーブ方式を採用しており、通常1つのマスターデバイスが1つ以上のスレーブデバイスを制御する。
- 全二重通信
- 全二重通信が可能であり、マスターとスレーブが同時にデータを送受信できる。
- 3本以上の信号線
- SPIは、以下に示す信号線を使用する。
- SCLK (Serial Clock)
- マスターが生成するクロック信号
- MOSI (Master Output, Slave Input)
- マスターからスレーブへのデータ送信線
- MISO (Master Input, Slave Output)
- スレーブからマスターへのデータ送信線
- SS (Slave Select)
- マスターがスレーブを選択するための信号線
- SCLK (Serial Clock)
- デイジーチェーン接続
- 複数のスレーブを接続する場合、デイジーチェーン接続が可能である。
- これにより、マスターは最小限の信号線でスレーブを制御することができる。
- 高速通信
- SPIは比較的高速な通信が可能であり、一般的にはMHz単位のクロック周波数で動作する。
- 柔軟性
- SPIはクロック極性(CPOL)とクロック位相(CPHA)を設定できるため、様々なデバイスに対応可能です。
SPIは、EEPROM、フラッシュメモリ、センサ、ディスプレイ等、多様なペリフェラルとの通信に広く使用されている。
ただし、シンプルな構成と高速性が特徴であるが、デバイス数の増加に伴い信号線が増えるため、大規模なシステムには不向きな場合がある。
MSP430F149のSPI通信
MSP430F149のSPIモジュール
MSP430F149におけるSPIモジュールは、USART0またはUSART1 (Universal Synchronous/Asynchronous Receiver/Transmitter) を使用することにより、実現することができる。
MSP430F149では、USARTモジュールを同期モードで動作させることにより、SPI通信が可能になる。
MSP430F149は2つのUSARTモジュール (USART0とUSART1) を搭載しており、それぞれ独立してSPI通信に使用できる。
マイコンは、マスターおよびスレーブとして動作可能である。
データ長は7ビット、または、8ビットが選択可能である。
MSP430F149のSPIは、センサ、メモリ、ディスプレイ等の外部デバイスとの高速なデータ通信に適している。
適切な設定と通信プログラムにより、効率的なデータ交換が可能である。
SPI通信で使用する信号線
MSP430F149では、USART0またはUSART1をSPIモードで使用する場合、以下の信号線を使用する。
USART0を使用する場合のピン配置は以下の通りである。
- UCLK0 (Serial Clock) - P3.3
- マスターが生成するクロック信号
- SIMO0 (Slave In, Master Out) - P3.1
- マスターからスレーブへのデータ送信線 (MOSIに相当)
- SOMI0 (Slave Out, Master In) - P3.2
- スレーブからマスターへのデータ送信線 (MISOに相当)
- CS (Chip Select)
- スレーブを選択するための信号線 (任意のGPIOピンを使用可能)
USART1を使用する場合のピン配置は以下の通りである。
- UCLK1 (Serial Clock) - P5.3
- マスターが生成するクロック信号
- SIMO1 (Slave In, Master Out) - P5.1
- マスターからスレーブへのデータ送信線 (MOSIに相当)
- SOMI1 (Slave Out, Master In) - P5.2
- スレーブからマスターへのデータ送信線 (MISOに相当)
- CS (Chip Select)
- スレーブを選択するための信号線 (任意のGPIOピンを使用可能)
SPI通信の動作概要
まず、マスターがクロック信号を生成し、通信を開始する。
マスターとスレーブは、SIMOとSOMIを介して同時にデータを送受信する。
次に、マスターはCSを使用して通信するスレーブを選択する。
クロックの極性 (CPOL) と フェーズ (CPHA) は設定可能である。
SPI通信の設定手順
まず、SPIに使用するピンの機能を選択する必要がある。
MSP430F149では、ピンは複数の機能を持つことができるため、P3SELレジスタ (USART0の場合) または P5SELレジスタ (USART1の場合) を設定してSPI機能を有効化する。
次に、クロック源の選択とボーレートを設定する。
これにより、SPI通信の速度が決定される。
クロック源は通常SMCLKまたはACLKから選択し、ボーレートレジスタで分周比を設定する。
その後、SPIモード (マスター / スレーブ) を選択する。
マスターモードでは、マイコンがクロックを生成してスレーブデバイスを制御する。
スレーブモードでは、外部のマスターデバイスから送られるクロックに同期して動作する。
データ長、クロックの極性とフェーズの設定では、接続するスレーブデバイスの仕様に合わせる必要がある。
必要に応じて、割り込みを設定して、データの送受信完了時に自動的に処理を実行する。
最後に、マスターの場合は、CSピン (チップセレクト) を制御する必要がある。
CSピンは任意のGPIOピンを使用できるため、通信を開始する前にLowにして、通信終了後にHighにする。
- SPIに使用するピンの機能を選択する。
- (SIMO0 / SIMO1、SOMI0 / SOMI1、UCLK0 / UCLK1
- クロック源の選択とボーレートを設定する。
- SPIモード (マスター / スレーブ) を選択する。
- データ長、クロックの極性とフェーズを設定する。
- 必要に応じて、割り込みを設定する。
- マスターの場合は、CSピンを制御する。
サンプルコード : データの送信
以下の例では、MSP430F149がマスターとしてSPI通信を行い、スレーブデバイスにデータ (0x55) を繰り返し送信している。
まず、spi_init関数でSPIの初期化を行う。
これは、SPIに使用するピンの機能選択、クロック源の選択、ボーレートの設定、SPIモードの設定等を行う。
初期化の完了後、SPIモジュールが通信可能な状態になる。
メインループ内では、まず、CSピンをLowにしてスレーブを選択することにより、接続されているスレーブデバイスがこれから自分に対して通信が行われることを認識する。
次に、spi_send_byte関数を実行して、データ (例: 0x55) をスレーブに送信する。
送信バッファが空になるまで待機して、データを送信バッファに書き込む。
送信バッファにデータが書き込まれると、ハードウェアが自動的にSPI通信を実行する。
データの送信が完了した後、CSピンをHighにしてスレーブを解放する。
これにより、スレーブデバイスは通信が終了したことを認識する。
最後に、100ミリ秒の遅延を入れることにより、連続した通信の間に適切な間隔を設けている。
実際に使用するスレーブデバイスの種類や接続方法に応じて、適宜変更すること。
例えば、CSピンの番号、送信するデータの内容、遅延時間等を変更する。
#include <msp430.h>
// USART0をSPIモードで使用する場合のピン定義
#define SPI_UCLK_PIN BIT3 // P3.3 (UCLK0)
#define SPI_SIMO_PIN BIT1 // P3.1 (SIMO0)
#define SPI_SOMI_PIN BIT2 // P3.2 (SOMI0)
#define SPI_CS_PIN BIT0 // P3.0 (CS - 任意のGPIOピン)
void spi_init(void);
void spi_send_byte(unsigned char data);
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // ウォッチドッグタイマを停止
spi_init(); // SPIの初期化
while (1) {
P3OUT &= ~SPI_CS_PIN; // CSをLowにしてスレーブを選択
spi_send_byte(0x55); // データ (例: 0x55) を送信
P3OUT |= SPI_CS_PIN; // CSをHighにしてスレーブを解放
__delay_cycles(100000); // 100[ms]の遅延 (1MHzクロックを想定)
}
}
void spi_init(void)
{
// USART0をSPIモードで使用するためのピン設定
P3SEL |= SPI_UCLK_PIN | SPI_SIMO_PIN | SPI_SOMI_PIN; // SPI用のピンを選択
P3DIR |= SPI_CS_PIN; // CSピンを出力に設定
P3OUT |= SPI_CS_PIN; // CSをHighに設定 (スレーブ非選択状態)
// USART0の設定
U0CTL |= SWRST; // USART0をリセット状態にする
U0CTL |= CHAR | SYNC | MM; // 8ビット文字、同期モード、マスターモード
U0TCTL |= CKPH | SSEL1 | STC; // クロック位相、SMCLK選択、3線式SPI
U0BR0 = 0x02; // ボーレートを設定 (クロック分周比 = 2)
U0BR1 = 0x00; // ボーレート上位バイト
U0MCTL = 0x00; // 変調制御 (SPI通信では未使用)
ME1 |= USPIE0; // USART0 SPIモジュールを有効化
U0CTL &= ~SWRST; // USART0をリセット解除して動作開始
}
void spi_send_byte(unsigned char data)
{
while (!(IFG1 & U0TXIFG)); // 送信バッファが空になるまで待機
U0TXBUF = data; // データを送信バッファに書き込む
}
※注意
MSP430F149でUSART1を使用する場合は、U0CTL、U0TCTL、U0BR0、U0BR1、U0MCTL、U0TXBUF等のレジスタ名をU1CTL、U1TCTL、U1BR0、U1BR1、U1MCTL、U1TXBUF等に変更し、
ME1の代わりにME2を使用し、IFG1の代わりにIFG2を使用すること。
また、ピン設定もP5SELレジスタとP5.1、P5.2、P5.3ピンを使用すること。
サンプルコード : データの受信 (マスターデバイス側)
以下の例では、MSP430F149がマスターとしてSPI通信を行い、スレーブデバイスからデータを繰り返し受信している。
SPI通信の特徴として、全二重通信が可能であることが挙げられる。
つまり、マスターがクロックを生成している間、マスターとスレーブは同時にデータを送受信する。
したがって、データを受信するためには、マスターがダミーデータを送信してクロックを生成する必要がある。
まず、spi_init関数でSPIの初期化を行う。
これは、データ送信の場合と同様である。
初期化により、SPIモジュールが通信可能な状態になる。
メインループ内では、以下に示す処理を繰り返す。
まず、CSピンをLowにしてスレーブを選択する。
これにより、スレーブデバイスが通信を開始する準備をする。
次に、spi_receive_byte関数を実行して、スレーブからデータを受信する。
この関数では、まずダミーデータ (通常は0x00やOxFF) を送信バッファに書き込むことにより、クロックを生成する。
その後、受信バッファにデータが受信されるまで待機する。
受信が完了すると、受信バッファからデータを読み出して、変数received_dataに格納する。
データの受信が完了した後、CSピンをHighにしてスレーブを解放する。
最後に、100ミリ秒の遅延を入れて、次の受信まで適切な間隔を設ける。
受信したデータは、プログラム内で必要に応じて処理することができる。
例えば、センサからのデータであれば、値を解析して適切な処理を行うことができる。
実際に使用するスレーブデバイスの種類や接続方法に応じて、適宜変更すること。
#include <msp430.h>
// マクロ定義は、データ送信の場合と同様のため省略
void spi_init(void);
unsigned char spi_receive_byte(void);
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // ウォッチドッグタイマを停止
spi_init(); // SPIの初期化
unsigned char received_data;
while (1) {
P3OUT &= ~SPI_CS_PIN; // CSをLowにしてスレーブを選択
received_data = spi_receive_byte(); // データを受信
P3OUT |= SPI_CS_PIN; // CSをHighにしてスレーブを解放
// 受信したデータを処理
// 例: LEDの制御、データのログ保存、シリアル通信での出力等
// ...略
__delay_cycles(100000); // 100[ms]の遅延 (1MHzクロックを想定)
}
}
void spi_init(void)
{
// データ送信の場合と同様のため省略
// 上記の送信サンプルコードのspi_init関数を参照してください
}
unsigned char spi_receive_byte(void)
{
U0TXBUF = 0xFF; // ダミーデータを送信してクロックを生成
// (0x00でも可、スレーブの仕様に応じて選択)
while (!(IFG1 & U0RXIFG)); // 受信バッファにデータが入るまで待機
return U0RXBUF; // 受信バッファからデータを読み込んで返す
}
※注意
USART1を使用する場合は、レジスタ名を適切に変更すること。(U1TXBUF、U1RXBUF、IFG2等)
送信と受信で異なる設定が必要な場合
一般的に、SPIの初期化 (ピンの機能選択、クロック源の選択、ボーレートの設定、SPIモードの設定等) において、送信および受信で同じ設定を行う。
これは、SPI通信の性質上、送信と受信が同時に行われるためである。
しかし、特定のシナリオでは、送信用と受信用で異なる設定が必要になる場合がある。
以下に示すシナリオでは、送信用と受信用で異なる設定が必要になることがある。
そのため、SPIの初期化において、送信用と受信用に分けて実装する、または、送信と受信の切り替え時に動的に設定を変更する必要がある。
ただし、多くの場合、送信と受信で同じ設定を使用できるため、共通化することが一般的である。
異なる設定が必要な場合は、プログラム内で適切に制御レジスタを変更することで対応できる。
- クロックの位相 (CPHA) や 極性 (CPOL) が異なる場合
- スレーブデバイスによっては、クロックの位相や極性の要件が異なる場合がある。例えば、あるセンサは立ち上がりエッジでデータをサンプリングするのに対し、別のセンサは立ち下がりエッジでサンプリングする場合がある。
- 送信時と受信時で、クロックの位相や極性を変更する必要がある場合は、U0TCTLレジスタ (またはU1TCTL) のCKPHビットやCKPLビットを動的に変更する。
- このような変更は、マルチデバイス環境で複数の異なるSPIデバイスと通信する際に必要になることがある。
- ボーレート (通信速度) が送信時と受信時で異なる場合
- スレーブデバイスによっては、送信時と受信時でボーレートが異なる場合がある。
- 例えば、データを書き込む際は高速で行えるが、データを読み出す際は低速でしか動作しないデバイスが存在する。
- 送信時と受信時で異なるボーレートを使用する必要がある場合は、U0BR0およびU0BR1レジスタ (またはU1BR0、U1BR1) を動的に変更する。
- ただし、このような要件を持つデバイスは稀であり、通常は固定のボーレートで動作する。
- データ長が異なる場合
- スレーブデバイスによっては、送信時と受信時でデータ長が異なる場合がある。
- 例えば、コマンドは8ビットで送信するが、応答データは7ビットで受信する場合がある。
- 送信時と受信時で異なるデータ長を使用する必要がある場合は、U0CTLレジスタ (またはU1CTL) のCHARビットを動的に変更する。
- MSP430F149では、CHARビットを設定することで8ビットモード、クリアすることで7ビットモードになる。
- 送信と受信で異なるSPIモードを使用する場合
- マスターとスレーブの役割が固定されている場合は、送信と受信で同じSPIモードを使用できる。これが最も一般的な使用方法である。
- ただし、マスターとスレーブの役割が動的に切り替わる場合は、送信時と受信時で異なるSPIモードを使用する必要がある。この場合、U0CTLレジスタのMMビット (マスターモード) を動的に変更する。
- このような構成は、マルチマスター環境や、デバイス間で対等な通信を行う場合に使用される。
- 送信と受信で異なるチップセレクト (CS) ピンを使用する場合
- 複数のスレーブデバイスを接続する場合、送信先と受信先で異なるCSピンを使用することがある。
- 例えば、温度センサから読み取る際はCS1を使用し、フラッシュメモリに書き込む際はCS2を使用する場合がある。
- 送信時と受信時で異なるCSピンを使用する必要がある場合は、それぞれの通信の前後でGPIOピンの出力を適切に制御する。
- これは、プログラムロジックで管理する事項であり、SPIモジュールの設定とは独立している。
MSP430F149とMSP430G2553の主な違い
MSP430F149とMSP430G2553では、SPI通信に使用する通信モジュールが異なる。
この違いを理解することで、異なるMSP430マイコン間でのコード移植が容易になる。
- MSP430F149
- USART (Universal Synchronous/Asynchronous Receiver/Transmitter) モジュールを使用
- 2つのUSARTモジュール (USART0とUSART1) を搭載
- レジスタ名: U0CTL、U1CTL、U0TCTL、U1TCTL、U0TXBUF、U0RXBUF 等
- ピン配置: USART0の場合 P3.1 (SIMO0)、P3.2 (SOMI0)、P3.3 (UCLK0)
- ピン配置: USART1の場合 P5.1 (SIMO1)、P5.2 (SOMI1)、P5.3 (UCLK1)
- 割り込みフラグ: IFG1 (USART0)、IFG2 (USART1) のU0TXIFG、U0RXIFG等
- モジュール有効化: ME1 (USART0) またはME2 (USART1) レジスタのUSPIE0またはUSPIE1ビット
- MSP430G2553
- USCI (Universal Serial Communication Interface) モジュールを使用
- USCI_A0とUSCI_B0モジュールを搭載
- レジスタ名: UCB0CTL0、UCB0CTL1、UCB0TXBUF、UCB0RXBUF 等
- ピン配置: P1.5 (UCB0CLK)、P1.6 (UCB0SOMI)、P1.7 (UCB0SIMO)
- 割り込みフラグ: IFG2レジスタのUCB0TXIFG、UCB0RXIFG等
- 割り込みベクタ: USCIAB0TX_VECTOR、USCIAB0RX_VECTOR 等
MSP430F149でSPI通信を実装する場合は、データシートを参照して、適切なレジスタ設定とピン配置を確認することが重要である。
特に、使用するUSARTモジュール (USART0またはUSART1) によって、レジスタ名とピン配置が異なることに注意する必要がある。
また、USARTモジュールは同期モード (SPI) と非同期モード (UART) の両方をサポートしているため、U0CTLレジスタのSYNCビットを設定して同期モードを選択する必要がある。
これにより、USARTモジュールがSPI通信に適した動作を行う。