/

SPI

SPIバス (コントローラ側) の読み書き
SPIバス (コントローラ側) の読み書きを行います。

注意事項

定数

定数意味
const uint8_t
SPI_CONF::MSBFIRST
MSB を先頭ビットにする
const uint8_t
SPI_CONF::LSBFIRST
LSB を先頭ビットにする
const uint8_t
SPI_CONF::SPI_MODE0
SPI MODE 0 に設定する
const uint8_t
SPI_CONF::SPI_MODE1
SPI MODE 1 に設定する
const uint8_t
SPI_CONF::SPI_MODE2
SPI MODE 2 に設定する
const uint8_t
SPI_CONF::SPI_MODE3
SPI MODE 3 に設定する

初期化と終了

SPIバスの利用手続きはbegin()メソッドによります。

begin()

void begin(uint8_t slave_select, SPISettings settings)
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)

ハードウェアの初期化を行います。

パラメータ解説
slave_select対象のペリフェラルのセレクトピンを指定する。0 : DIO19``1 : DIO0 (DIO 19 は予約されます)``2 : DIO1 (DIO 0,19 は予約されます)
settingsSPIのバス設定を指定します。

clock[hz]でSPIバスの周波数を指定します。指定した周波数に近いディバイザが選択されます。16Mhzまたは16Mhzを偶数で割った値になります。
bitOrderSPI_CONF::MSBFIRSTSPI_CONF::LSBFIRSTを指定します。
dataModeSPI_CONF::SPIMODE0..3を指定します。

void setup() {
  ...
  SPI.begin(0, SPISettings(2000000, SPI_CONF::MSBFIRST, SPI_CONF::SPI_MODE3));
  ...
}

void wakeip() {
  ...
  SPI.begin(0, SPISettings(2000000, SPI_CONF::MSBFIRST, SPI_CONF::SPI_MODE3));
  ...
}

end()

void end()

SPIのハードウェアの利用を終了します。

読み書き

読み書きの手続きは、以下の2種類あります。いずれかを選択して利用します。

使用例

次のサンプルコードは、Analog Devices の温度センサ ADT7310 から1秒おきに温度を取得し、シリアルポートへ出力します。

#include <TWELITE>
#include <SM_SIMPLE>

enum class STATE : uint8_t {
    INTERACTIVE = 255,
    INIT = 0,
    INIT_WAIT,
    SENSOR,
    LOOP_WAIT
};
SM_SIMPLE<STATE> step;

struct SensorData {
    uint8_t highByte;
    uint8_t lowByte;
    uint16_t rawValue;
    int32_t tempValue16th;
    div_result_i32 temperature;
} sensorData;

void setup() {
    step.setup(); // 状態マシンの初期化
}

void loop() {
    do {
        switch (step.state()) {
        case STATE::INIT: // 初期状態
            SPI.begin(0 /* DIO19をチップセレクトとして使用 */
                      , { 400000UL /* クロック周波数 */
                    , SPI_CONF::MSBFIRST
                    , SPI_CONF::SPI_MODE3
            }
                      );

            // ソフトウェアリセット
            SPI.beginTransaction();
            for (int i = 0; i < 4; i++) {
                SPI.transfer(0xFF);
            }
            SPI.endTransaction();

            // Continuous Readモード開始
            SPI.beginTransaction();
            SPI.transfer(0x54);
            SPI.endTransaction();

            step.set_timeout(300); // 待機時間の設定
            step.next(STATE::INIT_WAIT);
            break;

        case STATE::INIT_WAIT: // 待機
            if (step.is_timeout()) {
                step.next(STATE::SENSOR);
            }
            break;

        case STATE::SENSOR: // センサーデータの読み取り
            SPI.beginTransaction();
            sensorData.highByte = SPI.transfer(0x00);  // ダミーデータを送信してクロック信号を生成
            sensorData.lowByte = SPI.transfer(0x00);   // ダミーデータを送信してクロック信号を生成
            SPI.endTransaction();

            sensorData.rawValue = (((uint16_t)sensorData.highByte << 8) | sensorData.lowByte) >> 3;
            if (sensorData.rawValue & 0x1000) {
                sensorData.tempValue16th = int32_t(sensorData.rawValue) - 0x2000;
            } else {
                sensorData.tempValue16th = sensorData.rawValue;
            }

            // div100()を使用して温度計算
            sensorData.temperature = div100((sensorData.tempValue16th * 100) / 16);

            // 結果をシリアル出力
            Serial << crlf << sensorData.temperature.format() << "°C";

            step.set_timeout(1000); // 次のキャプチャまで待機
            step.next(STATE::LOOP_WAIT);
            break;

        case STATE::LOOP_WAIT: // 待機
            if (step.is_timeout()) {
                step.next(STATE::SENSOR);
            }
            break;

        default:
            break;
        }
    } while (step.b_more_loop());
}

ここでは、メンバ関数版のインタフェースを利用しています。


SPI (メンバ関数版)

SPI (メンバ関数を使用する方法)

SPI (ヘルパークラス版)

SPI (ヘルパークラスを使用する方法)