---
---
16F1455に、I2Cで超小型16文字x2行のLCD表示器を接続しました。MSSPをI2C マスターモードで利用します。パラレル接続の場合は、6本の信号線、コントラスト調整線、電源の計9本の配線が必要ですが、I2C接続すれば、信号線は2本で済み、リセットと電源を含めても5本の配線です。パラレル接続のLCD表示器との共通性を持たせるI2C接続LCD表示器用の関数名と同じにしています。
文字やアイコンを画面に表示するだけのプログラムです。プログラムは、メインプログラムとLCD表示関数から構成されています。また定義部門に電圧を変更したときに指定する画面コンスタント定数が定義されています。メインプログラムは、これら関数を呼び出して、文字やアイコンを表示させます。具体的には、以下の手順で表示します
*注意*
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); // 表示命令モード
}