« 誤解している人が多そうなコンデンサの“ESR”の意味 | トップページ | PICでSPI - SDカードの書き込みエラーの話 »

2015年4月 1日 (水)

I2C薄型液晶ディスプレイ(LCD)・AQM1602XAの使い方

表示したいものは日時、ADコンバータの測定値(10個)、気温(4個)、気圧(3個)、湿度、周波数/周期など20項目くらいあるので今使っているACM1602の16文字2行ではまったく足りません。そこで焼け石に水ですがLCDをもう一つサブディスプレイ的に追加しようと思います。

秋月に小さなバックライトなしのディスプレイがありお値段もそんなに高いものではなかったので買ってきました。

これがもう泣きたくなるくらい動きませんでした。

クロックが高すぎる、コマンド送出のタイミングに問題がある、....いろいろ考えたり試したりしたのですが、単に製品についているプログラム例に不備(私の理解不足?)があっただけでした (^^;;

--------

例によってきむしげさん(きむ茶工房ガレージハウス)の記事「秋月電子I2C接続小型LCDモジュールに表示を行うの」は参考になります。詳細な解説つきです。

ACM1602みたいなのは使ったことがあるから要点だけ知りたいという方はMt. Rubbleさんの「Arduino YunでLCD(I2C接続)を制御する。」の方がいいかもしれません。

=======

秋月電子通商の「I2C接続小型キャラクタLCDモジュール(3.3V/5V)ピッチ変換キット 」を使ったのですがまずLCDを変換基板に取り付ける必要があります(感覚的にはLCDに変換基板を取り付けるわけですが)

秋月の写真と見比べていただくとわかるのですが、変換基板を逆向き(裏返し)に取り付けています。実装したときの強度とかスペースを考えてわざとこうしています。別に間違ったわけではないです。
Imgp92211000

裏側から見るとこうなります。
Imgp92241000

ピン番号の向きとか自信が持てないときは参考にしてください。

テスト風景です。接続するのはSCL、SDAと電源(VSS、VDD)だけですからI2Cは簡単です。
Imgp92201000

右上の赤いかたまりは「24ビットバイナリーカウンター(12STAGEリップルキャリー・バイナリー・カウンター TC4040BP+SN74HC4040AP)」で作ったバイナリカウンタです。12bitカウンタ2台に分けてI2Cのクロックとデータを監視しています。どういうデータが送られているかなんてわからないのですが、なんとなくデータを送られていそうだということぐらいは確認できます。

記事の最後にソースを付けておきます。
I2Cのソース - PIC12F1822/16F1705/16F1938/18F26K22 - LCD(ACM1602)を例にして」にあるI2Cライブラリを使うことを前提にしています。
ソースにも書いてあるように全体的にきむしげさん(「きむ茶工房ガレージハウス」) のソースのパクリです。

ソースは四機種分ありますが、今回はPIC18F26K22だけしか確かめていません。他のでもたぶん動くと思います。そう言えばCG RAMの書き込みも確かめていません(ふだん使わないもので....)

ソースで注意した方がいいところは赤でマークしてあります。

-------

関連

全般
  「記事一覧(測定、電子工作、天文計算
    「趣味の電子工作
      「PIC
    「趣味の実験
    「趣味の気象観測

PIC
  「PIC+SPI+I2C 自記温湿度計+気圧計+8ch電圧計+周波数カウンタ(技術要素一覧)
  「PIC+SPI+I2C 自記温湿度計+気圧計+8ch電圧計のソース - main()

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

AQM1602lib.h

// 秋月電子通商 AQM1602XA-RN-GBW
// I2C接続薄型16文字x2行液晶
//  Sitronix ST7032 CONTROLED
// ソースは次のサイトのものを参考にさせていただきました。
// きむ茶工房ガレージハウス
// http://www.geocities.jp/zattouka/GarageHouse/Top.htm
// Mt. Rubble
// Arduino YunでLCD(I2C接続)を制御する。
// http://blogs.yahoo.co.jp/mattsu1045/55280011.html
#ifndef _AQM1602_H_
#define _AQM1602_H_
#define LCD_ADRES 0x3E
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 /* AQM1602LIB_H */
AQM1602lib.c

// 秋月電子通商 AQM1602XA-RN-GBW
// I2C接続薄型16文字x2行液晶
//  Sitronix ST7032 CONTROLED
// ソースは次のサイトのものを参考にさせていただきました。
// きむ茶工房ガレージハウス
// http://www.geocities.jp/zattouka/GarageHouse/Top.htm
// Mt. Rubble
// Arduino YunでLCD(I2C接続)を制御する。
// http://blogs.yahoo.co.jp/mattsu1045/55280011.html
/*******************************************************************************
*  skI2CLCDlib - I2C接続LCD関数ライブラリ                                *
*             このライブラリは秋月電子通商 AQM1602XA-RN-GBW用です。 *
*                                                                              *
*    LCD_Init      - LCDの初期化を行う処理                                  *
*    LCD_Clear     - LCDモジュールの画面を消す処理                          *
*    LCD_SetCursor - LCDモジュール画面内のカーソル位置を移動する処理        *
*    LCD_Putc      - LCDにデータを1バイト出力する処理                      *
*    LCD_Puts      - LCDに文字列データを出力する処理                        *
*    LCD_CreateChar - オリジナルのキャラクタを登録します                       *
*                                                                              *
*******************************************************************************/
#include <xc.h>
#include "MyDef.h"
#include "I2Clib.h"
#include "AQM1602lib.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() ;                            // ストップコンディションを発行する
}
/*******************************************************************************
*  LCD_Clear( )                                                                *
*    LCDモジュールの画面を消す処理                                          *
*******************************************************************************/
void LCD_Clear(void)
{
     command(0x01) ;     // Clear Display
     __delay_ms(2) ;
}
/*******************************************************************************
*  LCD_SetCursor(col,row)                                                      *
*    LCDモジュール画面内のカーソル位置を移動する処理                        *
*                                                                              *
*    col : 横(列)方向のカーソル位置(0-7)                                       *
*    row : 縦(行)方向のカーソル位置(0-1)                                       *
*******************************************************************************/
void LCD_SetCursor(int col, int row)
{
     int row_offsets[] = { 0x00, 0x40 } ;
// Set DDRAM Adddress : 00H-0FH,40H-4FH
     command(0x80 | (col + row_offsets[row])) ;
}
/*******************************************************************************
*  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(0b01000000) ;             // control byte の送信(データを指定)
          I2C_Send(c) ;                      // data byte の送信
     }
     I2C_Stop() ;                            // ストップコンディションを発行する
}
/*******************************************************************************
*  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 : 登録したいキャラクタのデータを格納したバッファを指定                *
********************************************************************************/
// **** 未検証です ****
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()
{
    __delay_ms(40) ;
    // Function set
    command(0x38);
    // Function set
    command(0x39);
        // Internal OSC frequency
        command(0x14);
        // Contrast set
//      command(0x73);  // 3.3V
        command(0x76);  // 5V
        // POWER/ICON/Contrast control
//      command(0x56);  // 3.3V
        command(0x54);  // 5V
        // Follower control
        command(0x6C);
    // Function set
    command(0x38);
    // Display ON/OFF control
    command(0x0C);
    // Clear Display
    command(0x01);
    __delay_ms(2) ;
    // Entry Mode
    command(0x06);
}

main.c

#include <xc.h>
#include "MyDef.h"
#include "I2CLib.h"
#include "AQM1602lib.h"
// C:\Program Files (x86)\Microchip\xc8\v1.32\docs\chips\12f1822.html
#ifdef _12F1822
#pragma config FOSC = INTOSC
#pragma config WDTE = OFF
#endif
// C:\Program Files (x86)\Microchip\xc8\v1.32\docs\chips\16f1705.html
#ifdef _16F1705
#pragma config FOSC = INTOSC
#pragma config WDTE = OFF
#endif
// C:\Program Files (x86)\Microchip\xc8\v1.32\docs\chips\16f1938.html
#ifdef _16F1938
#pragma config FOSC = INTOSC
#pragma config WDTE = OFF
#endif
// C:\Program Files (x86)\Microchip\xc8\v1.32\docs\chips\18f26k22.html
#ifdef _18F26K22
#pragma config FOSC = INTIO67
#pragma config WDTEN = OFF
#endif
void interrupt InterFunction( void )
{
     // I2C関連の割り込み処理
     InterI2C() ;
}
void main()
{
    unsigned short i=0;
    int j;
#ifdef _12F1822
    OSCCON = 0b01111010 ;  // 16MHz
    ANSELA = 0b00000000 ;
#endif
#ifdef _16F1705
    OSCCON = 0b01110010 ;  // 8MHz
    ANSELC = 0b00000000 ;
    RC0PPS = 0x10;
    RC1PPS = 0x11;
#endif
#ifdef _16F1938
    OSCCON = 0b01110010 ;  // 8MHz
#endif
#ifdef _18F26K22
    OSCCON = 0b01110010 ;  // 16MHz
    // for I2C
    ANSELCbits.ANSC3 = 0;
    ANSELCbits.ANSC4 = 0;
#endif
    InitI2C_Master() ;
    LCD_Init() ;
    LCD_Clear();
    while(1) {
        LCD_Putc((i & 0x3f) + 0x30);
        for( j=0; j < 12; j++ ) __delay_ms(40);
        i++;
        if( ( i & 0x1f ) == 0x10 ) {
            LCD_SetCursor(0, 1);
        } else if(( i & 0x1f ) == 0x00 ) {
            LCD_Clear();
        }
    }
}
// PIC18F26K22
// 01 /MCLR .....(1), Pull-up 10k
// 02 RA0/AN0
// 03 RA1/AN1
// 04 RA2/AN2/DACOUT
// 05 RA3/AN3
// 06 RA4
// 07 RA5/AN4
// 08 VSS
// 09 RA7
// 10 RA6/OSC2/CLKO
// 11 RC0
// 12 RC1
// 13 RC2
// 14 RC3/SCL1.....I2C Clock, Pull-up 5k
// 15 RC4/SDA1.....I2C Data, Pull-up 5k
// 16 RC5/SDO1
// 17 RC6/TX1
// 18 RC7/RX1
// 19 VSS .....(3)
// 20 VDD .....(2)
// 21 RB0/INT0
// 22 RB1/SCL2
// 23 RB2/SDA2
// 24 RB3/SDO2
// 25 RB4
// 26 RB5
// 27 RB6/TX2/PGC .....(5)
// 28 RB7/RX2/PGD .....(4)
MyDef.h

/*
* File:   MyDef.h
* Author: Seppina
*
* Created on 2014/11/22, 14:38
*/
#ifndef MYDEF_H
#define MYDEF_H
// http://www.microchip.jp/docs/41406B_JP.pdf
#ifdef _12F1822
#define _XTAL_FREQ 16000000
#define MySSPADD    0x27
#define SSPIE   SSP1IE
#define SSPIF   SSP1IF
#define BCLIE   BCL1IE
#define BCLIF   BCL1IF
#endif
// http://ww1.microchip.com/downloads/en/DeviceDoc/40001729A.pdf
// http://ww1.microchip.com/downloads/jp/DeviceDoc/40001722A_JP.pdf
// (下は16F1703のものですが参考になります。これもきむしげさん情報です)
#ifdef _16F1705
#define _XTAL_FREQ 8000000
#define MySSPADD    0x13
#define SSPIE   SSP1IE
#define SSPIF   SSP1IF
#define BCLIE   BCL1IE
#define BCLIF   BCL1IF
#endif
// http://ww1.microchip.com/downloads/en/DeviceDoc/40001574C.pdf
#ifdef _16F1938
#define _XTAL_FREQ 8000000
#define MySSPADD    0x13
#endif
// http://ww1.microchip.com/downloads/en/DeviceDoc/41412F.pdf
#ifdef _18F26K22
#define _XTAL_FREQ 16000000
#define MySSPADD    0x27
#endif
#endif /* MYDEF_H */


« 誤解している人が多そうなコンデンサの“ESR”の意味 | トップページ | PICでSPI - SDカードの書き込みエラーの話 »

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

コメント

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

トラックバック


この記事へのトラックバック一覧です: I2C薄型液晶ディスプレイ(LCD)・AQM1602XAの使い方:

« 誤解している人が多そうなコンデンサの“ESR”の意味 | トップページ | PICでSPI - SDカードの書き込みエラーの話 »

フォト

サイト内検索

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

新着記事

リンク元別アクセス数

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

人気記事ランキング

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