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

ホーム
16F18313
16F18325
16F18346
16F1619
Curiosity
---
---
    
12F1822
16F1455
16F1459
18F14K50
18F26J50
dsPIC
その他
I2C接続LCD表示器(ストロベリーリナックス社製)

16F1455に、I2Cで超小型16文字x2行のLCD表示器を接続しました。MSSPをI2C マスターモードで利用します。パラレル接続の場合は、6本の信号線、コントラスト調整線、電源の計9本の配線が必要ですが、I2C接続すれば、信号線は2本で済み、リセットと電源を含めても5本の配線です。パラレル接続のLCD表示器との共通性を持たせるI2C接続LCD表示器用の関数名と同じにしています。

LCD表示器のプログラム例

文字やアイコンを画面に表示するだけのプログラムです。プログラムは、メインプログラムとLCD表示関数から構成されています。また定義部門に電圧を変更したときに指定する画面コンスタント定数が定義されています。メインプログラムは、これら関数を呼び出して、文字やアイコンを表示させます。具体的には、以下の手順で表示します

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

*注意*
PIC16F1455のI2Cピンは、ICSPピンと同一です。 PICにプログラムするためPICkit3を接続したままにすると、このピンがPICkit3内部で4.7kΩの抵抗でプルダウンされるため、I2C機能が動作しません。 正常に動作させるには、PICにプログラムを書き込んだ後で、PICkit3を回路から取り外す必要があります。

<プログラム>

//  データをLCDに表示する。
//  ストロベリーリナックス液晶表
//    「LCD Disp Test」と液晶表示する。
//     1)Define I/O PORT
//                   --PIC16F1455--  --PIC16F1459--
//           SDA  :  PORTC(1) pin 9  PORTB(4) pin13
//           SCL  :  PORTC(0) pin10  PORTB(6) pin11
//     2)OSC
//         4MHz (内部クロック)
//
//    Language: MPLABX XC8
//    Target: PIC16F1455
// Copyright (c) 2012 iwamoto All Rights Reserved
//*********************************************************
//  調整用定数
//***********************************************
#define CONTRAST  0x2D          // for 3.3V
// #define CONTRAST  0x18               // for 5.0V
//
//***********************************************
//  アイコン定数
//***********************************************
#define i_Ant  0x4010           // アンテナ
#define i_Tel  0x4210           // 電話
#define i_Aud  0x4410           // 音声
#define i_Pulg  0x4610          // 接続
#define i_Up  0x4710            // Up
#define i_Dn  0x4708            // Down
#define i_UpDn  0x4718          // Down
#define i_Lock  0x4910          // 鍵
#define i_XFlag  0x4B10         // X旗
#define i_BatEMP  0x4D02        // バッテリー空
#define i_BatLOW  0x4D12        // バッテリー小
#define i_BatMID  0x4D1A        // バッテリー中
#define i_BatFUL  0x4D1E        // バッテリー満
#define i_Circle  0x4F10        // 三重丸
//***********************************************
#include <xc.h>
#define _XTAL_FREQ 4000000

//************* Config  ***********************************
#pragma config FOSC  = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP  = OFF
#pragma config BOREN = ON, CLKOUTEN = OFF, IESO  = OFF, FCMEN = OFF
#pragma config WRT = OFF, CPUDIV = NOCLKDIV, USBLSCLK = 48MHz, PLLMULT = 3x
#pragma config PLLEN = DISABLED, STVREN = ON, BORV = LO, LPBOR = OFF, LVP = OFF

//********************************************************
void i2cByteWrite(char, char, char);    // i2c byte送信
void i2cTxData(char);                   // i2c SSPBUF セット
void LCD_dat(char);                     // 1文字表示
void LCD_cmd(char);                     // コマンド出力
void LCD_clr(void);                     // 全消去
void LCD_int(void);                     // 初期化
void LCD_str(char *);                   // 文字列表示
void LCD_ROMstr(const char *);          // ROM文字列表示
void LCD_posyx(char,char);              // カーソル位置指定
void LCD_hex(char);                     // 6進文字変換表示
void LCD_icon_on(int icn);              // 指定アイコン ON
void LCD_icon_off(int icn);             // 指定アイコン OFF
void LCD_icon_clr(void);                // 全アイコン OFF

//////////// Main //////////////////////////////////
void main(void){
    char msgStart[] ="LCD Test";
    unsigned char num = 0;
    OSCCON = 0b00110100;           // 内部クロック4Mhz
    ANSELC = 0;                    // PortCをデジタルI/Oにする
    TRISC  = 0b11111111;           // PortCを入力I/Oにする
    SSPCON1 = 0x28;                // I2Cマスターモード指定
    SSPSTAT = 0x00;
    SSPADD  = 0x09;                // I2Cクロック周波数100KHz for 4MHz
    LCD_int();                     // LCD初期化
    // ------------------------------------------------------
    LCD_icon_clr();                // 全アイコン消去
    LCD_icon_on(i_Ant);            // アイコン点灯  アンテナ
    LCD_icon_on(i_Lock);           //               鍵
    LCD_icon_on(i_BatFUL);         //               バッテリー満
    LCD_icon_on(i_Circle);         //               三重丸
    // ------------------------------------------------------
    LCD_posyx(0,0);                // 1行目に表示
    LCD_str(msgStart);
    LCD_dat(' ');
    LCD_dat('!');
    // ------------------------------------------------------
    LCD_posyx(1,0);                // 2行目に表示
    LCD_ROMstr("1234567890123456");
    while(1){
        LCD_posyx(0,14);           // 1行14文字目に表示
        LCD_hex(num++);            // 数値を表示し、+1する
        __delay_ms(1000);          // 1000msec
    }
}

//-------- i2cで1byteデータを送信する -----------------------
//  以下の引数が必要
//  addr : Slaveのアドレス
//  cont : Slaveへ制御コード
//  data : 送信するデータ
//  NACKやBus衝突などの対応は行っていない
// -----------------------------------------------------------
void i2cByteWrite(char addr, char cont, char data){
    SEN = 1;                       // Start condition 開始
    while(SEN);                    // Start condition 確認
    i2cTxData(addr);               // アドレス送信
    i2cTxData(cont);               // 制御コード送信
    i2cTxData(data);               // データ送信
    SSP1IF = 0;                    // 終了フラグクリア
    PEN = 1;                       // Stop condition 開始
    while(PEN);                    // Stop condition 確認
}

//-------- SSPBUFに1文字保存し送信終了を待つ -----------------
void i2cTxData(char data){
    SSP1IF = 0;                    // 終了フラグクリア
    SSPBUF = data;                 // データセット
    while(!SSP1IF);                // 送信終了待ち
}

//-------- 1文字表示 --------------------------------------
void LCD_dat(char chr){
    i2cByteWrite(0x7C, 0x40, chr);
    __delay_us(50);                // 60μsec
}
//-------- コマンド出力 --------------------------------------
void LCD_cmd(char cmd){
    i2cByteWrite(0x7C, 0x00, cmd);
    if(cmd & 0xFC)                 // 上位6ビットに1がある命令
        __delay_us(50);            // 60usec
    else
        __delay_ms(2);             // 3msec 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;  // 1行目
        case 1: pcode=0xC0;break;  // 2行目
        case 2: pcode=0x94;break;  // 3行目
        case 3: pcode=0xD4;break;  // 4行目
    }
    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){
    const char hexch[] ="0123456789ABCDEF";
    LCD_dat(hexch[c >> 4]);        //上位4bit表示
    LCD_dat(hexch[c & 0xF]);       //下位4bit表示
}

//-------- 初期化 --------------------------------------
void LCD_int(void){
    __delay_ms(100);               // 電源安定するまでの時間
    LCD_cmd(0x38);           // 8bit 2行 表示命令モード
    LCD_cmd(0x39);           // 8bit 2行 拡張命令モード
    LCD_cmd(0x14);           // OSC  BIAS 設定1/5
                             // コントラスト設定
    LCD_cmd(0x70 + (CONTRAST & 0x0F));
    LCD_cmd(0x5C + (CONTRAST >> 4));
    LCD_cmd(0x6B);           // Ffollwer
    __delay_ms(200);
    LCD_cmd(0x38);           // 表示命令モード
    LCD_cmd(0x0C);           // Display On
    LCD_cmd(0x01);           // Clear Display
}
//-- 指定アイコン ON
void LCD_icon_on(int icn){
    LCD_cmd(0x39);            // 拡張命令モード
    LCD_cmd(icn >> 8);        // Icon アドレス
    LCD_dat(icn & 0xFF);      // Icon ビット <ON>
    LCD_cmd(0x38);            // 表示命令モード
}
//-- 指定アイコン OFF
void LCD_icon_off(int icn){
    LCD_cmd(0x39);            // 拡張命令モード
    LCD_cmd(icn >> 8);        // Icon アドレス
    LCD_dat(0x00);            // Icon ビット <OFF>
    LCD_cmd(0x38);            // 表示命令モード
}
//-- 全アイコン OFF
void LCD_icon_clr(void){
    unsigned char icn = 0x40;
    LCD_cmd(0x39);            // 拡張命令モード
    while(icn <= 0x4F){
        LCD_cmd(icn++);       // Icon アドレス
        LCD_dat(0x00);        // Icon ビット <OFF>
    }
    LCD_cmd(0x38);            // 表示命令モード
}