SH7286(master)を使用して複数のマイコン(AVR)とI2C(IIC3)を使用して順次通信してデータを受信しています。
停止条件発行後に時々バスが開放されずに止まってしまいます。
(このとき通信相手側は動き続けているので止まる原因が不明です)
システムの都合上、処理を止めたくないので強制的にバスを開放してI2Cの状態をリセットさせたいと考えています。
(本来止まらないようにするべきですが、何かあった場合でのエラー処理も含めての対応策として実装しておきたい)
ユーザーマニュアルに載っていたI2Cのリセットを一定時間以上待ってから使用してもその後通信ができませんでした。
強制的にバスを開放して、I2Cを再開させる何か良い方法があれば教えていただければと思います。
IIC3.ICSR.BIT.STOP = 0; /* STOPフラグクリア */
IIC3.ICCR2.BYTE &= 0x3f; /* 停止条件発行 */ while(IIC3.ICSR.BIT.STOP == 0){ /* ==== バス解放待ち ==== *//***********この中で止まる************/
if(){ iic3_reset(); }// 一定時間以上経過したらresetをかける
}
void iic3_reset(void){ IIC3.ICCR1.BIT.ICE = 0; IIC3.ICCR2.BIT.IICRST = 1; IIC3.ICCR1.BIT.MST = 0; IIC3.ICCR1.BIT.TRS = 0; IIC3.SAR.BIT.FS = 1; IIC3.ICCR2.BIT.BBSY = 0; IIC3.SAR.BIT.FS = 0; IIC3.ICSR.BYTE = 0x80; IIC3.ICCR2.BIT.IICRST = 0; IIC3.ICCR1.BYTE = 0x00; IIC3.ICCR2.BYTE =0x7D; IIC3.ICMR.BYTE =0x38; IIC3.ICIER.BYTE =0x00; IIC3.SAR.BYTE =0x00; IIC3.NF2CYC.BYTE = 0x00; IIC3.ICCR1.BIT.ICE = 1;}
sinさん
こんにちは。
バスが開放されないとは、スレーブによってSCLとSDAのどちらが開放されないのでしょうか?
SCLだとSH7286のI2Cバスラインからの打つ手はないと思います。
スレーブ側でSDAがLowに固定されているのであれば、SCLから疑似クロックを出力してSDAを開放させる手があります。
ルネサスサイトのFAQにスレーブ側でSDAがLow固定されている場合のバス解除手段が記載されているものを見つけました。
対象製品は異なりますが、同じI2Cバスなので解除方法の参考になると思います。
japan.renesas.com/.../r8c_107454_jp.jsp
japan.renesas.com/.../MPUMCU_H8S_077J.jsp
SAさん
返答ありがとうございます。
>バスが開放されないとは、スレーブによってSCLとSDAのどちらが開放されないのでしょうか?
主にSDAが開放されていない場合が多いです。(たまにSCLもLOWのままになっています)
参考資料ありがとうございます。
いろいろ試してみましたが、うまくいきませんでした。
更に質問なんですがこの資料にある疑似パルスとはどうやって出すのでしょうか?
汎用ポートに切り替えてから、on/offを切り替えるタイミングなどあるのでしょうか?
こんにちは
お考えの通りです。設定している転送レートの周期の1/2の時間で切りかえます。
SCLと同じ端子に割り当てられているI/Oポートを使用します。
SCL端子からI/Oポートに切り替えて、出力ポートに切り替えます。
SCLラインはHighですので、出力ポートかLowを出力します。
転送レートの周期の1/2の時間分Low出力を保持した後、この出力ポートから今度はHighを出力に切り替えます。
このHighを転送レートの周期の1/2の時間分のHigh幅分出力します。
この動作を繰り返すと疑似SCLとなります。
疑似SCLを出力しながらSDAの状態を確認して見てみて下さい。
SH2で使用されているIICコントローラでは、いったんバスロックしてしまうとそこから回復させる手段は用意されていません
で、どうやってバスロックの状態から回復させるかというと、SDAとSCLを汎用出力ポートにしてしまい、手動で疑似的にSCLパルスを発生させる/あるいはストップコンディションを発生させて、バスの開放を確認する、ということになります。
バスの開放を確認した後、SDA,SCLを再びIICの端子として設定し、通信を継続させていく、という手順になります。
バスロックの状態からどういう手順でバス開放するかというのは、お使いのIICデバイスのデータシートに書いていると思いますので、それに従って行ってください。
一般的にはSDAをHighにしたままSCLパルスを10発以上出力する、とか、ストップコンディションを10発以上発行する、ということになるとおもいますが
次に、なぜバスロックが発生するか、ということですが、これはひとえにIICデバイスの想定通りにSCL、SDA信号が操作されていない、ということに尽きます。
まずはIICデバイスのデータシート、CPUのデータシート(IICコントローラの記述)を熟読、理解し、オシロスコープなどで動作の信号を確認していき、なにが違うのかをはっきり確認されることをお勧めします。(というよりそれしか解決の方法はありません)
少し時間が経ちましたが結果報告です。
結論から言うと無事にバス開放ができました。
おかげで、I2Cが落ちても復帰ができ止まることなくシステムが動く状態になりました。
疑似パルスを出しバス開放をするやり方ではだめでした。
データシートのI2Cのマニュアルに載っているリセットを行い、I2Cの初期化をしたら動くようになりました。
スレイブ側が複数動いていたために思っていたところと違うところで止まっていたり、正しい動作をさせる前に次の処理をさせていたため解決が延びました・・・。
アドバイスありがとうございました。
今回の解決では使用できませんでしたが、疑似パルスの出し方や他の解決方法など勉強になりました。
今後に生かせていけそうです。
わわいさん
おっしゃるとおり、完全な理解、確認不足でした。
触り始めてから日が浅いと言うのは言い訳になりますが、データシートをしっかり確認してオシロスコープを使いこなせていたらもう少し早く解決できた気がしました。
やはり基本が大事ですね。。。