いつもお世話になっております。
solと申します。
C-Firstという基板と「絵解き マイコンCプログラミング教科書」という教科書でマイコンの勉強をしています。
現在、以下の資料を参考に気温データ・ロガーを作成しております。
https://japan.renesasrulz.com/cafe_rene/f/002-2095199602/4975/cq
I2CでLCDと通信を試みているのですが、ACKが検出できず、困っています。
一方で、基板上の加速度センサや、リアル・タイム・クロックとは正常に通信ができており、ACKも検出できています。
そこで、(絵解き マイコンCプログラミング教科書のサポートページより入手可能な)気温データ・ロガーのサンプルプログラムを動かしてみたところ正常に動作したため、自分のプログラムと何が違うのか見比べてみたところ、サンプルプログラムはACKが受信できているかどうかを確認しておらず、ただ送り付けているだけだということに気づきました。
私のプログラムも同様にACKの確認をせず、ただ一方的に送り付ける形で送信してみたところ、LCDにきちんと文字列が表示され、動作しました。
ACKの受信が検出できない原因が分からないのですが、どのような理由が考えられるでしょうか。
ご回答よろしくお願いします。
LCDのバスドライブ能力が低いためだと考えられます。 経験上、I2Cバスのプルアップが10kΩ以上は欲しいところです。 しかし、そうすると通信速度を上げたり、複数デバイスを繋ぎにくくなります。
このような場合、I2Cバスリピーター経由でつなぐような事が世間では行われています。(Raspberry Piでの対策として有名なようです)
参考: akizukidenshi.com/.../goodsfaq.aspx strawberry-linux.com/.../619011
チョコです。 >まず、I2Cバスになぜプルアップ抵抗が必要なのでしょうか。 I2Cバスはオープン・ドレイン出力でドライブするようなバスになっています。 このようになっているのは、複数のマスタを接続して、複数のマスタのが同時にバスを使い始めようとしたときに信号がぶつかっても問題ないようにするために、ハイレベルをプルアップ抵抗で供給するようになっているからです。
追記
>また、抵抗値に関して、(現在4.7kΩですが)なぜ10kΩの抵抗であればうまくいきそうなのでしょうか?
プルアップ抵抗値が小さいと、大きな電流を流さないと、ロウレベルにはできません。4.7kΩでは、500μA流したとすると、2.35Vの電圧降下になるので、3.3Vの電源電圧なら、0.95Vになります。ロウレベル入力電圧の閾値が0.2VDDなら0.66V以下でないとロウレベルと判断されず、ACKが検出できません。抵抗を10kΩにすると、264μA流せば、0.66Vになるので、ロウレベルと判断され、ACKが検出できます。
>プルアップ抵抗を10kΩとした場合、通信速度を上げたり、複数デバイスをつなぎにくくなるのはなぜなのでしょうか。
信号の立ち上がりはプルアップ抵抗でのI2Cバスの容量を充電することになり、抵抗値が大きいと、信号の立ち上がりがなまってしまい、タイミングが遅くなってしまいます。また、複数のデバイスが接続されると、リーク電流が大きくなり、ハイレベルを維持できなくなる可能性が出てきます。
チョコです。
気になったので、NXP社のI2Cの仕様で電気的な特性を確認してみました。
標準モードやファストモードでLOWレベル出力電流が、VOLが0.4Vでも3mA(最小)と規定されています。ファスト・モードでは、0.6Vで6mA(最小)と規定されています。
この規格が満足されていれば、3.3Vで4.7kΩで全く問題ないはずです。
にも拘わらず、4.7kΩをLOWレベルまでドライブできないということは、LCDモジュールのコントローラがI2Cの規格を満足できていないことになります。
以前使った別のLCDモジュールでもI2Cバスのドライブ能力は低かったのですが、それでも3.3kΩで大丈夫でした。規格を満足しないだけでなく、その中でさらにバラつきがあることになります。そのためにデバイスのドライブ能力が明確にされていないのかもしれません。
海外メーカのデバイスにはこういうことがよくあるようです。(それを使いこなすのがノウハウというのはおかしい気がします。何のための標準規格でしょう。)
同じI2Cの仕様書に以下の記述もありました。
かなり愚痴が出てしまいましたが、これがI2Cの実態かもしれません。
チョコです。 >ところで、以前、電源電圧5Vの波形を確認したところ、3.7V - 4.7V くらいの範囲(5Vになることはなかった) C-Firstの電源をどのように供給しているかが分かりませんが、USBからの5V電源の供給が弱いのではないでしょうか。
(以前、別のスレッドで、PCのUSBからの5Vが異常に低いケースがあり、誤動作して例がありました。) >IICWH0 の tR と tF の計算の仕方が分からず、暫定的に0としたところ、コード生成と(ほぼ)一致したためこれでやっていますが、正しいでしょうか…? 単に、通信速度が tR と tF の遅くなるだけで、大勢に影響しないと思います。 (信号ラインの負荷容量が、配線やつながっているデバイスで変化するので、 tR と tF を計算するのは難しいと思います。 tRはプルアップ抵抗での負荷容量の充電カーブ、tFはロウに引っ張るデバイスのドライブ能力も影響します。)
追伸
ICの端子容量はパッケージによっても異なりますが、数十pFと考えられます。配線の浮遊容量は長さやパターンの引き方にも依存しますが、100~200pF程度と考えて、合計で300pF程度と考えておけばそんなに外れないと思います。今回の例では、LCDのコントローラのドライブ能力が不明ですが、結構tFは長くなるとと考えられます。プルアップ抵抗も結構大きくしないといけないので、10kΩと300pFでの時定数は3μsとなります。すごくラフですが、この程度のオーダと考えられます。ちなみにI2Cバスの標準モードでは立下り300n、立ち上がり1000ns以下と規定されています。とにかく、関係するパラメータがよくわからないので、転送速度がそんなに気にならないなら、ハイ幅が4μs、ロウ幅が4.7μsで設定してみてください。
100kbpsだと、1ビットが10μsに対して、立ち上がりと立下りで6μsかかるとすると、結局1ビットが16μsとなり、実効的な通信速度は60kbps程度に下がるだけです。これが問題になるかどうかです。