非常にはまっている。MSP430の初期設定から疑い始めてさらに沼に。。今回は、128x64に変えたということに併せてHUSB238という、少し怪しいICをI2Cにぶら下げているということも影響していて、HUSB238の通信も怪しく、OLED表示も怪しい、何が一体悪いのだと抜け出せない。
沼1:表示が崩れる)
今回、さらに大きな表示領域を求めて128x64をAmazonで2個購入。32が拡張されいるだけだと思いそのまま動かしたら、表示が怪しい。1個飛ばしだ。
連続データを送るcls関数では全データが表示されていたため、初期化が異なるのでは?という疑いを持つ前に、データの送信の方法からすべてを疑って、弄り回したが何も解決せず。最終的に、ssd1308もmbedライブラリを見て、この考えに至り、この点は解決した。初期化コードの1か所のみ。
//i2c_send(0xDA);i2c_send(0x02); // Set COM Pins hardware configuration (128x32 OLED)
i2c_send(0xDA);i2c_send(0x12); // Set COM Pins hardware configuration (128x64 OLED)
僕の初期化コードは、SSD1306のデータシートに記載のある最後の例をそのまま使用している。送り方、それとも値違い?訳が分からない。mbedのライブラリの中を探してみたらSSD1308があり、それを見ると初期化コードにいくつか違いがあった。クロックやChargePump設定が違ってたら表示しなかったりおかしくなるはずだから、一番疑わしいのはCOMの設定だろうと、ここにきてようやく察しがついた。
mbedのライブラリには、DAhの設定に12hが使われている。僕のは、02h。データシートのよると下記の記載がある
Set COM Pins | Hardware Configuration |
DAh | A[4]=0b, Sequential COM pin configuration A[4]=1b(RESET), Alternative COM pin configuration A[5]=0b(RESET), Disable COM Left/Right remap A[5]=1b, Enable COM Left/Right remap |
下記の記載
10.1.18 Set COM Pins Hardware Configuration (DAh)
このコマンドは、COM信号のピン構成をOLEDパネルのハードウェアレイアウトに一致するように設定します。 次の表は、さまざまな条件下でのCOMピン構成を示しています(MUX比= 64の場合)。
僕のコードは02hなので、Condition=1。。。なんとなくわかってきた。bit4はSequentialかAlternative、これは、ドライバの中が32構成で2つに分かれているので、2面分を上下で分けるのか、1ラインごと分離するかの設定だ。だから1個飛ばしの文字になっていて、clsで128x64このデータを送ればきちんとクリアできてるわけだ。
02h | 12h |
だから、今回使っているのは、1個飛ばしに表示されているから、12hに修正でいいのだ。128x32のOLEDの時は、一つのドライバで動かせるから02hでいいのだ。(基板の設定にもよるのかもしれないが、今回は12hに変えたら正常になった。)
沼2)表示がミスる、レジスタ読みがミスる
i2cでデータを送るのを失敗しているときがあるのか?、送ってからの時間待ちをかけても同じである。HUSB238へのデータ送信の間にOLEDへの送信を行うと正常に戻るが、それは解決にならんな。・・・
実は解決してない。オシロで見ていると(I2Cでコードできるオシロが欲しい!)、アドレス送信してスタートするはずだが、アドレスがおかしい時がある。というか、同じルーチンを繰り返すとおかしくなる、なぜなんだ!!!!。おかしくなったときは、i2cアドレスが00hになっており、それでありえないデータが読める、表示においてはありえないデータを送信している、ということになっているようだ。i2cデコードできるオシロがないので、エッジを数えました。画面も小さいし、疲れた。
で、なんで、間違ったアドレスになってしまうのか・・・、それがいまだわからない。
ここからすべてに疑いが出てしまった。今までコード、i2c制御が間違っているんじゃないか?、クロックの設定?、PCを変えてコンパイラが変わったせいか?、など、あらゆること。PCを新しくした際に、CCSをv8からv11に変えたのだが、それすら疑い始め、結局v8をインストールしている。
なぜ間違っているのかわからないが、これまで入れてなかったi2c制御のエラー処理を入れて回避できるようになった。送信時にACKが返ってなかったら、再送するようにした。そもそも、ACKが返らなくなる理由が不明だ。送信するタイミング早いからでもない。0.5sぐらいに一度送信するようにしてもダメで数回目から値が飛ばされる。
一つ気づいたことは、OLED表示送信とHUSB238データ送信を互いに繰り返すと、間違いが起こらないということ。(HUSB238、OLDE、HUSB238、OLED、、、の繰り返し)なぜか?、わからん。
回避コード
int i2c_start(unsigned char addr,unsigned char mode){
int tmp;
while(!(P1IN & BIT6));
USISRL = 0;
USICTL0 |= USIGE + USIOE;
USICTL0 &= ~USIGE;
tmp = i2c_send(addr<<1 | mode);
return tmp;
}
int i2c_send(unsigned char aData){
while(!(P1IN & BIT6));
USISRL = aData;
USICTL0 |= USIOE;
USICNT = 8;
while(!(USICTL1 & USIIFG));
USICTL0 &= ~USIOE;
USICNT = 1;
while(!(USICTL1 & USIIFG));
return USISRL & 1;
}
// 呼び出し時に回避策
while( i2c_start(LCD_ADDR,I2C_RW_WRITE) );
とりあえず。
コメントを追加