<LCD自作定義文字の表示>

LCDの文字表示は、文字コードとパターンの対応表に記載されている文字を使っています。

SC2004Cの資料からの文字コードとパターンは次のようになっている(一部抜粋)
------------------------------------------------
     I 0000 I  0001 I 0010 I 0011 I 0100 I 0101
------------------------------------------------
0000 ICGRAM1I       I      I  0   I  @   I  P
------------------------------------------------
0001 ICGRAM2I       I  !   I  1   I  A   I  Q
------------------------------------------------
0002 ICGRAM3I       I      I  2   I  B   I  R

しかし、文字コードとパターンの対応表に記載されていない↑などの文字はどうやって表示するのか?

調査したところ、表示方法が分かりましたので紹介します。


<使用PIC、LCD、LCDとPICの接続>

PIC:PIC16F688、LCD:SC2004C

LCDとPICの接続

LCD側ピン                                   PIC側ピン(PIC16F688)                      
 1.VSS(GND)                                   GND(14)
 2.VDD(+5V)                                   +5V(1)
 3.VLC(コントラスト) VRを接続して調整できる
 4.RS          レジスタ選択信号(H or L)----→ RC5(5)
 5.R/W     読・書信号(GND接続)            GND(14)
 6.E           イネーブル信号(H or L)  ----→ RC4(6)
 7.DB0         -下位4ビットデータバス
 8.DB1         -
 9.DB2         -
10.DB3         -
11.DB4         上位4ビットデータバス   ----→ RC0(10)
12.DB5         -                       ----→ RC1(9)
13.DB6         -                       ----→ RC2(8)
14.DB7         -                       ----→ RC3(7)

まずは、次のプログラムをビルドしてPICに書き込んで下さい、↑が表示されたと思います。
(このプログラムは文字コード0x03に↑を作成しています。)


プログラム中の<は半角に修正してください
----------------------------------------------------------------------------------------------------
#include <htc.h>
__CONFIG(FCMDIS & IESODIS & BORDIS & UNPROTECT & MCLREN & PWRTEN & WDTDIS & INTIO);
__IDLOC(0001);

#define _XTAL_FREQ 8000000	//8MHz
#define E RC4
#define RS RC5
#define DB4 RC0
#define DB5 RC1
#define DB6 RC2
#define DB7 RC3

ioport();
lcd_init();

main()
{
	OSCCON=0x70;	//8MHz
	ioport();
	lcd_init();	//LCDを初期化する

//自作文字の文字コード0x03
//   m_b75643210
PORTC=0b00000101; //文字コード(0x00-0x07)は、m_b10とl_b3の計3ビットで設定する
__delay_us(800);  //0x00:m_b00000100 l_b00000000 0x04:m_b00000110 l_b00000000
E=1;              //0x01:m_b00000100 l_b00001000 0x05:m_b00000110 l_b00001000
__delay_us(800);  //0x02:m_b00000101 l_b00000000 0x06:m_b00000111 l_b00000000
//   l_b75643210  //0x03:m_b00000101 l_b00001000 0x07:m_b00000111 l_b00001000
PORTC=0b00001000; 
__delay_us(800);
E=1;
__delay_us(800);

//ライン0書込み
PORTC=0b00100000;
__delay_us(800);
E=1;
__delay_us(800);
PORTC=0b00100100;
__delay_us(800);
E=1;
__delay_us(800);

//ライン1書込み
PORTC=0b00100000;
__delay_us(800);
E=1;
__delay_us(800);
PORTC=0b00101110;
__delay_us(800);
E=1;
__delay_us(800);

//ライン2書込み
PORTC=0b00100001;
__delay_us(800);
E=1;
__delay_us(800);
PORTC=0b00101111;
__delay_us(800);
E=1;
__delay_us(800);

//ライン3書込み
PORTC=0b00100000;
__delay_us(800);
E=1;
__delay_us(800);
PORTC=0b00100100;
__delay_us(800);
E=1;
__delay_us(800);

////ライン4書込み
PORTC=0b00100000;
__delay_us(800);
E=1;
PORTC=0b00100100;
__delay_us(800);
E=1;
__delay_us(800);

////ライン5書込み
PORTC=0b00100000;
__delay_us(800);
E=1;
__delay_us(800);
PORTC=0b00100100;
__delay_us(800);
E=1;
__delay_us(800);

////ライン6書込み
PORTC=0b00100000;
__delay_us(800);
E=1;
__delay_us(800);
PORTC=0b00100100;
__delay_us(800);
E=1;
__delay_us(800);

////ライン7書込み
PORTC=0b00100000;
__delay_us(800);
E=1;
__delay_us(800);
PORTC=0b00100000;
__delay_us(800);
E=1;
__delay_us(800);

//LCDの表示位置アドレス設定0x00
PORTC=0b00001000;
__delay_us(800);
E=1;
__delay_us(800);
PORTC=0b00000000;  //0x00
__delay_us(800);
E=1;
__delay_us(800);
//文字コード0x03の書込み
PORTC=0b00100000;
__delay_us(800);
E=1;
__delay_us(800);
PORTC=0b00100011;  //0x03
__delay_us(800);
E=1;
__delay_us(800);
E=0;
while(1);

}//main

ioport()
{
	TRISC=0x00;
	ANSEL=0x00;
	CMCON0=0x07;
}

lcd_init()		// LCDモジュール初期化
{ 
E=0;
__delay_ms(15);
PORTC=0b00000011; //1
E=1;
__delay_us(500);
E=0;

__delay_ms(5);
PORTC=0b00000011;//2
E=1;
__delay_us(500);
E=0;

__delay_us(200);
PORTC=0b00000011; //3
E=1;
__delay_us(500);
E=0;

PORTC=0b00000010; //4
E=1;
__delay_us(500);
E=0;

PORTC=0b00000010; //5
E=1;
__delay_us(500);
E=0;

PORTC=0b00001000; //6
E=1;
__delay_us(500);
E=0;

PORTC=0b00000000; //7
E=1;
__delay_us(500);
E=0;

PORTC=0b00001100; //8
E=1;
__delay_us(500);
E=0;

PORTC=0b00000000; //9
E=1;
__delay_us(500);
E=0;

PORTC=0b00000001; //10
E=1;
__delay_us(500);
E=0;

PORTC=0b00000000; //11
E=1;
__delay_us(500);
E=0;

PORTC=0b00000110; //12
E=1;
__delay_us(500);
E=0;
}
----------------------------------------------------------------------------------------------------

例えば、Aを表示するには、LCDの何行の何桁目に表示するかのアドレスを設定して、文字コードとパターンの
文字コード0x41(A)を書き込みます。

↑を表示するには、この↑を文字コードのCGRAM1(0x00)に作成します。(文字コードは0x00-0x07が使用出来ます)
作成出来ればLCDの何行の何桁目に表示するかのアドレスを設定して文字コード0x00(↑)を書き込めば表示出来ます。

CGRAMのアドレスセット
RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
0  0   0   1   b5  b4  b3  b2  b1  b0
b5-b3が文字コード b2-b0がラインdataのアドレス

<ビットパターン>(↑の例 横0-4の5bit縦0-7の8bit)
        43210
ライン0   -
ライン1  ---
ライン2 -----
ライン3   -
ライン4   -
ライン5   -
ライン6   -
ライン7 ここは空けておく

文字コード0x00に文字(↑)を書くイメージは次のような感じ
CG RAMアドレス(文字コード)に0x00をセットしてライン0からライン7のデータを書き込む

(↑の例)文字コード0x00

                    RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
CGRAM Address       0  0   0   1   0   0   0   0   0   0    文字コード(DB5-DB3 0x00)のラインdata0アドレス
writeラインdata0    1  0   0   0   0   0   0   1   0   0
writeラインdata1    1  0   0   0   0   0   1   1   1   0
writeラインdata2    1  0   0   0   0   1   1   1   1   1
writeラインdata3    1  0   0   0   0   0   0   1   0   0
writeラインdata4    1  0   0   0   0   0   0   1   0   0
writeラインdata5    1  0   0   0   0   0   0   1   0   0
writeラインdata6    1  0   0   0   0   0   0   1   0   0
writeラインdata7    1  0   0   0   0   0   0   0   0   0

(↓の例)文字コード0x05

                    RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
CGRAM Address       0  0   0   1   1   0   1   0   0   0    文字コード(DB5-DB3 0x05)のラインdata0アドレス
writeラインdata0    1  0   0   0   0   0   0   1   0   0
writeラインdata1    1  0   0   0   0   0   0   1   0   0
writeラインdata2    1  0   0   0   0   0   0   1   0   0
writeラインdata3    1  0   0   0   0   0   0   1   0   0
writeラインdata4    1  0   0   0   0   1   1   1   1   1
writeラインdata5    1  0   0   0   0   0   1   1   1   0
writeラインdata6    1  0   0   0   0   0   0   1   0   0
writeラインdata7    1  0   0   0   0   0   0   0   0   0

*ライン0-7のアドレスはインクリメントするのでライン毎に設定しない、最初のDB2-DB0の000だけでいい。
(LCDの初期化でエントリーモードセットでI/D:1にしている)
プログラムの基本は、次の@−Cの手順で行います。

@CG RAMアドレスに0x00(文字コード)にセット(abcの3bitで設定、0x05ならa:1 b:0 c:1)
               c
PORTC=0b00000100;  //CGRAM AddsetはDB6:1(RC2) E:0(RC4)1 RS:0(RC5)
E=1;
      ba
PORTC=0b00000000;
E=1;

Aライン0-7の書込み(例↑)
//ライン0書込み
PORTC=0b00100000;
E=1;
PORTC=0b00100100;
//ライン1書込み
PORTC=0b00100000;
E=1;
PORTC=0b00101110;
//ライン2書込み
PORTC=0b00100001;
E=1;
PORTC=0b00101111;
//ライン3書込み
PORTC=0b00100000;
E=1;
PORTC=0b00100100;
//ライン4書込み
PORTC=0b00100000;
E=1;
PORTC=0b00100100;
//ライン5書込み
PORTC=0b00100000;
E=1;
PORTC=0b00100100;
//ライン6書込み
PORTC=0b00100000;
E=1;
PORTC=0b00100100;
//ライン7書込み
PORTC=0b00100000;
E=1;
PORTC=0b00100000;

BLCDの表示位置アドレス設定0x00
PORTC=0b00001000; //アドレス設定するときはDB7:1(RC3) RS:0(RC5)にする
E=1;              //1回目の書き込み
PORTC=0b00000000;  //0x00

CCGRAMアドレス(文字コード)0x00に作成した文字書込みRS:1(RC5)
PORTC=0b00100000;
E=1;
PORTC=0b00000000;

以上ですが、@ーCをそれぞれ関数にすれば、次のような表示も出来て応用が広がると思います。