PICkit 2を18F14K50に接続してプログラムする場合に供給されるVddは最大3.3vです。このため回路は3.3vの電源で動作するように作成しています。ですからLCD表示器も3.3v用を使用するのが鉄則です。 しかし、今回使用したLCD表示器は5v用です。このままだと、PICkit 2を接続してプログラムした後に、動作確認のためLCDに文字を表示するには、いちいち、電源電圧を5vに取り替えなければできません。 調べてみると、LCD表示器のコントロールロジックは、3.3vでも機能するのですが、液晶自体を駆動するバイアス電圧(Vo)に4v程度の電位差が必要なため、液晶が十分なコントラストを作り出すことができないようです。解決策として、LCD表示器の電源電圧Vddは3.3vのまま、液晶のバイアス端子(Vo)にマイナスの電位を加えると、LCDに文字表示することができました。 必要となる液晶バイアス用の負電圧を得るには、以下の方法が考えられます。
今回は、2番の電源IC、LTC1144、を使い負電圧を発生させました。LTC1144は、コンデンサ2個で簡単に負電圧を発生することができるチャージポンプ方式の電源ICです。なお、3番の方法が最も安価ですが、PICのPWM機能などを使用し、方形波を発生させるプログラムを組む必要があります。この例は、シリアル受信機の項目で採用しています。
写真にマウスを重ねると、液晶表示器下の配線が見られます。
文字を画面に表示するだけのプログラムです。
プログラムは、メインプログラム(main.c)とLCD表示ライブラリ(L_LCD.h、L_LCD.c)から構成されています。
L_LCD.c にLCD表示する手順が記載されており、
L_LCD.h には、クロックを変更した場合に手直しをするべき、遅延定数等が書かれています。メインプログラムは、これらライブラリに登録されている関数を呼び出して、文字を表示させます。
具体的には、以下の手順で表示します。
<プログラム>
main.c
//*********************************************************
// データをLCDに表示する。
// 1)Define I/O PORT
// PIC pin : LCD pin PIC pin : LCD pin
// PORTC(3) 7 : LCD(DB7)14 PORTC(4) 6 : LCD_(EN) 6
// PORTC(2)14 : LCD(DB6)13 GND : LCD_(RW) 5
// PORTC(1)15 : LCD(DB6)12 PORTC(5) 5 : LCD_(RS) 4
// PORTC(0)16 : LCD(DB4)11 VR : LCD_(Vo) 3
// +3.3v : LCD(Vdd) 2
// GND : LCD(Vss) 1
// 2)OSC
// 4MHz (内部クロック)
/
// Language: MPLABX XC8
// Target: PIC18F14K50
//*********************************************************
#include <xc.h>
#include "L_LCD.h"
//
#pragma config FOSC = IRC // 内部クロック
#pragma config USBDIV = OFF, CPUDIV = NOCLKDIV
#pragma config IESO = OFF, FCMEN = OFF, PLLEN = ON
#pragma config BORV = 30, BOREN = OFF, PWRTEN = OFF
#pragma config WDTPS = 32768, WDTEN = OFF
#pragma config MCLRE = OFF, HFOFST = OFF, XINST = OFF
#pragma config BBSIZ = OFF, LVP = OFF, STVREN = ON
#pragma config CP1 = OFF, CP0 = OFF, CPD = OFF, CPB = OFF
#pragma config WRT1 = OFF, WRT0 = OFF, WRTB = OFF, WRTC = OFF
#pragma config EBTR1 = OFF, EBTR0 = OFF, EBTRB = OFF
void main(void){
char msgStart[] ="LCD Test";
OSCCON = 0b01010010; // 内部クロック4Mhz
TRISC = 0b00000000;
LCD_int(); // LCD初期化
// --------------------------------------------
LCD_str(msgStart); // 1行目に表示
LCD_dat(' ');
LCD_dat('X');
// --------------------------------------------
LCD_posyx(1,0); // 2行目に表示
LCD_ROMstr("1234567890123456");
while(1);
}
L_LCD.h
//************************************************************* // LCD ライブラリ PIC18 // //************* I/O Define ********************** // #define LCD_DB LATC #define LCD_EN LATCbits.LATC4 #define LCD_RS LATCbits.LATC5 // //************* Delay ******************************************* // 必要とするディレイ時間をクロック周波数から計算し、 // 指定するために、クロック周波数を指定する。 //*************************************************************** #define _XTAL_FREQ 4000000 //******************************************************** //#define LCD_ROMstr LCD_str void LCD_dat(char); void LCD_cmd(char); void LCD_clr(void); void LCD_int(void); void LCD_str(char *); void LCD_ROMstr(const char *); void LCD_posyx(char,char); void LCD_hex(char); void LCD_hxH(char); void LCD_hxL(char);
L_LCD.c
///////////////////////////////////////////////
// 液晶表示ライブラリ for PIC18Fxxxx
// 以下の機能を提供
// LCD_int() ----- 初期化
// LCD_cmd(cmd) ----- コマンド出力
// LCD_dat(chr) ----- 1文字表示
// LCD_str(*char) ---- 文字列表示
// LCD_ROMstr(*str) -- ROM文字列表示
// LCD_posyx(y,x) ---- カーソル位置指定、行 y、横位置 x
// LCD_clr() ----- 全消去
// LCD_hex(chr) ----- 16進文字変換表示
//////////////////////////////////////////////
#include <xc.h>
#include "L_LCD.h"
/*
//-------- 上位4ビットをデータ出力 (Upper nibble接続)
void LCD_out(char c){
LCD_DB = (c & 0xF0) | (LCD_DB & 0x0F);
LCD_EN = 1; // Enable Hi
Delay1TCY(); // NOP
LCD_EN = 0; // Enable Low
}
*/
//-------- 上位4ビットをデータ出力 (Lower nibble接続)
void LCD_out(char c){
LCD_DB = (c>>4) | (LCD_DB & 0xF0);
LCD_EN = 1; // Enable Hi
NOP(); // NOP
LCD_EN = 0; // Enable Low
}
//-------- 1文字表示
void LCD_dat(char c){
LCD_RS = 1; // 表示データの送信
LCD_out(c); // 上位4ビット出力
LCD_out(c<<4); // 下位4ビット出力
__delay_us(50); // 50μsec
}
//-------- コマンド出力
void LCD_cmd(char c){
LCD_RS = 0; // コマンドデータの送信
LCD_out(c); // 上位4ビット出力
LCD_out(c<<4); // 下位4ビット出力
if(c & 0xFC) // 上位6ビットに1がある命令
__delay_us(50); // 50usec
else
__delay_ms(2); // 2msec ClearおよびHomeコマンド
}
//-------- 全消去
void LCD_clr(void){
LCD_cmd(0x01); //Clearコマンド出力
}
//-------- カーソル位置指定
void LCD_posyx(char ypos, char xpos){
unsigned char pcode;
switch(ypos & 0x03){
case 0: pcode=0x80;break;
case 1: pcode=0xC0;break;
case 2: pcode=0x94;break;
case 3: pcode=0xD4;break;
}
LCD_cmd(pcode += xpos);
}
//-------- 文字列出力
void LCD_str(char *str){
while(*str) //文字列の終わり(00)まで継続
LCD_dat(*str++); //文字出力しポインタ+1
}
// //-------- Rom 文字列出力
void LCD_ROMstr(const char *str){
while(*str) //文字列の終わり(00)まで継続
LCD_dat(*str++); //文字出力しポインタ+1
}
//-------- 16進文字変換表示
void LCD_hex(char c){
LCD_hxH(c);
LCD_hxL(c);
}
//****************************************************************
// LCD_hxL(char) 引数の下位4ビットの16進文字を表示
// LCD_hxH(char) 引数の上位4ビットの16進文字を表示
//****************************************************************
void LCD_hxL(char c){
c = c & 0x0F; // 下位4ビットを取り出す
if(c < 10){ // 9以下なら
c += 0x30; // '0'の文字コードを加える
}else{ // 10以上なら
c += (0x41-10); // (c-10)に
} // 'A'の文字コードを加える
LCD_dat(c);
}
void LCD_hxH(char c){ // 上位4ビットを下位に移動し
LCD_hxL(c >> 4); // 下位の16進文字を返す
}
//-------- 初期化
void LCD_int(void){
__delay_ms(40); //40msec
LCD_RS = 0; //コマンドの送信
LCD_out(0x30);__delay_ms(5); // 8bit mode set//5msec
LCD_out(0x30);__delay_ms(1); // 8bit mode set
LCD_out(0x30);__delay_ms(1); // 8bit mode set
LCD_out(0x20);__delay_ms(1); // 4bit mode set
LCD_cmd(0x2E); // DL=0 (4bit mode)
LCD_cmd(0x08); // Display off
LCD_cmd(0x0C); // Display on Cursor=1 Blink=0
LCD_cmd(0x06); // Entry Inc/Dec=1 Shift=0
LCD_cmd(0x01); // Clear
}