- 9891. dsPICでI2C送信時にSCLが止まってしまう [TAKA] 2006/03/13 16:12
- TAKAです。
原因になりそうなことを思いついた方がいましたら教えてください。
環境はC30とICD2を使用してます。
現在、dsPICにI2C機能(以下スレーブ)がついたチップを接続しています。
とりあえず、スレーブIDとスレーブ内のアドレスを指定しようとして下記のようなPGをしましたが、
[スレーブID][スレーブ内のアドレス]
を送るつもりなのにSCLがはじめの9クロックで止まってしまい、その後LOW出力を続けてしまいます(よってストップコンディションにもならない)。どのような原因が考えられますでしょうか?
ちなみに、スレーブの方から1個目の8ビット送信後にACKが返ってきてますので、ハード&設定は問題ないものと考えています。
以下PGです。
I2CBRG = 133;//Set I2C for 100kHz
I2CCONbits.I2CEN = 1;//Eneble I2C
//Strat condition
I2CCONbits.SEN = 1;//Request Start condition
while(I2CCONbits.SEN);//Wait till Start condition is compleated
//Send Slave ID
I2CTRN = SlaveID_Write;//Set target ID
while(I2CSTATbits.TBF);//Wait till transmitted
while(I2CSTATbits.ACKSTAT);//Wait ACK
//Send Addr
I2CTRN = 0x55;//Set data
while(I2CSTATbits.TBF);//Wait till transmitted
while(I2CSTATbits.ACKSTAT);
//Stop condition
I2CCONbits.PEN = 1;//Request Stop condition
while(I2CCONbits.PEN);//wait till Stop contion is compleated
これを1秒おきに繰り返すと、ストップコンディションにならないまま、1バイト目のスレーブIDだけ送信され、その間のSCLだけはクロックが立ちます(それ以外はSCL=Lowでクロック無し)
予想では、2バイトデータを送信してますので18クロック立った後に、ストップコンディション−>IDLEコンディション(SCL&SDAが両方High)になるはずなのですが、1秒おきに9クロック立ってSCL=Low,SDA=Highになります。
他にはUART2から状態確認のデータ(Startの文字を送信して他のPCでモニタとか)を送っているだけでなにもしてません。
ボーレートはオシロで計ったところ100kHzになってましたので設定は合ってます。
- 9892. Re: dsPICでI2C送信時にSCLが止まってしまう [TAKA] 2006/03/13 16:16
- 情報追加ですが、IDを送っている間のSDAは送信している値の波形がきちんと出ています。
- 9893. Re: dsPICでI2C送信時にSCLが止まってしまう [i2c] 2006/03/13 16:53
- >[スレーブID][スレーブ内のアドレス]
>を送るつもりなのにSCLがはじめの9クロックで止まってしまい、その後LOW出力を続けてしまいます(よってストップコンディションにもならない)。どのような原因が考えられますでしょうか?
dsPICとC30は知らないけど、SSPIFをクリアしてないからなのでは?
- 9894. Re: dsPICでI2C送信時にSCLが止まってしまう [i2c] 2006/03/13 17:00
http://www.picfun.com/midi2c06.html
- ↑PIC16の説明だけど、タイミング図を参照。
もちろん、使用dsPICのDatasheetも確認してください。
- 9895. Re: dsPICでI2C送信時にSCLが止まってしまう [i2c] 2006/03/13 17:31
- >dsPICとC30は知らないけど、SSPIFをクリアしてないからなのでは?
補足:スレーブIDを勘違いしてRead要求出しちゃってるのかも。
Clockストレッチ等含めよく調べてみてください。
C30(Ver.2以降?)ではI2C関連の関数も結構充実して来ているのではないでしょうか。
- 9898. Re: dsPICでI2C送信時にSCLが止まってしまう [TAKA] 2006/03/13 21:10
- i2Cさん、
返信ありがとうございました。
>>dsPICとC30は知らないけど、SSPIFをクリアしてないからなのでは?
今、作業環境と別なところにいるので確認できませんが、SSPIFはクリアしてません。確認してみます(SSPIFという項目はリファレンスには無かったような気がしますが、I2C以外のところは読んでないので割り込み関係もチェックしてみます。他の項目でxxしてないとxxできない、というのがよくありますからね。)
>
>補足:スレーブIDを勘違いしてRead要求出しちゃってるのかも。
>Clockストレッチ等含めよく調べてみてください。
Read要求(bit0を1にする)など、いろいろな組み合わせをやってみましたが、データ的には問題ないと思います。ちなみに、Read要求をすると1バイト送った状態ではACKが帰ってきませんでした。先の方法のときだけ、始めのデータ送信後にACKが帰ってきますので、スレーブへの要求は通った上でACKが帰ってきてるという感じがします。
>C30(Ver.2以降?)ではI2C関連の関数も結構充実して来ているのではないでしょうか。
C30のライブラリにI2C関連の関数はありますが、結局はリファレンス見ないとI2C使えないし、I2Cの関数がSFRのビットを1つ変えるだけのものが多いので微妙でした。ちなみに先のPGはもともとはC30のライブラリ関数で書いてましたが行数はほぼ同じです。
という感じです。
- 9902. Re: dsPICでI2C送信時にSCLが止まってしまう [TAKA] 2006/03/14 08:27
- TAKAです。
dsPICにはSSPIFは無いようです。割り込みは行ってないので割り込みの設定でも無いようですね。
未だ試行錯誤中ですがまったくわかりません。
ちなみに、昨晩、同じIC(スレーブにしてるやつ)をAVRで駆動してみたら問題なく通信できました。
やはりI2C以外の設定が関連してるのか?
リファレンス全部読むのはしんどいなあ...760P。
- 9904. Re: dsPICでI2C送信時にSCLが止まってしまう [nyannnyannko] 2006/03/14 10:13
↓マイクロチップ米国のホームページから
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=64
Support の下の Online Discussion Groups を 選びます。
( http://forum.microchip.com/ )
[16 bit Digital Signal controllers] の中の dsPIC30F Topics を クリック
( http://forum.microchip.com/tt.aspx?forumid=153 )
Display topics from last: のダイアログは All Topics を選択。
Search のダイアログでは、I2C SCL で検索をかけると。
↓等がヒットします。
http://forum.microchip.com/tm.aspx?m=145328
- 9910. Re: 解決。C30のマニュアルを見るとハマる。C30でのI2Cまとめました。 [TAKA] 2006/03/14 13:00
- nyannnyannkoさん、
ぴしいです。以前も教えていただきありがとうございます。以前はたしかエラッタを見るということを教わりましたが生かせてませんね。本家のユーザーフォーラム、勉強になりました。
さて、解決しましたが、結論はC30に添付されているライブラリ解説のプログラム例のようにコーディングすると動かないということでした。
//C30マニュアルに書いてある1バイト送信のPG(動かない)
MasterWriteI2C(DATA);
while(I2CSTATbits.TBF);
while(I2CSTATbits.ACKSTAT);
動いたコーディングは下記のようになります。
//1バイト送信
MasterWriteI2C(DATA);
while(I2CSTATbits.TRSTAT);
フォーラムでも指摘の通り、sdPICリファレンスマニュアルのタイミング図を見ると、1バイト送信終了判定ではTRSTATを見た方がよい感じになります(明言はしてないが)。C30マニュアルでは送信バッファとACKを見てますが、これだとACKのクロックの終了まで待たないようになります。
その他、C30には書かれてない状態もまとめましたので書いておきます。これだけ使えばI2Cは網羅しているかと(データ列送受信以外は。)
//ボーレート設定
I2CBRG = ???; //数値はハードに依存
//I2C有効
I2CCONbits.I2CEN = 1;
//スタートコンディション発行
StartI2C();
while(I2CCONbits.SEN);
//1バイト送信
MasterWriteI2C(DATA);
while(I2CSTATbits.TRSTAT);
//リスタート
RestartI2C();
while(I2CCONbits.RSEN);
//1バイト受信
value = MasterReadI2C();
//NCKを発行
NotAckI2C();
while(I2CCONbits.ACKEN);
//ストップコンディション発行
StopI2C();
- 9936. Re: 解決。C30のマニュアルを見るとハマる。C30でのI2Cまとめました。 [nyannnyannko] 2006/03/16 10:27
解決して良かったですね。ちなみに私は dsPIC はまだ使った事がありません。
下記から日本語の資料をダウンロードしておくと理解し易いと思います。
dsPIC 関連
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1999&ty=&dty=§ion=&NextRow=&ssUserText=dsPIC&x=3&y=7
MPLAB C30 dsPIC用のCコンパイラのユーザーズガイド(日本語)
http://ww1.microchip.com/downloads/en/devicedoc/51284c_jp.pdf
dsPIC30F Family Reference Manual(日本語)
http://ww1.microchip.com/downloads/en/devicedoc/70046b_jp.pdf