PIC18F14K50の基本動作から応用プログラムまでを学びます。

ホーム
16F18313
16F18325
16F18346
16F1619
Curiosity
---
---
    
12F1822
16F1455
16F1459
18F14K50
18F26J50
dsPIC
その他
パラレル LCD表示器の接続

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に文字表示することができました。 必要となる液晶バイアス用の負電圧を得るには、以下の方法が考えられます。

5v用LCD表示器を3.3vで使用する
  1. 乾電池等の別電源を準備する。
  2. 電源ICを使い、3.3vから負電圧を発生させる。
  3. PICで矩形はを発生させ整流し、負電圧を発生させる。

今回は、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 には、クロックを変更した場合に手直しをするべき、遅延定数等が書かれています。メインプログラムは、これらライブラリに登録されている関数を呼び出して、文字を表示させます。
具体的には、以下の手順で表示します。

  1. LCD_int() で表示器を初期化し、
  2. LCD_posyx() で表示位置を指定し、
  3. LCD_dat()、LCD_str()、などの関数で文字を表示

<プログラム>
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
}