目次
- はじめに
- 1. NXP マイコンに搭載している Flexcomm について
- 2. FRDM-MCXN947 と FRDM-STBI-A8974 の回路情報
- 3. Pin / Clock Configuraiton Tool を使った Pin と Clock の設定方法
- 4. LPI2C Driver の有効化
- 5. Peripheral Configuraiton Tool を使った LPI2C の設定方法
- 6. Trasnfer モードの制御方法
- 7. [実機検証] FRDM-MCXN947 と FXLS8974 の通信テスト
- まとめ
はじめに
初心者ガイド 13 では I2C プロトコルを自由に構成する制御方法をご紹介しました。
今回はあらかじめ用意されている Transfer 関数を使用して LPI2C を制御する方法をご紹介します。
Transfer 関数にはポーリング処理の Blocking 関数と割り込みを使用する NonBlocking 関数があり、より簡単に制御処理を記述することができます。
NXP の加速度センサーである FXLS8974CF の評価ボード FRDM-STBI-A8974 を FRDM-MCXN947 の Arduinoポートに接続し、XYZ の3軸加速度情報を取得します。I2C の制御ソフトウェアは他のセンサーでも使用できる形にしていますので、自由にカスタマイズして活用ください。
評価ボードとはこのように接続します。
対象デバイス、この記事で使用する評価ボードとバージョンは下記のとおりです
対象デバイス:MCX、LPC、Kinetis、i.MXRT ファミリー
Hello World サンプルプロジェクト をベースに作成していきます。
下記コンテンツを参考に、Hello World サンプルプロジェクトを作成しておきましょう。
参考:[NXP マイコン初心者ガイド 1] MCUXpresso IDE でサンプルプロジェクトを作成する方法
I2C の概要はぜひこちらをご覧ください。
NXP から提供されている FXLS8974CF のサンプルソフトウェア と GUI Tool の使用方法はこちらをご覧ください。
参考:[NXP 加速度センサー初めてガイド 1] FXLS8974 のサンプルデザインを動かしてみた
1. NXP マイコンに搭載している Flexcomm について
Flexcomm は Low-Power Flexible Communications Interface の略称になります。
LPI2C, LPSPI, LPUART など汎用通信インターフェースとして設定が可能で、内部に FIFO を持っていおり、割込み、送受信DMA要求、トリガー出力などの機能を持っています。
マイコンにより搭載数は異なりますが、MCXN947 は10個搭載しています。
ポイント:Flexcomm はアプリケーションに応じて自由に I2C, SPI, UART の数をカスタマイズすることが可能です。
図1:MCXN LP_FLEXCOMM ブロック図 (MCXNx4xRM.pdf 抜粋)
外部 PIN の設定は順番が決まっており、例えば Flexcomm0 で I2C の SDA SCL を設定する場合、Flexcomm0_P0 が SDA、Flexcomm0_P1 が SCL となります。
図2:MCXN LP_FLEXCOMM Pin アサイン (MCXNx4xRM.pdf 抜粋)
2. FRDM-MCXN947 と FRDM-STBI-A8974 の回路情報
FRDM-STBI-A8974 の回路図は下記のとおりです。
- INTF_SEL と BT_MODE はマイコンから LOW を出力するために GPIO に接続します。
- I2C_SDA0 と I2C_SCL0 をマイコンの I2C に接続します。(抵抗でプルアップされています)
- I2C 切り替えジャンパーを 1:2 に設定します。
図3:FRDM-STBI-A8974 の回路図
FRDM-MCXN947 の回路図は下記のとおりです。
- P1_21 と P1_2 を INTF_SEL と BT_MODE に接続するために GPIO を設定します。
初期値として LOW を Output させておきます。 - P4_0 と P4_1 を I2C_SDA0 と I2C_SCL0 に接続するために LPI2C を設定します。Flexcomm2 を使用します。
図4:FRDM-MCXN947 の回路図
ポイント:回路図は評価ボードの NXP HP からダウンロード可能です。FRDM-STBI-A8974 の回路図、FRDM-MCXN947 の回路図
3. Pin / Clock Configuraiton Tool を使った Pin と Clock の設定方法
図5 の赤枠で囲った部分をクリックし、Configuration Tool を立ち上げます。
Pin Configuraiton Tool が起動します。
図5:Configuration Tool の表示方法
3-1 Pin の設定
先ほど確認した、P1_21 と P1_2 を GPIO、P4_0 と P4_1 を Flexcomm2 LPI2C に設定します。
Routing Detail タブは下記のようになります。
Label 列と Identifier 列に名前を設定します
GPIO の Direction を Output、GPIO initial state を Logic0 に設定します
I2C の Pull Up 設定を行います(今回はボード上で Pull Up されるため OFF にしてます)
ボードの構成に合わせて有効にしてください
図6:Pin Assign 後の Routing Detail の設定項目
ポイント:Label 列と Identifier 列を設定しておくことで、board/pin_mux.h に定義を追加してくれます
3-2 Clock の設定
Clock Configuraiton Tool に切り替えます。
右上のボタンから、Pins と Clocks を切り替えてください
図7:Pins と Clocks の切り替え
Clock Diagram を表示します。
FLEXCOMM2 clock の項目をスクロールして表示し該当箇所をクリック
右側に表示される Halt the Divider Counter の設定を Enable the Divider Counter に変更
FCCLKSEL2 を FRO 12 MHz clock に変更
FLEXCOMM3 clock を 12MHz に設定できれば有効化完了です
図8:Clock Diagram Flexcomm2 clock の設定変更
ポイント:この後行う Peripheral Configuraiton Tool の設定は Pin Clock の設定が反映される GUI 画面になっているため、ここで一旦 Update Code を実行してます
ポイント:GPIO の Clock 設定は Pin 設定を行うだけで有効になるため、Clock Configuration Tool での設定は必要ありません。
4. LPI2C Driver の有効化
Project Explorer 内で、下記箇所をクリックして、Manage SDK components を開きます。
LPI2C を検索し、有効化しておきます。
drivers フォルダーに、fsl_lpi2c.c と fsl_lpi2c.h が追加せれていれば完了です。
図10:Manage SDK components の起動
図11:LPI2C Driver の有効化
5. Peripheral Configuraiton Tool を使った LPI2C の設定方法
こちらのアイコンをクリックしてPeripheral Configuraiton Tool の画面を表示します。
有効化した後 + ボタンを押してペリフェラルの追加をしていきます。
ポップアップで LPI2C を検索して、選択し、OKを押します。
LP_FLEXCOMM の番号が異なっていると、最初エラーになりますので、合わせます。今回は LP_FLEXCOMM2 を選択します。自動的に Clock の設定も反映されます。
ボーレートの設定もこちらで変更可能です。
図12:Peripheral Configuraiton Tool の有効化
図13:LPI2C の選択
図14:LPI2C デフォルト時の画面
図15:LP_FLEXCOMM2 に変更し、ボーレートを 300000 Hz に変更後の画面
5-1. Transfer モードの設定方法
Transfer モードにするために、図16のように設定します。
変更点はこちらです。
- Mode を Transfer に変更
- Transfer Configuration の Transfer callback initialization を有効化
- Identifier に任意の割り込みハンドラ名を記載
- Initialization transfer structure を無効化
- Interrupt にて LP_FLEXCOMM2_IRQn を選択
図16:LPI2C_MasterTransferNonBlocking() の設定内容
ポイント:コールバック関数は LPI2C_MasterTransferNonBlocking() の送受信が完了したら割込みが発生します。そのとび先の関数となります。
ポイント:transfer structure は LPI2C_MasterTransferNonBlocking() や LPI2C_MasterTransferBlocking() を実行する前に都度送信設定を行う為、初期値で設定する必要はなく、無効化をしています。
設定が完了したら、を押してコードを生成します。
board/peripheral.c が生成され、Peripheral Configuraiton Tool で設定した内容を初期化する関数BOARD_InitBootPeripherals() が生成されます。
設定内容は LP_FLEXCOMM2_masterConfig 構造体に格納され、LP_FLEXCOMM2_master_handle が作成されています。LP_FLEXCOMM2_master_handle は LPI2C_MasterTransferNonBlocking() 内で必要となる各種変数を定義しています。
最終的に実行されるLPI2C_MasterInit() と LPI2C_MasterTransferCreateHandle() に引数を渡して、初期化処理が実行されるようになっています。
LPI2C_MasterTransferCreateHandle()には LP_FLEXCOMM2_master_handle と設定した Callback 関数も引数に渡されています。
BOARD_InitBootPeripherals() を main() の冒頭で実行するようにすることで、初期化は完了です。
図17:LPI2C_MasterTransferNonBlocking() 使用時の初期処理
6. Trasnfer モードの制御方法
Transfer モードは2つの転送関数があり、特徴は下記のとおりです。
- LPI2C_MasterTransferBlocking() 割込み未使用(ポーリング処理)
指定したデータサイズ分終わるまで待ち続けます:センサー向け - LPI2C_MasterTransferNonBlocking() 割込み使用
転送完了後割込みが発生する為、転送中他の処理を実施可能:メモリー向け
| 転送関数名 | 引数1 | 引数2 | 引数3 |
| LPI2C_MasterTransferBlocking() | LPI2C_Type *base | lpi2c_master_transfer_t *transfer | - |
| LPI2C_MasterTransferNonBlocking() | LPI2C_Type *base | lpi2c_master_handle_t *handle | lpi2c_master_transfer_t *transfer |
ポイント:LPI2C_Type *base は LPI2C のベースアドレスで、LP_FLEXCOMM2_PERIPHERAL などになります。
lpi2c_master_handle_t *handle は LPI2C_MasterTransferNonBlocking() で使用します。BOARD_InitBootPeripherals() の初期設定で既にグローバル変数で宣言済みであり、LP_FLEXCOMM2_master_handle を渡す形になります。
lpi2c_master_transfer_t *transfer は転送関数を実行前に I2C のコマンドに合わせて設定を変更する必要があり、下記のように設定します。
- I2C リードの場合
lpi2c_master_transfer_t mastertrasnfer; // lpi2c_master_transfer_t の変数を宣言
mastertrasnfer.flags = kLPI2C_TransferDefaultFlag; // Transfer 設定 Flag を設定
mastertrasnfer.slaveAddress = (uint16_t)slave_address; // I2C Slave デバイスのアドレスを設定
mastertrasnfer.direction = kLPI2C_Read; // Read を設定
mastertrasnfer.subaddress = reg_address; // I2C Slave のレジスターアドレスを設定
mastertrasnfer.subaddressSize = reg_address_size; // レジスターアドレスのサイズを設定
mastertrasnfer.data = rxBuff; // Read Buffer を設定
mastertrasnfer.dataSize = rxSize; // Read データサイズを設定- I2C ライトの場合
lpi2c_master_transfer_t mastertrasnfer; // lpi2c_master_transfer_t の変数を宣言
mastertrasnfer.flags = kLPI2C_TransferDefaultFlag; // Transfer 設定 Flag を設定
mastertrasnfer.slaveAddress = (uint16_t)slave_address; // I2C Slave デバイスのアドレスを設定
mastertrasnfer.direction = kLPI2C_Write; // Write を設定
mastertrasnfer.subaddress = reg_address; // I2C Slave のレジスターアドレスを設定
mastertrasnfer.subaddressSize = reg_address_size; // レジスターアドレスのサイズを設定
mastertrasnfer.data = txBuff; // Write Buffer を設定
mastertrasnfer.dataSize = txSize; // Write データサイズを設定そして、転送関数を下記のように実行します。
- LPI2C_MasterTransferBlocking() の場合
LPI2C_MasterTransferBlocking(base, &mastertrasnfer);- LPI2C_MasterTransferNonBlocking() の場合
LPI2C_MasterTransferNonBlocking(base, &LP_FLEXCOMM2_master_handle, &mastertrasnfer);実際に Read Wrtie 関数を作成するとこのようになります。
図18:LPI2C_MasterTransferBlocking() の場合の Read Write 関数例
図18の lpi2c_master_transfer_t 構造体の設定を変更することで、I2C スレーブのレジスターアドレスに自由に Read Write することができます。
6-1. LPI2C_MasterTransferNonBlocking() の割り込みハンドラについて
割込みを使用する LPI2C_MasterTransferNonBlocking() は 送受信の転送が完了すると設定した Callback 関数に飛ぶようになっています。
グローバル変数等で Flag を用意して置き、転送完了 CallBack が実施されたらアプリケーションに通知することができます。転送中マイコンは他の処理を実施できるため、メモリーなど大量のデータを転送する際に有益です。
作成した Read Write 関数では、グローバル変数で定義した g_MasterCompletionFlag が コールバック関数で True になるまで次に進まないようになっていますが、必要に応じてカスタマイズしてご使用ください。
図19:LPI2C_MasterTransferNonBlocking() の場合の Read Write 関数
7. [実機検証] FRDM-MCXN947 と FXLS8974 の通信テスト
FXLS8974 のサンプルソフトウェアは FRDM-MCXN947 のサンプルソフトウェアをインポートする際に、FXLS8974評価用の項目を選択後、fxls8974cf_poll を選択するとインポートが可能です。
fxls8974.h だけ今回使用します。source フォルーダにコピーしてください。
図20:FXLS8974 のサンプルソフトウェアのインポート
今回ご用意した main 関数は init_FXL8974() 実行後、xyz 軸のデータを取得して print 出力するコードです。
図21:main 関数
init_FXL8974() はセンサーの初期化処理を実施しており、下記処理を行っています。
- FXLS8974_WHO_AM_I = 0x13 を発行しデバイス ID を取得します
- FXLS8974_SENS_CONFIG1 = 0x15 のデータをリードし Standby mode に設定を変更します
- FXLS8974_SENS_CONFIG1 = 0x15 のデータをリードし ±2g; 0.98 mg/LSB (1024 LSB/g) nominal sensitivity に設定を変更します
- FXLS8974_SENS_CONFIG3 = 0x17 のデータをリードし WAKE_ODR_6_25Hz に設定を変更します
- FXLS8974_SENS_CONFIG1 = 0x15 のデータをリードし Active mode に設定を変更します
- FXLS8974_INT_STATUS = 0x00 のデータをリードし Output data-ready となっているか確認します
図22:init_FXL8974() 処理内容
ポイント:レジスターの詳細は FXLS8974CF, 3-Axis Low-g Accelerometer, data sheet をご覧ください
実際にデバッグをすると下記ログが出力されます。
hello world.
FXLS8974_WHO_AM_I = 0x86
FXLS8974_SENS_CONFIG1 Default = 0x1
FXLS8974_SENS_CONFIG3 Default = 0x90
FXLS8974_SENS_CONFIG1 After Update = 0x1
FXLS8974_SENS_CONFIG3 After Update = 0x90
FXLS8974_INT_STATUS = 0x81
X= 11
Y= -4
Z= 1143添付ファイルに hello_world_FXLS8974.c と nxp_lpi2c_transfer.c/.h を格納していますので、source フォルダーにコピーして是非活用ください。
まとめ
センサーとの通信でよく使用される Flexcomm LPI2C の制御方法について解説しました。
初心者ガイド 13 と合わせて、実機検証いただくことで I2C の SDK の使い方を理解頂けるかと思います。
使用するセンサー仕様やセンサーメーカーが用意しているサンプルソフトウェアの仕様に合わせてカスタマイズして活用いただければと思います。