前回はPIC16搭載のMSSPをSPIマスタとして使ってみました。今回はSPIスレーブとして使ってみます。ううむ誰かマスタになってくれる奴が必要なのだけれどどうしようか?今回は「とりあえずのテスト用」マスタからスレーブにデータが届いていることを確かめるだけ。あなた任せなだけにスレーブの方がちょっとメンドイです。
※『PIC三昧』PIC関係の記事総目次はこちら
※作業はMicroChip社の統合開発環境 MPLAB X IDEと、その上で走るコンフィギュレーションツールMCC Classic を使用して行っています。ターゲット・マイコンはPIC16F18855です。
MSSPをSPIスレーブとして設定
MSSP(Master Synchronous Serial Port)は、SPIとしてもI2Cとしても使用可能な周辺回路です。お名前にMasterとありますが、SPI、I2Cともにマスタでもスレーブでも担うことができる優れものです。
PIC16F18855にはMSSPが2個搭載されているので、そのうちのMSSP1を使用してみます。また、Printfを使いたいのでEUSARTを非同期シリアルとして使用します。同期、非同期そろい踏みっす。
まずMCC Classic のResourceの追加画面から。
MSSP1の設定画面が以下に。今回はスレーブなので、いつデータが到来するのか自分じゃ決められませぬ。そこでInterrupt Drivenにチェック。そしてSPI、モードはSlaveです。SPI Mode 0は、SCKの極性とサンプリングタイミングを制御するもの。前回やったとおり Mode 0 は、ノーマルLowで、立ち上がりエッジでサンプリングの筈。
EUSARTの設定が以下に。こちらも同期式シリアルにもなる周辺回路ですが、今回はUSBserialへ接続するのに非同期デス。STDIOとしてPrintfの宛先として使うので設定は以下のようにしてみました。
なお、毎度のことですが、MCC Classicが自動生成してくれるコードの中の関数がXC8コンパイラのデフォルト関数とバッティングします。その度に1か所コメントアウトしてます。トホホ。
ピン配は以下のとおり。信号的には前回同様ですが、SPIの立場がMasterからSlaveへと変わっているので、SPI関係の信号の方向が前回とは逆転してます。
ここまで設定して「Generate」ボタンを押せば、ソースファイルが一式生成されます。
SPIスレーブ、手抜きなテストプログラム
自前の割り込みハンドラを記述して、SPI用に生成されたAPIを使って設定しなおすのが正しい使い方のような気がします。しかしメンドイという理由で、自動生成あれた spi1.c 内のSPI1_Isr()関数を直接書き変えてしまいました。こんな感じ。
extern volatile uint8_t dat; void SPI1_Isr(void) { if(PIR3bits.SSP1IF == 1){ PIR3bits.SSP1IF= 0; } dat = SPI1_ReadByte(); }
なお、dat変数はmain.c 内で宣言した大域変数です。
一方、main.c内のmain()関数は以下のようにしてみました。
void main(void) { SYSTEM_Initialize(); INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); dat = 0; printf("SPI1 slave test.\n"); SPI1_Initialize(); SPI1_Open(0); while (1) { RA0 = 1; __delay_ms(1000); printf("DAT=0x%02x\n", dat); RA0 = 0; __delay_ms(1000); } }
PortAのビット0(RA0)にはLEDがつながっているので、ゆるゆるとLチカしつつ、そのときのdat変数の値を標準出力(USBシリアルに向いている)にたれ流すだけのコードです。多分、割り込みハンドラは忙しくdatへ書き込んでいるのに、そのほとんどは捨てられる運命。たまに巡ってくるタイミングのときのdatの値を表示するだけのきわめて手抜きなコードです。でもデータが「届いている」ことだけは分かるわいな~。
SPIマスタはAnalog Discovery2
さて、誰をSPIマスタにするかと考えたのですが、他のマイコンボードをプログラムするのもメントイし、ということで、困った時のDigilent社Analog Discovery2「万能ツール」のお出ましであります。AnalogといいつつDigitalパターンジェネレータを含んでいるので、以下のようにSCK(0), SDI(1)、SS(2)波形を定義してみます。なお、ロジアナ機能ではSPIとかI2Cとか自動でデコードしてくれる機能がありますが、パターンジェネレータでは特にそういうサービスはないようです。自前で書いていくっと。
実機動作確認
SPIスレーブとして動作するようにプログラムを書き込んだ評価ボードに、AD2の信号を接続したところが以下に。
上の方で設定したSPIマスタ(AD2)側のテストパターンを食わせているときの、STDIOへのprintf出力の様子が以下に。
期待どおりの0x57が到来しているようであります。マスタからスレーブにデータは届いているようね。
※別シリーズ記事にてESP32をSPIマスタとして使って上記プログラムの動作確認したものはこちら