トップページ > dsPIC入門 > dsPICでSPI通信(3)
それでは、2つのdsPICを組み合わせて簡単なSPI通信のプログラムを書いてみます。 ここではデバッグの基本として、何かアクションがあった場合に適当な文字列をUARTで PCへ送信することにします。
・・・という流れのプログラムをマスター、スレーブに分けて書いていきます。なお、dsPIC同士の通信ではなく 相手が何かのモジュールの場合はdsPICがマスターとなることが多いので、このマスター側プログラムだけを 書けばよいことになります。
これから書くプログラムのマスターはテストボード2(右)、 スレーブはテストボード1(左)です。 あまり重要ではありませんが、2つの回路ではLEDを光らせるポートが異なるので自分が忘れないために・・・(汗)
//********************************************************************
//SPIテスト(マスター) @dsPIC30F4012
//********************************************************************
//********************************************************************
//ヘッダファイル
#include "p30f4012.h"
#include "spi.h"
//********************************************************************
//コンフィギュレーション
_FOSC(CSW_FSCM_OFF & XT_PLL8);//10MHzセラロックを使っているのでクロックは80MHz。
_FWDT(WDT_OFF);
_FBORPOR(PBOR_ON & BORV_20 & PWRT_64 & MCLR_EN);
_FGS(CODE_PROT_OFF);
//********************************************************************
//SPIの設定パラメータ(マスター、送信有り、クロックは最も遅く設定)
unsigned int spi_config1 = FRAME_ENABLE_OFF & FRAME_SYNC_INPUT & ENABLE_SDO_PIN &
SPI_MODE16_OFF & SPI_SMP_ON & SPI_CKE_OFF & MASTER_ENABLE_ON &
CLK_POL_ACTIVE_LOW & PRI_PRESCAL_64_1 & SEC_PRESCAL_8_1 ;
unsigned int spi_config2 = SPI_ENABLE & SPI_IDLE_CON & SPI_RX_OVFLOW_CLR;
//********************************************************************
//メイン関数
int main(void)
{
//受信した文字を格納する変数
unsigned char temp;
//デバッグ用に、ポートEのLEDを使用します。
TRISE = 0x00;
PORTE = 0x00;
//-------------------------------------------------------------------
//SPI初期設定
OpenSPI1(spi_config1,spi_config2);
//もう一方の基板が受信待機状態になるまで、十分待ちます。
wait();
wait();
wait();
//-------------------------------------------------------------------
//'a'を送信
WriteSPI1('a');
//送信完了まで待つ
wait();
//'b'を送信
WriteSPI1('b');
//送信完了まで待つ
wait();
//'b'を送信
WriteSPI1('c');
//送信完了まで待つ
wait();
//-------------------------------------------------------------------
//デバッグ用。すべて文字を送信した時点でLEDを1つ点灯。
PORTE = 0x01;
//データが送られてくるまで待機
while(!DataRdySPI1());
//データが来たらLEDを2つ点灯。
PORTE = 0x03;
//1文字受信
temp = ReadSPI1();
//もし送られてきたデータが'd'なら・・・
if(temp == 'd')
{
//LEDをすべて点灯。
PORTE = 0xff;
//ここでストップ。
while(1);
}
}
//********************************************************************
//送信待ち関数(ただの時間稼ぎ・・・)
void wait(void)
{
unsigned long t;
for(t=0;t<10000;t++)
{
}
}
//********************************************************************
SPIモジュールを使うために、初期設定をする関数です。 引数は2つあります。1つ目の引数はSPI通信の各種設定について、2つ目の引数はSPIモジュールのハードウェア的な 設定についてです。毎度のことですが、最初に変数を宣言してやる場合、 マクロを入れる変数はunsigned int型となります。
「フレーム化」は、常にクロックを出し続けて“/SS”ピンを通信の同期信号として使う特殊なSPI通信です。 これをを使うかどうかを決めます。
もしSPI通信において常に受信動作しかしない場合は、出力ピンである“SDO”ピンを無効にすることができます。
いずれにせよ、マスター・スレーブ間で同じ設定にする必要があります。
SPI通信の同期クロックは、通常“H”レベルで信号出力ごとに“L”レベルへ落とす場合と、逆に 通常“L”レベルで信号出力ごとに“H”レベルへ上げる場合があります。どちらにするかは、 コンフィグによります。ここでは「アクティブ」と「非アクティブ」の間でどちらからどちらへ信号が変化した 場合に出力とするかを設定します。
SPIのクロックには、マイコンの設定クロックを4で割った値に、 第一プリスケーラの値と第二プリスケーラの値を掛け合わせた周波数が使われます。
このマクロを記述すると、SPIステータスレジスタのオーバーフロービットがクリアされます。