トップページ 組込みソフト Raspberry SPI 制御コード
Raspberry SPI 制御コード                 2014/6/8
 Raspberry PiでSPIインターフェースを使うためのコードを公開します。SPIで何ができるか?
インターフェースがGND, MISO(SDO), MOSI(SDI), CE(CS), SPC(CLK)の5本の線で繋げばいいのでI2Cより2本多いです。
I2Cと同様にセンサーや、LCD、メモリなどがありいろいろ遊べます。
I2Cの通信速度は最大5Mb/です。しかし、SPIは未定義ですが、Raspberry PiにカラーグラフィックLCDを接続したときは18MHzで動作しました。未定義ということは、遅いのも速いのもありということです。
Raspberry Piで使えるSPIデバイスは2つまでです。
このコードのウリは、

SPIの使い方がわかりやすくなっています
Raspberry Piでの設定
SPIモジュール(spi-bcm2708)を「ブラックリスト」からを外しておくことが必要です。(SPIモジュールは前科者なのか?)
sudo vi /etc/modprobe.d/raspi-blacklist.conf
変更前
spi-bcm2708
変更後
#spi-bcm2708
#をつけてコメントにします。

sudo vi /etc/modules
spidev
を最後の行に付け加えます。


リブートします。
sudo reboot
これでSPIが動きます。
ダウンロード
ソースフィルはエクリプスでコンパイルして動作確認しています。
SPI.cpp
SPI.h
spi_app.cpp(サンプルプログラム)
使ってみたI2Cデバイス
大気圧センサー
秋月電子通商 LPS331使用 高精度大気圧センサーモジュール
I2Cで試したデバイスです。SPIでも使えます。
注意:
SDO(4番ピンを10kΩ)でプルアップしてください。これをやらなないとセンサーからの信号が取得できません。
SPIはI2Cにはないモードというのがある
SPIにはモードというのがあります。
モード CE信号 信号が取り込まれるときのクロックタイミング
通常L:動作時H Low->High
1 通常L:動作時H High->Low
2 通常H:動作時L High->Low
3 通常H:動作時L Low->High
これはオシロスコープで確認しました。間違っていたらゴメンです。
これを間違えると動作しません。センサーの添付資料には記載がありませんでした。わからないときは4つですので0から3まで試してください。
ちなみに大気圧センサーはモード3でした。
制御の仕方は2つある
ただデータを送るだけ
Raspberry PiにカラーグラフィックLCDを接続したときは、インターフェースがシフトレジスタだけだったのでデータの流れは、
Raspberry Pi ->LCD
だけです。
LCD->Raspberry Pi
はありません。
これ実装した関数は、
int WriteOnly(int len, char* lpOut)
です。

センサーに送って、受ける
センサーに、
温度のデータを要求(送信)
温度データを取得(受信)
というプロセスです。
これ実装した関数は、
int WriteRead(int len, char* lpOut, char* lpIn)
です。

もうひとつ受信だけをする
というのも考えられますが、それはないように思います。マスターとスレーブに分けられる場合、マスターが何か指令を出してスレーブが応答する。これが基本ですので、マスターが何もしないでただ待っているというのはなさそうです。
プログラムの解説
仕様書をみると次のようになっています。1バイト送信、1バイト受信のタイミングチャートです。

R/W:1 アドレス送信後、受信しろ
   0 アドレス送信後、送信しろ
MS: 0  1バイトだけ
   1  複数バイト
これではわかりにくいので実例を!
大気圧センサーは、レジスタ0x20に0x90を書き込まないと計測を開始しません。これはただ
データを送るだけ
です。

char buf[8], rx[8];
コードは、
buf[0] = 0x00 + 0x20;
buf[1] = 0x90;
spi.WriteOnly(2, buf);
となります。
オシロスコープの観測波形は

SPIはクロックです。16個のパルスになります。
SDIはセンサーから見て入力、マスターから見て出力になります。0x20の信号が観測されました。

SDOはセンサーから見て出力、マスターから見て入力です。同一値を出しているのか無応答なのか判別はできません。

次に1バイト受信です。
コードは、
buf[0] = 0x80 + 0x2b;
spi.WriteRead(2, buf, rx);
引数の2は次のようになります。
レジスタ指定て1バイト、センサーからの送信データで1バイト。合計2バイトということです。
l = rx[1];
rx[0]ではなくrx[1]に受信データがはいります。
rx[0]は0xffになるようです。
オシロスコープの観測波形は、

0x80 + 0x2b
の信号が観測されます。buf[1]は0にした結果なので、次の8ビットは0です。


最初SPC8ビット送信後に、センサーが温度の下位ビットを送信しているのが観測されます。

大気圧センサーは大気圧データが3バイトで構成させています。レジスタのアドレスも0x28から連続しています。
buf[0] = 0xc0 + 0x28;
buf[1] = 0x00;
spi.WriteRead(4, buf, rx);
MSのビットを1にしたので0xc0になっています。0x28から3バイトを取得します。
引数の4は次のようになります。
レジスタ指定て1バイト、センサーからの送信データで3バイト。合計4バイトということです。
オシロスコープの観測波形は、

クロックが4バイト出ています。

2バイト目からセンサーが気圧データを送ったのが観測できます。この値を計算すると986hPaになります。