RX220で本気の
I2C通信を行う場合は
RIIC機能を使います。
RIICではSCLとSDA端子を使うのですが、64ピンのRX220ではSCLとSDAに割り当て可能な
端子はそれぞれ
P16と
P17のみとなります。
ところが
P16と
P17は
貴重なPWM端子なのでI2Cとして使いたくありません。
ハードウェアマニュアルの機能別端子一覧を見ると
SCL,
SDAの代わりに
SSCLと
SSDAという
端子は幾つかあります。
SDAでも
SSDAでもまあ、変わらないだろうと思っていたらちょっ
と厄介なことになりました。
SCLと
SDAは
RIICで使用するのに対して、
SSCLとSSDAはRIICの端子ではありません。
マニュアルにて
簡易I2Cにて使用するところまでは分かったのですが、そこから先は
ネット上でよさげな情報が見つかりません。しかも公式サンプルを探してもどれが簡易I2Cの
サンプルなのかわかりません。
そこでハードウェアマニュアルを読み解きながら設定をしました。
RIICと
簡易I2Cでは設定がかなり違う様です。
ハードウェアマニュアルの
・SCI の初期化(簡易I2C モード)
および
・マスタ送信動作(簡易I2C モード))
のフローチャートに基づいて設定を行っていきます。
※Acrobat Reader DCでは「起動時に保護モードを有効にする」を無効にしておかないと
日本語検索ができませんでした。RX220の
他の機能は設定の解説を省略していましたが、今回は
SH7125と異なるので真面目に紹介してみます。
関連:
I2Cとは受信編割込編
簡易I2Cの初期化
初期化で必要なのは大まかに
・端子の機能設定
・通信モジュールの停止解除
・簡易I2Cモードへの変更
・クロックや通信速度など通信条件の設定
の4項目です。
※2019/02/22色々間違っていたので修正PB6(SCI9_SSCL)、PB7(SCI9_SSDA)を使って簡易I2C通信を行います。
設定1、ピン設定と通信モジュールの停止解除初期化関数を作成します。
<設定>void init_I2C(
void)
{
//入出力の設定 PORTB.PDR.BIT.B6=1;
//PB6 SSCLを出力設定 PORTB.PDR.BIT.B7=1;
//PB7 SSDAを出力設定 //出力方式の設定 PORTB.ODR1.BIT.B4=1; //PB6をオープンドレインに設定 PORTB.ODR1.BIT.B6=1; //PB7をオープンドレインに設定 //特殊機能を使用する端子の設定 PORTB.PMR.BIT.B6=1;
//PB6を周辺機能モードに変更 PORTB.PMR.BIT.B7=1;
//PB7を周辺機能モードに変更 //特殊機能設定開始 MPC.PWPR.BIT.B0WI = 0;
//PFSレジスタの保護解除をするPFSWEレジスタの保護解除 MPC.PWPR.BIT.PFSWE = 1;
//PFSレジスタの保護解除 //Pxx 端子機能制御レジスタ(PxxPFS) MPC.PB6PFS.BIT.PSEL = 0xA;
//PB6の周辺機能を設定(SSCL) MPC.PB7PFS.BIT.PSEL = 0xA;
//PB7の周辺機能を設定(SSDA) //特殊機能設定終了 MPC.PWPR.BIT.PFSWE = 0;
//PFSレジスタの保護 MPC.PWPR.BIT.B0WI = 1;
//PFSレジスタの保護をするPFSWEレジスタの保護 //SCI9モジュールの停止解除 SYSTEM.PRCR.WORD = 0x0A503;
//クロックと動作モードの保護解除 MSTP(SCI9) = 0;
//SCI9モジュール停止解除 SYSTEM.PRCR.WORD = 0x0A500;
//クロックと動作モードの保護ここまでは
他の機能の設定とほぼ同じです。
※2019/02/22 追記出力方式をNチャンネルオープンドレイン(オープンコレクタ)に設定する必要があります。設定2、クロック同期式モードへの変更、通信条件の設定ここからはハードウェアマニュアルのSCI の初期化(
クロック同期式モード簡易 I2C モード)のフローチャート
に従って記述していきます。
※2023/02/25 参照資料が間違っていたので訂正 //クロックの設定準備 SCI9.SCR.BIT.CKE = 0x00;
//内部クロックを使用 SCI9.SCR.BYTE&=~0x30; //送信禁止+受信禁止 //[2] SCI9.SIMR3.BIT.IICSDAS=0x3;
//SSDAn端子はハイインピーダンス状態 SCI9.SIMR3.BIT.IICSCLS=0x3;
//SSCLn端子はハイインピーダンス状態 //[3] SCI9.SMR.BIT.CM=0;
//0:調歩同期式 1:クロック同期式 SCI9.SMR.BIT.CKS=0x3;
//PLCK/64 SCI9.SCMR.BIT.SDIR=1;
//MSBファーストで送受信 SCI9.SCMR.BIT.SINV=0;
//そのまま送信 SCI9.SCMR.BIT.SMIF=0;
//SCIモード //[4]/*32MHz,1分周期の場合*/// SCI9.BRR = 103; // 9600bps SCI9.BRR = 51;
//19200bps// SCI9.BRR = 25; //38400bps// SCI9.BRR = 8; //115200bps //[5] SCI9.SEMR.BIT.NFEN=1;
//ノイズ除去フィルタあり SCI9.SNFR.BIT.NFCS=1;
//1分周のクロックをノイズフィルタに使用 SCI9.SIMR1.BIT.IICM=1;
//簡易I2Cモード SCI9.SIMR1.BIT.IICDL=1;
//SCLから1サイクル遅れてSDAを変化させる SCI9.SIMR2.BIT.IICACKT=1;
//NACK送信またはACK/NACK受信 SCI9.SIMR2.BIT.IICCSC=1;
//クロック同期を行う(スレーブからのクロックストレッチを受け入れる) SCI9.SIMR2.BIT.IICINTM=1;
//0:ACK/NACK割込み、1:送受信割込み SCI9.SPMR.BYTE=0;
//SPI機能全停止 SCI9.SCR.BYTE|=0x30; //送信許可+受信許可}
※2019/02/27 追記送信許可、受信許可の設定を個別で変更すると先に変更した方だけが有効になるようです。
送信受信の許可/禁止はビットごとに変更せず、いっぺんに変更してください。<解説>[3]の部分SCI9.SMR.BIT.CKSは任意の設定が可能です。
今回は出力の視認のため、なるべく遅くなるようにメインクロックの1/64の速度で動作させます。
[4]の部分今回は32MHz動作時の
UART通信の値をそのまま持ってきました。
メインクロックの設定を変更していない場合はLOCO 125KHzで動作するので19200bpsにはなりません。
クロックの速度はUARTと異なりマスターがコントロールするので、適当に設定しても動きます。
[5]の部分ノイズ除去フィルタありに設定してみました。効果のほどは未検証です。
SCI9.SIMR2.BIT.IICINTMは送受信割込みに設定してみました。
とりあえず割込み無しで送信テストを行うので、今回はどちらもで良さそうです。
I2Cの送信
通信の準備ができたので送信を試してみます。
マスタ送信動作(簡易I2C モード)のフローチャートに基づいて設定を行っていきます。
SH7125の時と同様に
DRV8830に指令を送ります。
DRV8830の取説に従って、通信の順は
・スタートコンディション
・スレーブアドレス(0xC8)
・サブアドレス(0x00)
・設定値(0x49)
・ストップコンディション
となります。
<設定>void send_i2c(
void){
int i;
//スタートコンディションの発行 SCI9.SIMR3.BIT.IICSTIF=0;
//フラグクリア SCI9.SIMR3.BIT.IICSTAREQ=1;
//スタートコンディション生成指令 SCI9.SIMR3.BIT.IICSDAS=0x1;
//SSDAn端子は開始条件、再開始条件、停止条件 SCI9.SIMR3.BIT.IICSCLS=0x1;
//SSCLn端子は開始条件、再開始条件、停止条件 while(SCI9.SIMR3.BIT.IICSTIF==0);
//開始/再開始/停止条件生成が完了するまで待機 //データ送信準備 SCI9.SIMR3.BIT.IICSTIF=0;
//フラグクリア SCI9.SIMR3.BIT.IICSDAS=0x0;
//SSDAn端子はデータ出力 SCI9.SIMR3.BIT.IICSCLS=0x0;
//SSCLn端子はクロック出力 //データ0(アドレス)送信 SCI9.TDR=0xC8;
//宛先アドレス for(i=0;i<100;i++);
//ちょっとだけ空ループ while(SCI9.SSR.BIT.TEND==0);
//送信完了まで待機 //データ1(サブアドレス)送信 SCI9.TDR=0x00;
//サブアドレス for(i=0;i<100;i++);
//ちょっとだけ空ループ while(SCI9.SSR.BIT.TEND==0);
//送信完了まで待機 //データ2(電圧設定)送信 SCI9.TDR=0x49;
//電圧設定値 for(i=0;i<100;i++);
//ちょっとだけ空ループ while(SCI9.SSR.BIT.TEND==0);
//送信完了まで待機 //ストップコンディションの発行 SCI9.SIMR3.BIT.IICSTPREQ=1;
//ストップコンディション SCI9.SIMR3.BIT.IICSDAS=0x1;
//SSDAn端子は開始条件、再開始条件、停止条件 SCI9.SIMR3.BIT.IICSCLS=0x1;
//SSCLn端子は開始条件、再開始条件、停止条件 while(SCI9.SIMR3.BIT.IICSTIF==0);
//開始/再開始/停止条件生成か完了するまで待機 //送信終了の後処理 SCI9.SIMR3.BIT.IICSTIF=0;
//フラグクリア SCI9.SIMR3.BIT.IICSDAS=0x3;
//SSDAn端子はハイインピーダンス状態 SCI9.SIMR3.BIT.IICSCLS=0x3;
//SSCLn端子はハイインピーダンス状態}
<解説>
フローチャートではTXI割込みを使用していますが、今回は割り込みを使わず送信完了フラグ
TENDが立つまで待機させました。
また、SCI9.TDRを設定直後だと
TENDが立っている様なので、送信を開始するまでの間を持たせるためにちょっとだけ空ループをさせています。
今回はスレーブからのACK/NACKの返信を気にせずに一方的にデータを送って一方的に終了させました。
とりあえず、これでDRV8830が動くところまでは確認できました。
次回は受信動作を確認します。