たまりば

  パソコン・インターネット パソコン・インターネット  三鷹市 三鷹市

I2C液晶が動かない理由が分かった
2017年01月31日 01:54

以前、秋月で超小型のI2Cキャラクタ液晶(I2C接続小型キャラクタLCDモジュール 8x2行)を買い、PIC10F200で色々と表示していた。
ある時思いついたネタを実装しようとしたところ10F200ではROMが足りなかったので、石をPIC12F510に変えることにした。
移植作業はわりと楽であった。ADコンバータ関連を無効化すればあとはだいたい似たようなものである。
しかし動かない。
しかも不思議な事に信号線にLEDやテスターをつなぐと動く。つまり原因は単純なプログラムのミスではなくアナログ的な微妙な差異によるもののようだ。
色々考えたが分からないのでその時はあきらめた。一昨年の5月ころだ。

(昨年の4月に)その原因が判明したので顛末をここに書き留める。何かの参考になれば幸いだ。

まず最初に言っておくと、このプログラムで出していた信号は正常なI2Cではない。
第一に、本来I2CはLowとプルアップで駆動するものをHighとLowで駆動している。プログラムの簡略化と高速化の為だ。
第二に、クロック立ち下がりからデータ変化の時間、tHD:DATはデータシートによれば最小0・最大0.9μs(後述)のところ、最小ギリギリの0にしている。10F200で可能な間隔が1μsの為だ。またデータシートによればこれでも300nsの余裕があるように読める(後述)。

もっとまともな信号にすれば動くかもしれなかったが、それは解決にならない。
問題は動かない事ではなく、動かない理由が分からない事である。
規格外や規格ギリギリではあるものの、これでも動くはずだと考えてやっているのだし、実際10F200ではほぼ確実に動くのである。
この状態で適当に変更して動くようになったとしても本当にその変更が正しかったのか分からない。何か重大な思い違いがあったら危険だ。
またなにより、何が問題なのか分からないままというのは気持ち悪い。

移植して動かなかった時から(覚えている限り)時系列に沿って状況を書く。

MPLABのシミュレータで見た波形は全く同じ。
怪しいのは実際に信号が出ているかだ。TRISの設定を間違ったり、間違って別のピンにつないでいたりすることはしょっちゅうだ。
なので信号が出ているかどうかを確認するため、信号線に青LEDをつないだ。(LEDをつなぐと点滅具合で色々分かる。青なのは電源が電池2本の時抵抗を入れなくても大丈夫で便利だからだ)
すると…不思議なことにほぼ確実に動作するようになった。
最初はデータとクロック両方に付けていたが、データ線だけでも動作する。
赤LED(+抵抗)だと駄目。電圧の問題かと思い赤LED+ダイオード1、2本で試すも駄目。また、データ線にテスターを当てるとほぼ確実に動作する。

この時点で問題はアナログ的なものと分かった。

アナログ的な仕様に何か違いがあるのではないかとデータシートを見る。ほとんど同じだったが、1つだけ、デバイスリセットタイマ(DRT)の時間が異なっていた。早速その分の待ちを入れてみる。
…が、変わらず。

もはやこれはオシロスコープを買うしかない。
2万円の機種と迷ったが3万円のものを購入。オシロスコープで12F510で動く時(青LED付き)と動かない時を確認すると信号に違いが!
…と思ったがよく見るとそれはACKが返っていないだけであった。
分かったことは、最初の1バイト(アドレス)から既にACKが返っていないということだけ。
あとはノイズだが、電源投入からI2C送信までの間に目立ったノイズは無く、電源投入時のノイズはわりと酷いがどちらも同様に酷い。

そして10F200と12F510を比較してみると、I2C信号を送信するところは一切違いが見当たらないが、リセット直後の挙動が違っていた。
調べてみると、デバイスリセットタイマ相当の待ちを入れた時、待ちの後にHigh-ZからHighにするつもりのところを間違って待ちの前にHighにしてしまっていた。
…しかしこれを直しても変わらず。
もしかしてデバイスリセットタイマ中とプログラムが走っている時では何か違いがあるのだろうか。そうなると12F510で動かすのは不可能ということに。

この辺でできることも無くなり諦めてしばらく経った。

ある日、なんとなくI2Cについて考えていて思った。なぜtHD:DATに上限があるのだろう。
液晶コントローラのデータシートに上限があるように書かれていたので不審に思いながらも従っていたのだが、やはりおかしい。
I2C液晶データシート
I2Cのデータシートを見ると、違う書かれ方をしている。(なお後で知ったが古いデータシートでは上限0.9μsになっていた)
I2Cデータシート
上限はなし、その上で注釈として、
The maximum tHD:DAT could be 3.45 μs and 0.9 μs for Standard-mode and Fast-mode, but must be less than the maximum of tVD:DAT or tVD:ACK by a transition time.
最大のtHD:DATはスタンダードモードで3.45μs、ファースト(fast)モードで0.9μ秒になりうるが、tVD:DATまたはtVD:ACKの最大値よりトランジション時間だけ短くなくてはならない。
This maximum must only be met if the device does not stretch the LOW period (tLOW) of the SCL signal.
この最大値はデバイスがSCL信号のLOW期間(tLOW)をストレッチしないときのみ満たす必要がある。
If the clock stretches the SCL, the data must be valid by the set-up time before it releases the clock.
もしクロックがSCLをストレッチするなら(訳注: 意味が分からない。SCLはクロックだ)、データはそれ(訳注: どれ? クロック?)がクロックを解放する前にセットアップ時間だけ有効でなければならない。
CBUSとの兼ね合いかとも思って調べようともしていたが、どうも死んだ規格らしく情報がない。その辺で当時は諦めていた気がする。
しかしさらに考えてやっと分かった。この0.9μsという上限の値は、スレーブに対する制限なのだ。
「マスターがクロックを生成しスレーブがデータを送信するとき、マスターがクロックをLowにしている間にスレーブはデータを変化させなければならない」という当たり前の制限について言っているだけだ。

クロックがLowの間にデータを変化させるには、データのホールド時間(tHD:DAT)・データの立ち上がり時間(tr)または立ち下がり時間(tf)・データのセットアップ時間(tSU:DAT)の和がクロックのLow期間(tLOW)より短くなければならない。
I2Cタイミング関係
ファーストモードではクロックのLow期間の最小値が1.3μs、立ち上がり時間の最大値が300ns、データセットアップ時間の最小値が100nsなので、
1.3-0.3-0.1=0.9
となり注記の値に一致する。

スタンダードモードでも同様に
4.7-1-0.25=3.45
となる。

今回データ送信はマスター側からのみ行うため、スレーブの制限は無関係だ。よって最大0.9μsは無視してもっと長い時間とれば余裕を持った通信ができる。

解決方法は見えた。あとは原因の方だ。10F200と12F510、LEDやテスタリードを付けた12F510で何が違うのか。

もう一度オシロで波形を見てみよう。
ここまでI2Cの通信内容が分かる程度の縮尺で見ていたのだが、限界までサンプリング速度を上げて拡大して見てみる。すると波形が明らかに違っていた!
I2C_10F200/12F510比較
10F200はシンクが強いのか立ち下がりが速い。
これによって、SCK・SDAを同時に操作してもSCKの立ち下がりの後にSDAの立ち上がりが来てくれていたようなのだ。それが12F510では逆になっている。
この違いで動作が分かれていたのだろう。
なおこの3万円のオシロのサンプリング速度は250Msps(2ch時)、帯域は60MHz。迷っていた2万円の方の機種は100Msps・25MHzである。
1/(60MHz)=17ns、1/(25MHz)=40nsであり、25MHzの帯域で今回の波形の違いを捉えられたかはかなり怪しい。
高い方を選んで良かった。

さて最後に、冒頭で言った300nsの余裕の件だ。

tHD:DATの下限について、以下のように注釈がある。バージョンによって言い回しが少々変わっているが内容は同じようだ。
・A device must internally provide a hold time of at least 300 ns for the SDA signal (referred to the VIHmin of the SCL signal) to bridge the undefined region of the falling edge of SCL.
・A device must internally provide a hold time of at least 300 ns for the SDA signal (with respect to the VIH(min) of the SCL signal) to bridge the undefined region of the falling edge of SCL.
この文章も微妙に意味が取れないのだが、精一杯の訳が以下だ。
「SCLの立ち下がりの不定区間を橋渡しするため、デバイスはSDA信号に対して内部的に最低300nsのホールド時間を(SCL信号のVIH(min)を基準に)用意しなければならない。」
internally・reffered・with respect to・bridgeあたりの意味がよく分からない。
なお誤訳の可能性を考えてオランダ語の原文があるかと探したのだがどうやら英語が原文のようである。

これを自分はこう理解した。

受信側はSDA線の立ち下がりから300ns間内部的にHighと扱う。
よってSCKよりSDAが(300ns-立ち下がり時間)だけ早くてもよい。
立ち下がり時間の最大が300nsなので、都合余裕は0。

これは12F510で動作しない現状と食い違うが、上記の文章の解釈は他に思いつかない。
(「送信側がSDA線を300ns遅らせて駆動しなければならない」という説も見かけたが、それではinternallyでないのと、それはtHD:DATの下限が300nsと書けばよいことなので、別に注釈として書かれている説明がつかない。)
自分の解釈が間違っているのか、このデバイスが仕様に従っていないのか分からない。
まあどちらにせよ、諸悪の根源はI2Cの仕様書が分かりづらいせいだ。マスターの条件とスレーブの条件が混ざって書かれているし、0.9μsだの300nsだのと注釈で変な条件を追加するし、その注釈は文章の意味が取れない。

とそんなわけで不可解な点は残ったものの、まとめると、

・最大値が0.9μsだと思っていたが制限は無かった。
・最小値が0だが300nsの余裕があると思っていたが、文の解釈はよく分からず、現に余裕は無かった。
・石を変えて動かなくなったのは立ち下がりの速さの差のせい。

tHD:DATを長くしたところ、安定して動くようになった。
12F510でI2C液晶が動いた
(なお表示は温度計を作ろうとしていた時のダミー表示)

  • 同じカテゴリー(電子工作)の記事画像
    ゲームボーイの吸い出し機を作った (後編)
    ARMマイコンはじめました。
    SDカードから1セクタ読み取るまでの手順解説
    EEPROM書換え上限テスト
    最弱のPICマイコンでカレンダー
    PIC10F200 OSCCAL調整用コード
    同じカテゴリー(電子工作)の記事
     ゲームボーイの吸い出し機を作った (後編) (2017-01-16 22:44)
     ARMマイコンはじめました。 (2016-05-28 14:43)
     SDカードから1セクタ読み取るまでの手順解説 (2015-10-05 01:09)
     EEPROM書換え上限テスト (2014-11-17 08:06)
     最弱のPICマイコンでカレンダー_ちょっと短縮 (2014-11-02 04:03)
     最弱のPICマイコンでカレンダー (2014-10-30 01:12)
    URL欄を実験的に消してる間に廃止されてしまいました。まあいいか。
     
    <ご注意>
    書き込まれた内容は公開され、ブログの持ち主だけが削除できます。
    削除
    I2C液晶が動かない理由が分かった
      コメント(0)