« PICでI2C - 液晶(LCD)ディスプレイ(ACM1602N1-FLW-FBW)に表示する | トップページ | I2C大気圧温度センサーLPS331の驚くべき分解能 »

2014年8月28日 (木)

PICでI2C - LCD(液晶)ディスプレイによる違い - ACM1602N1-FLW-FBWのソース付き

記事の最後にソースをつけました。次の記事にあるI2Cライブラリを使うことを前提にしています。

  「I2Cのソース - PIC12F1822/16F1705/16F1938/18F26K22 - LCD(ACM1602)を例にして

タイトルにある四つのPICで動作を確認してあります。

(2014.11.24)
-------

このLCDを使用したサーミスタ温度計の記事を書きました。

  「PICで作るお手軽サーミスタ温度計 (2)

LCDの表示部分も含んだソース一式もダウンロードできるようになっています。

(2014.09.22)
-------

前記事「PICでI2C - 液晶(LCD)ディスプレイ(ACM1602N1-FLW-FBW)に表示する」でソースをダウンロードできるようにしますと書いたのですが、探せばソースはいくらでもあるので今回使った機種と「きむ茶工房ガレージハウス - 秋月電子I2C接続小型LCDモジュールに表示を行う 」にある機種の違いだけ紹介しておきます。

このI2Cのディスプレイというのは従来のLCDディスプレイにI2Cのインターフェースを追加したものそれもPICを使ってIC2を実現したものみたいです。
だったらインターフェースを統一すればいいだろうにと思うのですがいろいろと違いがありました。

なお「I2C薄型液晶ディスプレイ(LCD)・AQM1602XAの使い方」にあるようにAQM1602XAはこのACM1602N1に近いのですが、それでもやっぱり違ってるところがあります。

-----

もちろんデバイスのアドレスは違います。二つ以上使うのであれば違ってないと困るのですが、同じディスプレイを二つ以上使おうとするとこんどはアドレスがかち合うので困ります。アドレス変換ボードとか売っていないのでしょうか。

まずコマンドの出し方が違っていました。

     ans = I2C_Start(LCD_ADRES,RW_0);     // スタートコンディションを発行する
     if (ans == 0) {
          // command word の送信
#ifdef ACM1602
          I2C_Send(0b00000000) ;             // control byte の送信(コマンドを指定)
#else
          I2C_Send(0b10000000) ;             // control byte の送信(コマンドを指定)
#endif
          I2C_Send(c) ;                      // data byte の送信
     }
     I2C_Stop() ;                            // ストップコンディションを発行する

画面のクリアやカーソル位置の設定方法(インストラクション)は同じでした。

データ送信のときのコントロールバイトも違います。
     ans = I2C_Start(LCD_ADRES,RW_0);     // スタートコンディションを発行する
     if (ans == 0) {
          // command word の送信
#ifdef ACM1602
          I2C_Send(0b10000000) ;             // control byte の送信(データを指定)
#else
          I2C_Send(0b11000000) ;             // control byte の送信(データを指定)
#endif
          I2C_Send(c) ;                      // data byte の送信
     }
     I2C_Stop() ;                            // ストップコンディションを発行する

ACM1602は複数バイトのデータは送信できないようです。

#ifdef ACM1602
     while(*s) {
          LCD_Putc(*s++);
     }
#else
     ans = I2C_Start(LCD_ADRES,RW_0);     // スタートコンディションを発行する
     if (ans == 0) {
           I2C_Send(0b11000000) ;             // control byte の送信(データを指定)
           while(*s) {
               I2C_Send(*s++) ;              // data byte の送信(連続送信)
               __delay_us(26) ;
           }
     }
     I2C_Stop() ;                            // ストップコンディションを発行する
#endif

これはユーザーキャラクターを定義するときも同じです。

初期化はこんな感じです。

#ifdef ACM1602
    __delay_ms(40) ;    // 電源ON後40msまで待ってから初期化

    command(0x01);      // Clear Diplay.
    __delay_ms(5) ;     // 5ms待ちます。

    command(0x38);      // Function Set.
    __delay_ms(5) ;     // 5ms待ちます。
                        // 0b000x0000; DL; Interface Data length. 8bits/4bits
                        // 0b0000x000; N;  Numbers of display line. 2-line/1-line
                        // 0b00000x00; F;  Display font type. 5x10dots/5x8dots

    command(0x0c);      // Display ON/OFF Control.
    __delay_ms(5) ;     // 5ms待ちます。
                        // 0b00000x00; D;  Set display on/off.
                        // 0b000000x0; C;  Set curthor on/off.
                        // 0b0000000x; B;  Set blinking of curthor on/off.

    command(0x06);      // Entry Mode Set.
    __delay_ms(5) ;     // 5ms待ちます。
                        // 0b000000x0; I/D;Assign curthor moving direction.
                        // 0b0000000x; I/D;Enable the shift of entire display.

#else
     __delay_ms(40) ;    // 電源ON後40msまで待ってから初期化
     command(0x38) ;     // function set           : データ線は8本・表示は2行・フォントは5x8ドット
     command(0x39) ;     // function set           : 拡張コマンドの設定を有効にする
     command(0x14) ;     // Internal OSC frequency : バイアスの選択と内部OSC周波数の調整
     command(0x70) ;     // Contrast set           : コントラスト調整データ(下位4ビット)
     command(0x56) ;     // Contrast set           : 昇圧回路有効、コントラスト調整データ(上位2ビット)
     command(0x6C) ;     // Follower control       : フォロア回路をON、増幅率の調整を行う
     __delay_ms(200) ;   // 電力が安定するまで待つ
     command(0x38) ;     // function set           : 拡張コマンドを設定を無効にする
     command(0x0c) ;     // display control        : 画面表示はON・カーソル表示はOFF・カーソル点滅はOFF
     command(0x06) ;     // entry mode set         : 文字を表示した次にカーソルを移動するを指示
#endif

いちばん苦労したのは最後に書いた初期化です。いろいろやってみてやっと“正解”が見つかりました。

それと複数バイトのデータが送れないというのも最初気付かずちょっと手間取ってしまいました。

------

関連
  「PICでI2C - ADコンバーター・MCP3425の使い方
  「PICで平方根 - 白金薄膜抵抗で温度を測る
  「PICでI2C - 液晶(LCD)ディスプレイ(ACM1602N1-FLW-FBW)に表示する
  「PICでI2C - LCD(液晶)ディスプレイによる違い
  「PICでI2C - 1 (温度計を作る)
  「I2Cデバイス・アドレス一覧
  「I2C大気圧温度センサーLPS331の驚くべき分解能
  「海面更生気圧を気象庁とくらべてみた - I2C大気圧温度センサーLPS331
  「サーミスタによる温度測定の精度
  「サーミスタ温度計の精度を調べる - 1
  「ミニ恒温槽の作成に向けて - 1
  「炭素皮膜抵抗の温度係数を測定する話

-----

参考

  「きむ茶工房ガレージハウス - PICの動かせ方入門はこちら - 16F1938覚書
  「きむ茶工房ガレージハウス - I2C通信の実験
  「きむ茶工房ガレージハウス - 気圧センサーで大気圧と標高を測定して見ます(MPL115A1)(MPL115A2)」
  「きむ茶工房ガレージハウス - 秋月電子I2C接続小型LCDモジュールに表示を行う

----------------
ACM1602lib.h

// ACM1602lib.h
// I2C接続LCD関数ライブラリ用インクルードファイル
// ソースは次のサイトもものを参考にさせていただきました。
// きむ茶工房ガレージハウス
// http://www.geocities.jp/zattouka/GarageHouse/Top.htm
// 秋月電子通商 ACM1602N1-FLW-FBW
// 16文字x2行LCDモジュール バックライト付
#ifndef _ACM1602_H_
#define _ACM1602_H_
#define LCD_ADRES 0x50
void LCD_Clear(void) ;
void LCD_SetCursor(int col, int row) ;
void LCD_Putc(char c) ;
void LCD_Puts(const char * s) ;
void LCD_CreateChar(int p,char *dt) ;
void LCD_Init() ;
#endif

--------------------

ACM1602lib.c

// ソースは次のサイトのものを使わせいただきました。
// きむ茶工房ガレージハウス
// http://www.geocities.jp/zattouka/GarageHouse/Top.htm
// 気圧センサーで大気圧と標高を測定して見ます(MPL115A1)(MPL115A2)
// http://www.geocities.jp/zattouka/GarageHouse/micon/MPLAB/16F1938/Pressure/Pressure2.htm
// PIC16F1938
// 秋月電子通商 ACM1602N1-FLW-FBW
// 16文字x2行LCDモジュール バックライト付
// S1.01  http://seppina.cocolog-nifty.com/blog/
/*******************************************************************************
*  skI2CLCDlib - I2C接続LCD関数ライブラリ                                *
*             このライブラリは、秋月電子16文字x2行LCDモジュール バックライト付用です。 *
*                                                                              *
*    LCD_Init      - LCDの初期化を行う処理                                  *
*    LCD_Clear     - LCDモジュールの画面を消す処理                          *
*    LCD_SetCursor - LCDモジュール画面内のカーソル位置を移動する処理        *
*    LCD_Putc      - LCDにデータを1バイト出力する処理                      *
*    LCD_Puts      - LCDに文字列データを出力する処理                        *
*    LCD_CreateChar - オリジナルのキャラクタを登録します                       *
*                                                                              *
*    メモ:__delay_us() and __delay_ms() を使用しているので "MyDef.h" に *
*         "#define _XTAL_FREQ 8000000"が記述されています、                     *
*         8MHz以外のCPUクロックにする人は書き換えましょう。                    *
* ============================================================================ *
*  VERSION DATE        BY                    CHANGE/COMMENT                    *
* ---------------------------------------------------------------------------- *
*  1.00    2013-07-25  きむ茶工房(きむしげ)  Create                            *
*  2.00    2013-09-21  for ACM1602 by Seppina                              *
* ============================================================================ *
*  PIC PIC16F1938 (このライブラリ自体は他のPICでもOKと思います)      *
*  MPLAB IDE(V8.84)                                                            *
*  MPLAB(R) XC8 C Compiler Version 1.00                                        *
*******************************************************************************/
#include <xc.h>
#include "MyDef.h"
#include "I2Clib.h"
#include "ACM1602lib.h"
// LCDにコマンドを発行する処理
void command(unsigned char c)
{
     int  ans ;
     ans = I2C_Start(LCD_ADRES,RW_0);     // スタートコンディションを発行する
     if (ans == 0) {
          // command word の送信
          I2C_Send(0b00000000) ;             // control byte の送信(コマンドを指定)
          I2C_Send(c) ;                      // data byte の送信
     }
     I2C_Stop() ;                            // ストップコンディションを発行する
     __delay_us(26) ;
}
/*******************************************************************************
*  LCD_Clear( )                                                                *
*    LCDモジュールの画面を消す処理                                          *
*******************************************************************************/
void LCD_Clear(void)
{
     command(0x01) ;     // Clear Display : 画面全体に20Hのスペースで表示、カーソルはcol=0,row=0に移動
     __delay_ms(5) ;  // LCDが処理(2.16ms)するのを待ちます
}
/*******************************************************************************
*  LCD_SetCursor(col,row)                                                      *
*    LCDモジュール画面内のカーソル位置を移動する処理                        *
*                                                                              *
*    col : 横(列)方向のカーソル位置(0-7)                                       *
*    row : 縦(行)方向のカーソル位置(0-1)                                       *
*******************************************************************************/
void LCD_SetCursor(int col, int row)
{
     int row_offsets[] = { 0x00, 0x40 } ;
     command(0x80 | (col + row_offsets[row])) ; // Set DDRAM Adddress : 00H-07H,40H-47H
}
/*******************************************************************************
*  LCD_Putc(c)                                                                 *
*    文字列は、NULL(0x00)まで繰返し出力します。                                *
*                                                                              *
*    c :  出力する文字データを指定                                             *
*******************************************************************************/
void LCD_Putc(char c)
{
     int  ans ;
     ans = I2C_Start(LCD_ADRES,RW_0);     // スタートコンディションを発行する
     if (ans == 0) {
          // command word の送信
          I2C_Send(0b10000000) ;             // control byte の送信(データを指定)
          I2C_Send(c) ;                      // data byte の送信
     }
     I2C_Stop() ;                            // ストップコンディションを発行する
     __delay_us(26) ;
}
/*******************************************************************************
*  LCD_Puts(*s)                                                                *
*    LCDに文字列データを出力する処理                                        *
*    文字列は、NULL(0x00)まで繰返し出力します。                                *
*                                                                              *
*    *s :  出力する文字列のデータを格納した場所のアドレスを指定                *
*******************************************************************************/
void LCD_Puts(const char * s)
{
     int  ans ;
     while(*s) {
          LCD_Putc(*s++);
     }
}
/*******************************************************************************
*  LCD_CreateChar(p,*dt)                                                       *
*    オリジナルのキャラクタを登録します                                        *
*                                                                              *
*    p   : 登録する場所の指定(0〜5の6ヶ所のみ)                              *
*    p   : 登録する場所の指定(0〜5の6ヶ所のみ)                              *
*    *dt : 登録したいキャラクタのデータを格納したバッファを指定                *
********************************************************************************/
// **** ACM602では未検証です ****
void LCD_CreateChar(int p,char *dt)
{
    command(0x40 | p << 3 );
    __delay_ms(5) ;
    for (int i=0; i < 8; i++) {
         LCD_Putc(*dt++);
    }
}
/*******************************************************************************
*  LCD_Init( )                                                                 *
*    LCDの初期化を行う処理                                                  *
*******************************************************************************/
void LCD_Init()
{
 
    command(0x01);      // Clear Diplay.
    __delay_ms(5) ;     // 5ms待ちます。
    command(0x38);      // Function Set.
    __delay_ms(5) ;     // 5ms待ちます。
                        // 0b000x0000; DL; Interface Data length. 8bits/4bits
                        // 0b0000x000; N;  Numbers of display line. 2-line/1-line
                        // 0b00000x00; F;  Display font type. 5x10dots/5x8dots
    command(0x0c);      // Display ON/OFF Control.
    __delay_ms(5) ;     // 5ms待ちます。
                        // 0b00000x00; D;  Set display on/off.
                        // 0b000000x0; C;  Set curthor on/off.
                        // 0b0000000x; B;  Set blinking of curthor on/off.
    command(0x06);      // Entry Mode Set.
    __delay_ms(5) ;     // 5ms待ちます。
                        // 0b000000x0; I/D;Assign curthor moving direction.
                        // 0b0000000x; I/D;Enable the shift of entire display.
     LCD_Clear() ;       // Clear Display          : 画面を消去する
}

------------------------------

« PICでI2C - 液晶(LCD)ディスプレイ(ACM1602N1-FLW-FBW)に表示する | トップページ | I2C大気圧温度センサーLPS331の驚くべき分解能 »

趣味の電子工作」カテゴリの記事

コメント

この記事へのコメントは終了しました。

トラックバック

« PICでI2C - 液晶(LCD)ディスプレイ(ACM1602N1-FLW-FBW)に表示する | トップページ | I2C大気圧温度センサーLPS331の驚くべき分解能 »

フォト

サイト内検索

  • 記事を探されるんでしたらこれがいちばん早くて確実です。私も使ってます (^^;; 検索窓が表示されるのにちょっと時間がかかるのはどうにかしてほしいです。

新着記事

リンク元別アクセス数

  • (アクセス元≒リンク元、原則PCのみ・ドメイン別、サイト内等除く)

人気記事ランキング

  • (原則PCのみ、直近2週間)
無料ブログはココログ