火曜日, 10月 29, 2019

PIC24FV16KM202 w/microstick OLEDを使う

(追記始め)
以前の表示だが,かろうじてI2Cが接続できただけで,やっぱりどうもデータが化けている。いろいろデータの送り方を試行錯誤したが,最終的にはsaharaさんのページで紹介されていたマイクロチップのサポートページoled.zipをダウンロード。自分の環境に移植することで,うまく動くようになった。
本体メモリーにバッファを持つタイプ。描画スピードとかは少しずつテストしていこう。

やれやれ。ともかく,目標はクリアした。きれい! うれしい!!

ちなみに移植手段としては,saharaさんのページの通り,I2C初期化はMCCのコードに任せ,送信関数部分のレジスターの定義名などをPIC24FV16KM202用に修正しました。

ああ,振り返ってみると,これだけで動いたんだな。でもいい勉強になった。

あ,横5ドットの文字で,5ドットに続けて次の文字が書かれていたので,1ドット余白を作るようにしました。


amazonで買った,SSD1306の128*32です。
MPLAB X IDE v5.25
XC16 (v1.41) でした。

(追記終わり)

当面の目標であったOLEDだが,やっとPIC24FV16KM202で動き始めた。まだめちゃくちゃな表示だけど,うれしい!



参考にさせて頂いたwebページはたくさんあれど,とりあえず以下3つ。

http://www.eonet.ne.jp/~jr3tgs/oled_test.htm

https://neo-sahara.com/wp/2017/11/16/pic24fj64gb002-ssd1306gm009605/

https://tool-lab.com/make/pic-practice-40/

普通にMCCでMSSPを追加,生成された例をよく読んで,必要なコマンドを書いていったつもりだが,どうにも動かない。I2Cに適切に送り出していない。タイムアウトせず,反応待ちで止まっている感じ。

micro:bitでは,あっけなく表示できたので,OLEDの故障ではない。

MSSP1ではなくてMSSP2を使わないとうまくいかないPICもある,ということで試すもダメ。

そこで,上のSaharaさんのページに,こんなことが書いてあった。

 「基本的に、I2Cの初期化関連はMCCの吐いたコードに任せ、OLEDとのやり取りは参考にするコードの方をなるべく生かす。」

ということで,基本設定はMCCで行い,I2Cの基本はとっても理解しやすかったJR3TGSさんのページから移植することにした。

ビット定義等を修正しつつ,コンパイルエラーをとにかくなくす。動いた!

以下,MCCとソースの覚書

クロックは最速でOK

MSSP1の設定 High Speedで,Baud Rate Generatorの数字を調整して400kに合わせる。


以下をmain.cに記述。赤字は修正したところ。私の環境の都合で,日本語コメントは削除してコンパイルする必要があります。(冒頭の追記参照 結局これは使わず,別のものから移植しました)

void i2c_start() { 
    SSP1CON2bits.SEN = 1;
    while(SSP1CON2bits.SEN);
}


void i2c_stop() {
    SSP1CON2bits.PEN = 1;
    while(SSP1CON2bits.PEN);
}


void i2c_write(unsigned char byte) {
    IFS1bits.SSP1IF = 0; // レジスタ名をPIC24F用に修正

    SSP1BUF = byte;
    while(!IFS1bits.SSP1IF);
    SSP1CON1bits.CKP = 1;
}

void oled_ini(void) {
    i2c_start();
    i2c_write(0x78); // OLED slave address
    i2c_write(0x00); // Control byte Co=0, D/C#=0
    i2c_write(0x8D); // Set charge pump
    i2c_write(0x14); // Enable charge pump
    i2c_write(0xAF); // Display ON
    i2c_stop();


}

void oled_clr(void) {
    unsigned int i;

    i2c_start();
    i2c_write(0x78); // OLED slave address                                                             
    i2c_write(0x00); // Control byte Co=0, D/C#=0                                                      
    i2c_write(0x20); // Set memory addressing mode                                                     
    i2c_write(0x00); // Horizontal addressing mode                                                     
    i2c_write(0x21); // Set column address                                                             
    i2c_write(0x00); // Column start address 0                                                         
    i2c_write(0x7F); // Column end address 127d                                                        
    i2c_write(0x22); // Set page address                                                               
    i2c_write(0x00); // Page start address 0                                                           
    i2c_write(0x03); // Page end address 3d                                                            
    i2c_stop();

    i2c_start();
    i2c_write(0x78); // OLED slave address                                                             
    i2c_write(0x40); // Control byte Co=0, D/C#=1 (The following data bytes are stored at the GDDRAM)  

    for(i=0; i<512; i++) // 128 column * 4page                                                         
        i2c_write(0x00); // filled with 0 (OLED clear)                                                     

    i2c_stop();
}

int main(void)
{
    // initialize the device
    SYSTEM_Initialize();
   
    oled_ini();
    oled_clr();

    // sample print A

    i2c_start();
    i2c_write(0x78);
    i2c_write(0x40);
   
    i2c_write(0x7C);
    i2c_write(0x12);
    i2c_write(0x11);
    i2c_write(0x12);
    i2c_write(0x7C);
   
    i2c_stop();
   
   
    while (1) {
        _LATA0=(_RA1); // これはテスト用(ボタンを押したらLED消える)
    }

    return 1;
}

0 件のコメント: