今回はエンコーダー、ジャイロ等の通信に欠かせない SPI 通信をやってみました。
概要
この通信方式は基本的に(多重をしない場合は)4線によって構成されます。規格が一部ガバガバで名前とかプロトコルが多少違う場合があるのですが、概ね以下のような感じになっています↓
線名 | 機能 |
---|---|
SS, SSEL, CS | このロジックによってマスタが送信相手を指定する |
MOSI, SDO | マスタからスレーブに送信されるデータ(Master Out Slave In) |
MISO, SDI | |
SCK | シリアルクロック。これによってデータがやり取りされる(Serial Clock) |
I2C と違って ACK 等が無いので単純な方式になっています。万が一 SPI インターフェイスがマイコンに実装されていなくとも、GPIO をシコシコ操作するだけでとても簡単に通信をすることが出来ます。例えば MSB First で送信する場合の擬似コードは以下のような感じです。
// 0b110をGPIOのみで送信してみる
set(PA0, low); // SSをLowにして通信開始
set(PA1, high); // PA1はMOSI ここにデータを書き込む 最上位の1
set(PA2, high); // PA2(クロック)を立ち上げてデータ送信
wait(); // ちょっと待機
set(PA2, low); // PA2(クロック)を下げる
wait(); // ちょっと待機
set(PA1, high); // 次の1
set(PA2, high); // PA2(クロック)を立ち上げてデータ送信
wait(); // ちょっと待機
set(PA2, low); // PA2(クロック)を下げる
wait(); // ちょっと待機
set(PA1, low); // 最下位の0
set(PA2, high); // PA2(クロック)を立ち上げてデータ送信
wait(); // ちょっと待機
set(PA2, low); // PA2(クロック)を下げる
wait(); // ちょっと待機
set(PA0, low); // SSをHighにして通信終了。スレーブを解放
さあ、今回はこんな原始的なことはせずにペリフェラルでサクッとやることにしますよ。今のコードは忘れてね。
実際の設定
リファレンスマニュアルですが、Rev 1 ではセクション番号 20 番にこの項目があります。
当ブログで使用している F303K8T6 は I2S が無いらしいのですが、まあ関係ないっすね。とりあえず説明をしていきます。どこを設定すればいいかというと案外多く、
- SPI へのクロック有効化
- ピン設定
- 自身はマスターかスレーブか
- 通信速度
- データ長(通信1回につき何bitか)
- 極性(High or Low)
です。
マスターかスレーブか
言っていませんでしたが、SPI とは常にマスターがスレーブに指示を出すという方式を取っています。マスターがデータを書き込む指示を出したらスレーブは従う、マスターがデータをよこせと言ったらスレーブはデータを送ってくるといった感じです。今回はマスターの設定にします。
通信速度
ペリフェラルの入力クロックと、通信相手(スレーブ)の仕様に合わせてあげます。相手のデータシート等に最大通信速度が書いてありますので、それを超えない程度にしてやってください。どこで設定するかというと、ここです。
「BR」の所を詳しく見てみると、、、
こうなっています。HCLK はペリフェラルの入力クロックで、これを分周することで大まかな調節をします。とりあえず無難に 256 分周しておきます。
データ長
こちらもガバガバで、マスタに合わせなければなりません。大抵 8bit か 16bit です。この設定項目は CR2 の DR にあります。
極性
きました。これがSPI やってて一番面倒くさいものです。なんてったってガバガバ規格ですから。これはつまりどういうことかというと...
- クロックの立ち上がり時にスレーブはデータを受け取るのか、立ち下がり時なのか
- CS は Low でスレーブを捕捉するのか、High なのか
- SCK は 1つ目のクロックからデータを扱うのか、2クロック目からなのか
...とまあこんなことも規定されていません。というか規格自体がデバイスに丸投げ状態です(多分)。リファレンスにもこんな感じで説明があるので是非ご一読を。
あ、あとついでに
- MSB First か LSB First か
これも規定されていません。つらいですね〜 ちなみにこの設定箇所は CR1 にあります。
コード全景
とりあえず送受信を含めてコードを提供します。極性等の理解は是非 SPI 通信と言うものを勉強してみてください。そのほうがやりやすいと思いますので。
マスタモードのみでのコード提供です。IO設定ですが、NSS という見慣れないものがあります。これは Slave Select 端子(SS or SSEL)です。