いつもお世話になっております。
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の実態かもしれません。