mwf_periph_spi - SPI
mwf_periph_spi - SPI
SPIバスを利用するためのクラスオブジェクトthe_spi1
を実装しています。
- SPI0 の対応コードは含まれません。
- 一部 non blocking (非ブロック) を想定した定義が含まれますが、現バージョンでは blocking (ブロック) の API のみ利用可能です。
コード例
#include "mwf_periph_spi.hpp"
void func_spi_init() {
if (!mwf::the_spi1) {
mwf::spi::global_init_spi1_manager();
Serial << crlf << "the_spi1 constructed.";
}
mwf::spi::config conf{};
conf.baud = 4000000UL; // 4MHz
conf.bits = 8; // 8bit
conf.dir = mwf::spi::E_SPI_DIR::MSB_FIRST;
conf.mode = mwf::spi::E_SPI_MODE::MODE_3_INV_RISE;
conf.pin_ssel[0] = mwf::spi::E_PIN_SSEL::SSEL0_PIO3;
conf.pin_ssel[1] = mwf::spi::E_PIN_SSEL::SSEL1_PIO16;
mwf::the_spi1->init(conf);
}
void func_spi_transfer() {
uint8_t tx[16] = { 0xa5, 0x5a, 0x11, 0x88 }; // data to transmit
uint8_t rx[16]; // receive buffer
mwf::the_spi1->ssel_select(0);
mwf::the_spi1->transfer_blocking(tx, rx, 4); // four bytes transfer
CLOCK_uDelay(5); // wait 5us
mwf::the_spi1->transfer_blocking(tx, rx, 4); // four bytes transfer
mwf::the_spi1->ssel_deselect();
}
class mwf::periph::spi
struct config
mwf::periph::spi::config
構造体は以下のように定義されています。
struct config {
// evaluated only in init()
E_PIN_MAIN pin_conf; // master pin configuration (so far not used)
E_PIN_SSEL pin_ssel[3]; // SSEL0..2 (assignment settings for slave select pins.
// At least pin_ssel[0] shall be configured.
// evaluated in conf(), reconf()
uint32_t baud; // SPI frequency (default 50Mhz)
E_SPI_DIR dir; // transfer LSB first
E_SPI_MODE mode; // SPI mode (clock polarity and detect edge)
uint8_t bits; // bit width (0:default=8, ...)
uint8_t ssel; // 0..3 or 0x80..0x80 (if MSB is set, assert/deassert SSEL automatically)
};
構造体に値を設定してinit()
を呼び出します。init()
中で構造体の設定値は内部的にコピーされますので、呼び出し後は構造体領域を破棄しても構いません。
構造体の各メンバーの解説です。
信号名 | 解説 |
---|---|
pin_conf | 使用するピン割り当て(主・副)の指定を行います。E_PIN_CONF::NODEF (=0)を選択した場合は global_init_spi1_manager() の指定を利用します。 |
pin_ssel[3] | SELECTピンを指定します。配列の0番目はSPI SELECTの0番目(SSEL0)のピン、1番目はSSEL1、2番目はSSEL2を指定します。SSEL0は必ず指定し SSEL1,2 は E_PIN_SSEL::SSEL_VOID=0 にしておきます。ピンを2種類利用する場合は SSEL0, SSEL1 を指定し、3種類の場合は全てに値を格納します。※ソフトウェア制御のピン( E_PIN_SSEL::SSEL0_PIO3 など )を指定した場合は、すべてのセレクトピンはソフトウェアによる制御を行います。ソフトウエア制御ではピンはHIGHレベルで常時出力設定となり、セレクト時に対象ピンが LOW レベルに変化します。なお、TWENETcmpt (AHIライブラリ互換) ではソフトウェア制御を用いています。※ハードウェア制御の場合 SELECT ピンの制御は fsl_spi.c の SPI_MasterTransferNonBlocking() の動作に倣います。 |
baud | SPIのクロック周波数を指定します。32Mhz まで設定可能ですがセンサーデバイスなどは 1Mhz 前後がよく使われます。 (動作は、fsl_spi.h の spi_master_config_t::bandRate_Bps , fsl_spi.c のSPI_MasterSetBaud() に倣います) |
mode | SPISELはinit() で指定します。 |
bits | 転送単位です。通常は8を指定します。1..16まで設定できます。9ビット以上の場合、データ転送時に指定するバイト配列は2バイト単位で読み出されるため、データ数の二倍必要で、1バイト目が LSB から 8ビット分2バイト目が 残りのビットを表現します。 (動作は、fsl_spi.hの SPI_MasterTransferBlocking() に倣います) |
ssel | SPIのSELECTです。0..2 を指定します。 |
enum class E_PIN_CONF
enum class E_PIN_CONF : uint8_t {
NODEF = 0, // 未指定
PRIMARY = 1, // 主割り当て (PIO10/11)
ALT = 2 // 副割り当て (PIO15/16)
};
// enum class と int 型の代入、比較等をするための型。
using wE_PIN_CONF = mwf::enum_wapper<E_PIN_CONF>;
ピン割り当てを指定するための列挙体です。
enum class E_PIN_SSEL
enum class E_PIN_SSEL : uint8_t {
SSEL_VOID = 0, // 未定義
SSEL_PRIMARY, // 主設定ピン
SSEL_ALT, // 副設定ピン
SSEL_SOFT = 0x10,
SSEL0_PIO3, // SSEL0 をソフトウェア制御し PIO3 を使用する
SSEL1_PIO16, // SSEL1 をソフトウェア制御し PIO16 を使用する
SSEL2_PIO17, // SSEL2 をソフトウェア制御し PIO17 を使用する
SSEL1_PIO4, // SSEL1 をソフトウェア制御し PIO4 を使用する
SSEL2_PIO13, // SSEL2 をソフトウェア制御し PIO13 を使用する
};
この列挙体はSPI SELECTピンの配置を決めます。spi::confg::pin_ssel[3]
に対応する値か保存されます。
利用デバイス数に応じて
pin_ssel[]
を設定します。- 1つの場合
pin_ssel[0]
を設定。pin_ssel[1]
,pin_ssel[2]
はSSEL_VOID
- 2つの場合
pin_ssel[0]
とpin_ssel[1]
を設定。pin_ssel[2]
はSSEL_VOID
。 - 3つの場合
pin_ssel[0]
,pin_ssel[1]
,pin_ssel[2]
を設定。
- 1つの場合
ハードウェア制御を指定する場合
SSEL_PRIMARY
またはSSEL_ALT
(およびSSEL_VOID
)を指定します。混在させた場合は、ソフトウェア制御となります。
enum class E_SPI_DIR
enum class E_SPI_DIR {
MSB_FIRST = 0,
LSB_FIRST
};
ビットの並び順を指定します。通常は MSB_FIRST
です。
enum class E_SPI_MODE
enum class E_SPI_MODE {
MODE_0_RISE = 0,
MODE_1_FALL = 1,
MODE_2_INV_FALL = 2,
MODE_3_INV_RISE = 3,
};
SPI転送モードの指定です。クロックの判定エッジと、その時の H/L の値を 0 とするか 1 とするかを決めます。接続デバイスのデータシートに従い設定します。
global_init_spi1_manager(), global_deinit_spi1_manager()
static void global_init_spi1_manager(E_PIN_MAIN pin_conf = E_PIN_MAIN::PRIMARY);
static void global_deinit_spi1_manager();
SPI1のバスを利用するためのクラスオブジェクトの生成と破棄を行います。クラスオブジェクト生成時にpin_conf
により利用するためのピンの組み合わせを選択します。ピン設定の指定は E_PIN_MAIN::PRIMARY 値:0
及びE_PIN_MAIN::ALT 値:1
を指定できます。
init()
void init();
void init(spi::config& cnf);
void init(spi::config&& cnf);
SPIバスを初期化します。パラメータcnf
を与えることでいくつかの設定を行います。パラメータを省略した場合は、以前の設定を用いて最初期化します。
- セレクトピンをユーザプログラムでソフトウェア制御する場合であっても、必ず1つは指定してください。指定されたピンはGPIOの出力として設定されます。
unset_ssel_auto()
を呼び出しておけば、当該ピンに対するライブラリによる制御は行われなくなります。
reconf()
void reconf();
ペリフェラルのパラメータを再反映します。内部設定にアクセスするには spi::config& get_conf()
を用います。この手続でピンの設定 (pin_ssel[]
)は反映されません。
set_data_width()
void set_data_width(uint8_t bits);
転送データ幅を変更します。reconf()
より軽い手続きです。
set|unset|get_ssel_auto()
void set_ssel_auto();
void unset_ssel_auto();
bool get_ssel_auto();
セレクトピンの自動制御フラグの設定、解除、取得。
- ソフトウェア制御を利用する場合のみ有効。
transfer_blocking()
呼び出し時に自動的にSELECTピンがLOWに制御され、終了時にSELECTピンがHIGHに設定される。
ssel_select()
void ssel_select(uint8_t select);
セレクトピンの指定を行います。select
は 0, 1, 2 の値をとり、各々 SSEL0..2 に対応します。
- ハードウェア制御、ソフトウェア制御で自動制御フラグ(
set_ssel_auto()
)設定時は、ピンの制御は転送API呼び出し時に行われる。 - ソフトウェア制御の場合は、自動制御フラグの有無に関係なく
ssel_select()
呼び出し直後に、SELECTピンがLOWに設定される。 - ハードウェア制御の場合は、
reconf()
を呼び出し再初期化します。この処理は処理時間のコストが大きいため、頻繁にデバイスを切り替えて転送を行う場合は、ソフトウエア制御を使用してください。
ssel_deselect()
void ssel_deselect();
セレクトピンの解除を行います。
- ソフトウェア制御の場合は、セレクトピンをすべて HIGH レベルに戻します。
- ハードウェア制御の場合は、なにもしません。
ssel_select()
でのピンの指定は変更しません。
その他
bool has_init(); // init() 実行済みであれば true を返す
spi::config& get_conf(); // 内部保存の設定情報にアクセスする
ピンの割り当て
E_PIN_CONF::PRIMARYの場合
信号名 | PIO番号 | 解説 |
---|---|---|
SCK | 0 | クロック信号 |
MOSI | 2 | SPIMOSIです。TWELITE 側が出力、外部SPIデバイス側が入力です。 |
MISO | 5 | SPIMISOです。TWELITE 側が入力、外部SPIデバイス側が出力です。 |
セレクトピン
pin_ssel | E_PIN_SSEL | PIO | 備考 |
---|---|---|---|
SSEL0 pin_ssel[0] | SSEL_PRIMARY | 3 | |
SSEL_ALT | 16 | ||
SSEL0_PIO3 | 3 | ソフトウェア制御 | |
SSEL0_PIO16 | 16 | ソフトウェア制御 | |
SSEL1 pin_ssel[1] | SSEL_PRIMARY | 4 | |
SSEL_ALT | 14 | ||
SSEL1_PIO4 | 4 | ソフトウェア制御 | |
SSEL1_PIO14 | 14 | ソフトウェア制御 | |
SSEL1_PIO16 | 16 | ソフトウェア制御(SSEL0_PIO16 の指定は不可) | |
SSEL_VOID | セレクトは SSEL0 のみとする | ||
SSEL2 pin_ssel[2] | SSEL_PRIMARY | 13 | |
SSEL2_PIO13 | 13 | ソフトウェア制御 | |
SSEL2_PIO17 | 17 | ソフトウェア制御 | |
SSEL_VOID | セレクトは SSEL0 SSEL1 の2つとする |
- セレクトは
SSEL0
から順にSSEL1
SSEL2
まで最大3種類設定できます。 pin_ssel[]
のいずれかの指定がソフトウェア制御の場合、セレクトピンは全てライブラリ中でソフトウェア制御を行います。
E_PIN_CONF::ALTの場合
信号名 | PIO番号 | 解説 |
---|---|---|
SCK | 15 | クロック信号 |
MOSI | 17 | SPIMOSIです。TWELITE 側が出力、外部SPIデバイス側が入力です。 |
MISO | 18 | SPIMISOです。TWELITE 側が入力、外部SPIデバイス側が出力です。 |
セレクトピン
pin_ssel | E_PIN_SSEL | PIO | 備考 |
---|---|---|---|
SSEL0 pin_ssel[0] | SSEL_PRIMARY | 16 | |
SSEL_ALT | 3 | ||
SSEL0_PIO3 | 3 | ソフトウェア制御 | |
SSEL0_PIO16 | 16 | ソフトウェア制御 | |
SSEL1 pin_ssel[1] | SSEL_PRIMARY | 14 | SSEL0の指定必須 |
SSEL_ALT | 4 | ||
SSEL1_PIO4 | 4 | ソフトウェア制御 | |
SSEL1_PIO14 | 14 | ソフトウェア制御 | |
SSEL_VOID | セレクトは SSEL0 のみとする | ||
SSEL2 pin_ssel[2] | SSEL_PRIMARY | 13 | |
SSEL_ALT | 5 | PRGピンでもあるので注意が必要。 | |
SSEL2_PIO5 | 5 | ソフトウェア制御。PRGピンでもあるので注意が必要。 | |
SSEL2_PIO13 | 13 | ソフトウェア制御 | |
SSEL_VOID | セレクトは SSEL0 SSEL1 の2つとする |
- セレクトは
SSEL0
から順にSSEL1
SSEL2
まで最大3種類設定できます。 pin_ssel[]
のいずれかの指定がソフトウェア制御の場合、セレクトピンは全てライブラリ中でソフトウェア制御を行います。
class mwf::periph::spi (sys_ev_handler)
on_sleep()
スリープ前の手続きとして、SPIを未使用状態に戻す。
init()
により初期化済みであればこれを保存しておく。
on_wakeup()
スリープ前に初期化状態であれば、SPI バスを利用できるように最初期化します。