トップページ > 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ステータスレジスタのオーバーフロービットがクリアされます。