SPI通信の仕様-Arduinoで波形を解析する

SPI通信の仕様_アイキャッチ画像 Arduino
スポンサーリンク

SPI通信は、マイコンと周辺部品の通信でよく使われるシリアル通信です。
ここでは、ArduinoとSDカードのSPI通信波形を実際に確認しながら、SPIの仕様についてまとめていきたいと思います。

こんな人にオススメ
  • SPI通信について具体的なイメージを持っていない
  • SDカードの通信仕様をみてみたい

この記事で使うシステムについては以下の記事でご紹介しています。
実際に作ってみたいという方は、是非一読していただけるとうれしいです!

ArduinoでCO2センサーの値をLCDに表示する
Arduinoを使って、CO2センサーから取った数値をLCDに表示するプログラムを作りたいと思います。 CO2センサーとLCD(液晶ディスプレイ)はI2C通信で接続をします。I2C通信はマイコンに対して複数の機器を同時に接続できる利点があり...
ArduinoでCO2センサーの値をSDカードに保存する
この記事は、前回ご紹介したArduinoでCO2センサーから取得した数値をLCDへ表示するスケッチの続きとなります。 今回は上記のシステムにSDカードを追加して、CO2センサーで取得した数値を同時にSDカードへ保存していくスケッチを作りたい...

準備するもの

この記事では、以下の物を使います。

●Arduino Uno

amazonのスイッチサイエンスから購入する純正のArduinoは、永久保証を受けることができます。
ブレッドボードや電子部品が付いてくるので、すぐに工作を始めることができます。

●LCDディスプレイ

16文字×2行を表示することができるLCDディスプレイです。
本来LCDディスプレイはパラレル信号を入力しないといけませんが、この商品はパラレル通信⇔I2C通信を変換してくれる回路が元から付いているので、I2C通信によるやりとりが可能です。

●CO2センサー

I2C通信で接続することができるCO2センサーです。
精度はそれほど信用できるものではありませんが、手軽にArduinoでCO2を計測することができます。

詳細な使い方は以下の公式HPで紹介されています。
https://wiki.keyestudio.com/KS0457_keyestudio_CCS811_Carbon_Dioxide_Air_Quality_Sensor

●マイクロSDカード シールド

SPI通信で接続することができるマイクロSDカードシールドです。
手軽にArduinoでSDカードとの連携をすることができます。

SDカードは3.3Vで動作しますがArduinoの電源は5Vなので、本来はそのまま接続するとSDカードが壊れてしまいます。
ですがこのシールドは5Vを3.3Vに変換するチップが付いているので、そのままArduinoと接続しても問題ありません。

●マイクロSDカード

一般的なマイクロSDカードです。

●ジャンパーワイヤー

LCDディスプレイやセンサーは端子がオスになっているので、各種ワイヤーを揃えておくと便利です。

●ロジックアナライザ

このロジックアナライザを使用すれば、UART、IIC、SPIなどのシリアル通信のデータを見ることができます。

●解析ソフト pluseview

上記のロジックアナライザのデータを見るために、pluseviewというフリーソフトを使用します。
以下のサイト様でインストール方法から使用方法まで詳細に説明されているので、参考にしてください。

データベースエラー

SPI通信とは

Serial Peripheral Interfaceの略でシリアル通信の一つです。
SCLK(クロック)、CS(チップセレクト)、MOSI(マスターアウト・スレーブイン)、MISO(マスターイン・スレーブアウト)の4つの通信線で通信する仕様で、I2Cと比べて高速で通信することができますが、通信線が多くなってしまう特徴があります。

I2Cと同様に、上記の通信線を共有して複数の周辺部品と通信することができます。
ただし、CSで通信したいマイコンを指定してからそのマイコンと通信を開始する仕様上、CSだけは周辺機器の数だけ通信線が必要になってしまいます。

SPI通信のシステム図

使用するスケッチ

ArduinoでCO2センサーから取得したデータを、SDカードに保存するスケッチを使用します。
ArduinoとSDカードの通信にSPI通信を使っているので、ここの通信を解析してみたいと思います。

スケッチの中で重要なところを抜粋してご紹介します。

const int chipSelect = 4;

ArduinoからSDカードへCS信号を出力するピンを4ピンに設定しています。

void loop() {
  delay(1000);
// append to the string
    dataString += String(sensor.getCO2PPM());
    dataString += ",";

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();

メインループの中で、CO2センサーからI2Cでデータを受け取ってSDカードに書きこんでいます。
メインループの先頭で1秒のディレイを入れているので、1秒ごとにこの処理が繰り返されます。

SPI通信の仕様

上記のスケッチを実際に動かして取得したSPIの通信データを見てみましょう。
以下がその通信データです。

スケッチ通りに1秒間隔でなにやら通信をしているのが分かります。

SPIの解析データ(全体)

一つの通信を拡大してみます。

SPIの通信波形

SDカードにCS信号を入力している間、SCLKのタイミングに合わせてMOSIとMISOでデータをやり取りしているのが分かります。

通信シーケンス

通信するときのシーケンスは以下の通りです。

チェック
  • マスターから通信をしたい部品に対してCS信号を入力
  • マスターからクロック信号を入力
  • MOSIもしくはMISOから8bitのデータを送受信
  • CS信号をOFFにして通信を終了

順番にSPIの仕様を見ていきたいと思います。

電圧

マイコンの電源電圧によって異なりますが、5Vや3.3Vがよく使われます。

CS(チップセレクト)

CSはプルアップされているので、何も通信をしていないときは常にHighの状態になっています。
マスターは通信したいスレーブに対してCS信号を出力(Low)します。
スレーブはCSにLowが入力されると通信動作を開始します。

CSはI2CやUARTでいうスタートビットの役割も果たしていますね。

チェック
  • 何も通信していないときはHigh
  • スレーブの数だけCSの通信線が必要
  • CSがLowになっている間、対象のスレーブと通信を行う

通信データの確認

チップセレクト信号

マスターからスレーブに対してCS信号が出力されているのが分かります。
CSがLowになるとSCLKやMOSI、MISOが動作を始めています。

このように電圧がHighのときを「0」「偽」の意味で使い、Lowのときを「1」「真」の意味で使うことを負論理(アクティブロー)といいます。

SCLK(クロック)

マスターはスレーブに対してCS信号を出力したあとに、クロック信号SCLKを出力します。
お互いにこのSCLK信号でタイミングを合わせて8bitデータを送受信します。

このようにクロックのタイミングに合わせて通信を行う方式を同期式通信といいます。

チェック
  • マスターから出力されるSCLK信号にタイミングを合わせて8bitデータを送受信する
  • SCLKの立ち上がり、もしくは立ち下がりのタイミングに合わせてMOSI、MISOがHighかLowかを判断する

通信データの確認

SCLK信号

マスターからスレーブに対してSCLK信号が出力されているのが分かります。
ここではクロックが立ち上がりのときに、MOSI、MISOの電圧がHighかLowかを読み取っていますね。

MOSI

マスターからスレーブに対してデータを送るときに使われます。
通信時に送られるデータは8ビットです。

チェック
  • マスターからスレーブに対してデータを送るときに使われる
  • 8bitのデータを送信する

通信データの確認

MOSI信号

マスターから8bitのMOSI信号が出力されているのが分かります。
MOSIも何も通信していないときはHighになっていますね。

まずArduinoがSDカードに対してCSとSCLKを出力し、次に「0xFF」を出力しています。
これは、SDにCSを出力してからSDカードの準備が整うまでの時間を稼いでいるようです。

次に「0x51」を出力しています。
SDカードと通信するには、決められたルールを守る必要があります。
「0x51」はSDカードのメモリを1ブロック分読みだすコマンドを意味します。

MSBで1bit目は必ずスタートビットで「0」、2bit目はマスターからスレーブへのコマンドであることを意味する「1」、そして1ブロック分読み込むことを意味するコマンド「010001」をつなげて「0x51」というデータになっているわけです。

SPIは定められているルールがシンプルな分、それを利用する部品側でルールをしっかり定めておく必要があります。

MISO

スレーブからマスターに対してデータを送るときに使われます。
通信時に送られるデータは8ビットです。

SPIはマスターからスレーブにデータを送るMOSIと、スレーブからマスターにデータを送るMISOが用意されています。
よって、お互いの好きな時にデータを送っても通信が衝突することはありません。
このような通信方式を全二重方式といいます。

チェック
  • スレーブからマスターに対してデータを送るときに使われる
  • 8bitのデータを送信する

通信データの確認

MISO信号

スレーブからマスターに対して8bitのデータ「0x00」を出力しているのが分かります。

これはSDカードと通信するときのルールで、マスターから送られたコマンドに対するレスポンスになります。スレーブからマスターに「0x00」を送ることでコマンドを問題なく受け取れたことを伝えています。

マスターから1ブロックを読みだすコマンド「0x51」が送られているので、ここから512Byteのデータがスレーブから送られてきます。

まとめ

ArduinoとSDカードで無事にSPI通信ができていることが確認できました。
複雑な通信シーケンスのI2Cと比べて、SPI通信はとてもシンプルですね。

SDカードへデータをやり取りするときは、CO2センサの1回分の値(数Byte)でも毎回1ブロック(512Byte)単位でやり取りをしていました。

書き込む対象のブロック512Byteを一度読みだして、対象の数Byteだけを書き換えてもう一度SDに戻すということをしているので、少し贅沢な通信の使い方ですね。
通信の効率を上げるためには、一度Arduinoの中で512Byte分のデータが溜まるのを待ってから通信を行うなど工夫が必要そうです。

この辺りの話は今回の趣旨とは異なりますので、また機会があればご紹介してみたいと思います。

Arduino
スポンサーリンク
tsubablog

メーカーで組み込みプログラマーとして勤務しているサラリーマンです。
プログラミングの楽しさについて発信しています。

業務で扱っている言語はC、C++です。

tsubablogをフォローする
つばブログ

コメント

タイトルとURLをコピーしました