コピペで超簡単!PICマイコンでI2C接続のLCD(AQM1602)を使う【PIC16F1938】

Pocket

完成プログラム

文字を表示させるには、上記で作成したLCD_str()に配列を渡すだけで実現できます。LCDに「Hello,world!」と表示させたいときは、


  char moji[] = "Hello,world!";
  LCD_str(moji);

とすれば終わりです。

main部分

main部分は、LCDの初期化をして、while文の中で”Hello, PIC world Wak-tech”を繰り返すようにしてみました。以下のようになります。


  int main(void){
    PICinit();      //PICを初期化
    LCD_Init();
    writeCommand(0x01); //画面をクリア
    __delay_ms(20);
    writeCommand(0x02); //ホームへカーソル移動
    __delay_ms(2); // LCD側の処理待ち

    while(1){
        writeCommand(0x02);   //ホームへカーソル移動
        LCD_str(moji);
        writeCommand(0x40+0x80); //2列目へ移動
        __delay_ms(200);
        LCD_str(moji2);
        __delay_ms(1000);
        writeCommand(0x01); //画面をクリア
        __delay_ms(200);
    }
    return 0;
  }
  

途中、writeCommand()がたくさん出てきてますね。これは、LCDの機能を呼び出す関数(コマンド)です。次回色々なコマンドを解説します。特に、writeCommand(0x01)はLCDの画面を全てまっさらにするコマンドだということは知っておいて損はないです。

全体コード(そのままコピペで動く)

上記のすべての関数を組み込んだコードです。これをコピペして書き込めば、動画のように文字が表示されるはずです。


    // PIC16F1938 Configuration Bit Settings

    // 'C' source line config statements

    // CONFIG1
    #pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
    #pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
    #pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
    #pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
    #pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
    #pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
    #pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
    #pragma config IESO = OFF       // Internal/External Switchover (Internal/External Switchover mode is disabled)
    #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)

    // CONFIG2
    #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
    #pragma config VCAPEN = OFF     // Voltage Regulator Capacitor Enable (All VCAP pin functionality is disabled)
    #pragma config PLLEN = ON// PLL Enable (4x PLL disabled)
    #pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
    #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
    #pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)

    // #pragma config statements should precede project file includes.
    // Use project enums instead of #define for ON and OFF.

    #include <xc.h>
    #include <pic16f1938.h>
    #define _XTAL_FREQ 32000000
    #define LCD_ADD 0x7C

    char moji[] = "Hello, PIC World!";
    char moji2[] = "Wak-tech";
    void I2C_Master_Init(const unsigned long c)
    {
      SSPCON1 = 0b00101000;
      SSPCON2 = 0;
      SSPADD = (_XTAL_FREQ/(4*c))-1;
      SSPSTAT = 0b00000000 ;    // 標準速度モードに設定する(100kHz)
    }

    void I2C_Master_Wait()
    {
      while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
    }

    void I2C_Master_Start()
    {
      I2C_Master_Wait();
      SEN = 1;
    }

    void I2C_Master_RepeatedStart()
    {
      I2C_Master_Wait();
      RSEN = 1;
    }

    void I2C_Master_Stop()
    {
      I2C_Master_Wait();
      PEN = 1;
    }

    void I2C_Master_Write(unsigned d)
    {
      I2C_Master_Wait();
      SSPBUF = d;
    }
    void writeData(char t_data){
        I2C_Master_Start();
        I2C_Master_Write(LCD_ADD);
        I2C_Master_Write(0x40);
        I2C_Master_Write(t_data);
        I2C_Master_Stop();
        __delay_ms(10);
    }
    void writeCommand(char t_command){
        I2C_Master_Start();
        I2C_Master_Write(LCD_ADD);
        I2C_Master_Write(0x00);
        I2C_Master_Write(t_command);
        I2C_Master_Stop();
        __delay_ms(10);
    }
    void PICinit(){
      OSCCON = 0b01110000;
      ANSELA = 0b00000000;
      ANSELB = 0b00000000;
      TRISA  = 0b00000000;
      TRISB  = 0b00000000;
      TRISC  = 0b00011000;
      PORTA  = 0b00000000;    //2進数で書いた場合
      PORTB  = 0x00;          //16進数で書いた場合
    }
    void LCD_Init(){            //LCDの初期化
      I2C_Master_Init(100000);
      __delay_ms(400);
      writeCommand(0x38);
      __delay_ms(20);
      writeCommand(0x39);
      __delay_ms(20);
      writeCommand(0x14);
      __delay_ms(20);
      writeCommand(0x73);
      __delay_ms(20);
      writeCommand(0x52);
      __delay_ms(20);
      writeCommand(0x6C);
      __delay_ms(250);
      writeCommand(0x38);
      __delay_ms(20);
      writeCommand(0x01);
      __delay_ms(20);
      writeCommand(0x0C);
      __delay_ms(20);
    }

    void LCD_str(char *c) {     //LCDに配列の文字を表示
      unsigned char i,wk;
      for (i=0 ; ; i++) {
        wk = c[i];
        if  (wk == 0x00) {break;}
        writeData(wk);
      }
    }

    int main(void){
      PICinit();      //PICを初期化
      LCD_Init();
      writeCommand(0x01); //画面をクリア
      __delay_ms(20);
      writeCommand(0x02); //ホームへカーソル移動
      __delay_ms(2); // LCD側の処理待ち

      while(1){
          writeCommand(0x02);   //ホームへカーソル移動
          LCD_str(moji);
          writeCommand(0x40+0x80); //2列目へ移動
          __delay_ms(200);
          LCD_str(moji2);
          __delay_ms(1000);
          writeCommand(0x01); //画面をクリア
          __delay_ms(200);
      }
      return 0;
    }
  

次回

次回は、今回解説しなかったLCDのcommandについて解説します。例えば、文字を一文字ずつ右にずらす等の機能が備わっていて、それをPIC側から使う、ということをしていきます。お楽しみに!

関連記事   【PICマイコン】タイマー割り込みを使って時計を作る【PIC16F1938 TMR1】

次回>LCD(AQM1602)のコマンドを使って、文字を移動させてみた【PIC16F1938】

Pocket

4件のコメント

  1. すばらしいですね。本当にコピー&ペーストでできました。
    アマゾンで次の二個を購入しましたが、PICマイコン駆動のネット資料が少なく断念。
    ・EasyWordMall 1602 LCD ブラック IIC/I2C/TWI/SPI シリアル インタフェース ボード モジュール
    ・KKHMF DC 5V 1602 LCD ディスプレイモジュール 16×2キャラクタ LCDブルーブラックライト
    こちらのページを参考にLCDを買いなおし、あっさり出来たので拍子抜けしてしまいました。
    可能でしたら、上記モジュールとLCDユニットのサンプルも作っていただけるとありがたいです。

  2. ありがとうございました。

    1938が無かったので、手持ちのPIC16F1936で組んでみたのですが、最初、20番ピンにVDDを繋いだ時は、うまくいかず・・接触不良かと思い、20番ピンのVDD抜き差していたところ 21番ピンに VDDが接触した際 HELLO PIC WORLD WAK TECH と表示されました。

    こんなにあっさりとできるとは 思ってもみなかったので、小躍りして喜びました。
    ありがとうございました。

    VDD ピンの20番、21番については、何かの間違いだろうと 手持ちの2個の 1936にプログラムを入れてみましたが、やはり同じで、21番ピンに電源を入れないと動きません。
    19番のVSSは、接続してもしなくても変わりません。

    ブレッドボードがおかしいのか??と思い、新品のブレッドボードでも組んでみましたが、一緒の状況です。
    2台のブレッドボードで 1936のVDDが21番で 現在 「HELLO PIC WORLD WAK TECH」と表示中です。

    ご学業のかたわら、こんなページを作って頂いて 本当に頭が下がる思いです。
    ありがとうございました。ご本業でのご活躍もお祈りします・・・

    と いいつつも・・・ もし・・・・・上記の不可思議な症状・・心当たりがあれば ご教授頂ければ 幸いです。

    この状況の写真を 私のブログに載せておきますので、もし、お暇な折でも ご覧になって、ヒントでも頂ければ幸いです。

    1. 田崎様
      この度は弊サイトをご覧いただきありがとうございました!サイトも拝見させていただきました。無事動くようになり記事を書いた甲斐がありました。
      その状態で動くのは非常に不可解ですね…しかし写真を見る限り確かに21番ピンにVDDが接続されてますね。

      ソースコード中の
      #include の部分を
      #include に変更して試してみてもらえないでしょうか?

  3. 初めまして。I2CでLCDを制御したいと思い、いろいろ検索してヒットしました。
    PIC18F2620とXC8 1.45で開発しています。

    コピペでいけるか?と思ってやってみましたが、どうも下記関数で無限ループに入っていて、処理待ちになってしまいます。

    void I2C_Master_Wait()
    {
    while ((SSPSTAT & 0x04) ||(SSPCON2 & 0x1A)); //PENとSENが・・・
    }

    サイトでは SSPCON2 & 0x1F でしたが、どうもPENとSENがうまく0にならず、SSPCON2 & 0x1Aだとループに入らずに進んでくれます(LCDには表示されませんが・・・)
    I2C自体初めてで、「LCDが表示されない」という現象だけでどこから手を付けていいかも分かりません。
    お時間があるときにご教授ください。宜しくお願い致します。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です