LoginSignup
1
1

More than 3 years have passed since last update.

ロジックアナライザを試すその4:ハードウェアSPIとソフトウェアSPI

Posted at

MCP3008でのハードウェアSPIとソフトウェアSPIの処理時間

A/DコンバータであるMCP3008を用いたハードウェアSPIとソフトウェアSPIの処理時間に差があることに気がついたので、ここに記録する。

ハードウェアSPIとソフトウェアSPI

こちらに説明あり。ハードウェアSPIは専用回路を用い、ソフトウェアSPIはGPIOを用いる。

環境

ロジックアナライザを試すその3(SPI)と同じ。ArduinoでA/DコンバータMCP3008と温度センサーMCP9700とを利用。

MCP3008データシート

ハードウェアSPI処理


MCP3008Datasheet_Hard.png
ハードウェアSPIでは8ビットをまとめて処理する、‘leading zeros’がきっかけとなっているらしい。これをもとにコーディングする(前回のソースコード参照

ソフトウェアSPI処理


MCP3008Datasheet_Soft.png
シリアルに1ビットずつ処理する。

ソースコード

ハードウェアSPI

前回と全く同じ。

#include <SPI.h>
#define SPI_CS 10
float Vref = 5.0 ;
SPISettings settings(1000000,MSBFIRST,SPI_MODE0);

void setup() {
  Serial.begin(9600);
  pinMode(SPI_CS, OUTPUT);
  SPI.begin();
}

void loop(){
  // SPI setting and write&read
  SPI.beginTransaction(settings);
  digitalWrite(SPI_CS, LOW);
  SPI.transfer(0b00000001);                 // Start bit 1
  byte highByte = SPI.transfer(0b10000000); // SingleEnd Channel 0
  byte lowByte = SPI.transfer(0x00);        // dummy
  digitalWrite(SPI_CS, HIGH);
  SPI.endTransaction();
  unsigned int dataCh0 = ((highByte & 0x03) << 8) + lowByte;

  // Conversion of read data according to MCP9700 spec
   float volts = dataCh0 * Vref / 1024;
  float temperature = (volts - 0.5) / 0.01; // : 500 mv at 0 degree and 10 mv / degree 
  Serial.println("dataCh0: " + String(dataCh0,HEX) + "  Voltage: " + String(volts,3));
  Serial.println("Temperature: " + String(temperature,2) + " degrees");
  Serial.println();
  delay(3000);
}

ソフトウェアSPI

こちらにあるものとほぼ同じ。

#include <SPI.h>
#define SPI_CS   7
#define SPI_MOSI 6
#define SPI_MISO 5
#define SPI_CLK  4
float Vref = 5.0;

void setup() {
  Serial.begin(9600);
  pinMode(SPI_CS, OUTPUT);
  pinMode(SPI_CLK, OUTPUT);
  pinMode(SPI_MOSI, OUTPUT);
  pinMode(SPI_MISO, INPUT);
  digitalWrite(SPI_CLK, LOW);
  digitalWrite(SPI_MOSI, LOW);
  digitalWrite(SPI_CS, HIGH);
}

void loop() {
  // SPI setting and write&read
  unsigned int outBuffer, inBuffer = 0;
  byte command = ((0x01 << 7) |        // Start bit
                  (1 << 6) |           // 1: SingleEnd
                  ((0 & 0x07) << 3));  // Channel 0
  digitalWrite(SPI_CS, LOW);
  outBuffer = command << 8;
  for (int c = 0; c < 16; c++) {
    digitalWrite(SPI_MOSI, (outBuffer >> (15 - c)) & 0x01);
    digitalWrite(SPI_CLK, HIGH);
    digitalWrite(SPI_CLK, LOW);
    inBuffer <<= 1;
    if (digitalRead(SPI_MISO))
      inBuffer |= 0x01;
  }
  digitalWrite(SPI_CS, HIGH);
  unsigned int dataCh0 = inBuffer & 0x3ff;

  // Conversion of read data according to MCP9700 spec
  float volts = dataCh0 * Vref / 1024;
  float temperature = (volts - 0.5) / 0.01; // : 500 mv at 0 degree and 10 mv / degree 
  Serial.println("dataCh0: " + String(dataCh0,HEX) + "  Voltage: " + String(volts,3));
  Serial.println("Temperature: " + String(temperature,2) + " degrees");
  Serial.println();
  delay(3000);
}

ロジックアナライザ

ハードウェアSPI

ソフトウェアSPI


所持するロジックアナライザのSPIデコードはハードウェアSPIを前提にしているようで、そのままではデコードできず。試しに、Clock polarityとClock phaseを適当に選ぶとデコードしてくれた。
SoftSPISetting.png

比較

どちらもMISOにらしいデータ('9c'および'9f'、変換後は26−27度)が見られる。ここでのポイントは処理速度。ロジックアナライザでの取得データの処理時間(赤枠)を見ると、
- ハードウェアSPI  26μs
- ソフトウェアSPI  340μs
となっている。これだけ差があるのは少々びっくり。

ソフトウェアSPIについては用いるマイコンなどの能力にも依存するのであろう。また、他のSPI対応デバイスでどんな結果となるかは不明。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1