ちょっと、この記事は古いです。。。だいぶ前に書いたものを持ってきたので。。
デジタルノギスの表示部を取り出そうと思い、小さい液晶を探した所、秋月さんにI2Cタイプの小型の物があり、それを使う事にしました。ところで、I2Cでどうやって使うのって所から始めました。う〜ん実は判っていたようでいざ使おうとすると、う〜んよくわからん。設定に有るいくつかの事が実際わからなかった。
I2C仕様書
http://www.nxp.com/documents/user_manual/UM10204_JA.pdf
数年前までは、philips(NXP)にライセンス料を払わないとI2Cを名乗れなかったのですが、ライセンスは切れているようですよ。
I2Cを動かす
秋月の説明書に有る、ここの部分
- スレーブアドレスは、0xC7です。(アドレス0111110+0(R/W))
- コントロールバイトで「データ、コマンドの指定」RSと「連続データの指定」Coを送信します。
- コマンドの場合RS=0、データはRS=1になります。データを複数送る場合Co=1で、最終データはCo=0です。
特に最後の「データを複数送る場合Co=1で、最終データはCo=0です。」の部分。言っている事は判るのだが、データって0~FFまで有るわけだから、連続で送ったらコントロールかデータかなんて判らんやんか。これはつまり、最終データのときはCo=0としなはれということで、連続してデータを送る場合は、最後のデータを送りきったら、STOP状態を作ってのみ終了できるということ。と理解しておこう。下の表が参考になるのだろう。
- 一つのバスに複数デバイスをぶら下げる事が出来るのと、MasterになったりSlaveになったりするので、SDA,SCLともOpenDrain。PullUpする必要がある。
- データ列の最初にアドレスを指定する。
- データは8bit、MSBファースト固定の模様
- 8bitごとにACKを返す(Slave->Master)。ACKは1bit。Masterだけど、1bit受信する。
- データ列の最初にStartビット(Start状態)、最後にStopビット(Stop状態)の遷移をもうける。
Co | Description |
---|---|
0 | Last control byte to be sent. Only a stream of data bytes is allowed to follow. This stream may only be terminated by a STOP condition. 最後の制御バイトが送信される。 データ·バイトのストリームのみをたどることができる。 このストリームはのみSTOP条件で終了させることができる。 |
1 | Another control byte will follow the data byte unless a STOP condition is received. STOP条件を受信しない限り、別の制御バイトはデータバイトに従います。 |
StartとStop
データ列の最初にStart状態があって、最後にStop状態があるということらしい。そのStartとStopを作り出すための手順がある。
ユーザマニュアルから、
- START 条件とは、SCL が High のときの SDA の High から Low への遷移です。
- START 条件は、シフト・レジスタの MSB を 0(ゼロ)にセットすることにより生成されます。
- USIGE ビットおよび USIOE ビットをセットすると、出力ラッチがトランスペアレントになり、シフト・レジスタの MSB がただちに SDA に供給され、ラインを Low にします
- USIGE をクリアすると、クロック供給ラッチ機能が再開され、データが SCL でシフト・アウトされるまで SDA 上で 0(ゼロ)を保持します。
void i2c_start(void){
while(!(P1IN & BIT6));
USISRL = 0;
USICTL0 |= USIGE + USIOE;
USICTL0 &= ~USIGE;
}
- STOP 条件とは、SCL が High のときの SDA の Low から High への遷移です。
- シフト・レジスタの MSB をセットし、USICNTx に 1をロードします。
- USIGE ビットおよび USIOE ビットをセットすると、出力ラッチがトランスペアレントになり、USISRL の MSB は SDA をアイドル状態に解放します。USIGEをクリアすると、出力ラッチに MSB が格納され、出力は USIOE をクリアすることによりディスエーブルにされます。
void i2c_stop(void){
USICTL0 |= USIOE;
USISRL = 0;
USICNT = 1;
while(!(USICTL1 & USIIFG));
USISRL = 0xff;
USICTL0 |= USIGE;
USICTL0 &= ~(USIGE + USIOE);
}
データを送る
データを送る場合は、最初のほうで説明があるように、RS=1になる。それで、連続してデータを送ることになるから、Co=0となる。
- Start状態
- Slaveアドレス送信
- Co=1,RS=0でコマンドSet指定(80h)
- Set DDRAM Addressコマンド(80h+Addr)
- Co=0,RS=1でデータSet指定(40h)
- データ、データ、、、、、
- Stop状態
途中で、DDRAMアドレスを変えるときは、Start状態からはじめる。。。。。う~ん、めんどい。
コメントを追加