---
---
12F1822のUARTとI2C通信機能を使用し、非同期のシリアル信号入力を持つLCD表示器を作成します。マイコンからの情報を少ない配線数で表示でき、マイコン側のソフトウエアも単純なプログラムで処理できる表示ユニットです。ASCII文字以外は、画面表示に最低限必要と思われる制御コードを受け付けます。非同期受信は、パリティーなし、9600bpsのロジックレベル信号の入力とします。文字を表示するLCDは、 秋月の8文字x2行のI2CLCD表示器を使いましたが、aitendo のI2CLCD表示器やストロベリリナックスのI2CLCD表示器は、同じ制御コードを持っているため、同一のプログラムで使用可能です。
| 制御コード | 動作 |
|---|---|
| 0x00 | 何もしない |
| 0x01 | クリア 全表示をクリアし、カーソルを上段先頭にする |
| 0x02 | カーソルを上段先頭にする |
| 0x03 | カーソルを下段先頭にする |
| 0x8X | カーソルを上段 X番目(0-F)にする |
| 0x9X | カーソルを下段 X番目(0-F)にする |
| 0x20-0x7F | ASCII文字(英数字)を表示 |
| 0xA0-0xFF | ASCII文字(カタカナ、特殊文字)を表示 |
<回路図>
<プログラム> main.c
/*********************************************************************
* UART で受信したデータをLCDに表示する。
* 秋月(ACM1602NI)I2C LCD表示器を使用
* 4MHz (内部クロック)
*
* 1 VDD 8 VSS
* Rx 2 RA5 7 RA0
* 3 RA4 6 RA1 SCL
* 4 MCLR 5 RA2 SDA
*
* PIC12F1822 MPLAB X IDE with XC8 Ver1.32
* Copyright (c) 2012 iwamoto All Rights Reserved
* *******************************************************************/
#define CR_EN1 RCSTAbits.CREN
#define O_ERR1 RCSTAbits.OERR
#include <xc.h>
#include "L_i2cLCD.h" //I2C接続LCD関数
//******************* コンフィグレーション ****************************
#pragma config FOSC = INTOSC, WDTE = OFF, PWRTE = OFF, MCLRE = ON, CP = OFF
#pragma config CPD = OFF, BOREN = ON, CLKOUTEN = OFF, IESO = OFF, FCMEN = OFF
#pragma config WRT = OFF, PLLEN = OFF, STVREN = ON, BORV = LO, LVP = OFF
//
void i2cintl(void);
// ******************* main ******************************************
void main() {
char i;
OSCCON = 0b01101010; // 内部クロック4Mhz
TRISA = 0xFF; // Port すべて入力
ANSELA = 0x00; // すべてデジタル
PORTA = 0x00;
WPUA = 0b00001110; // RA1,2 弱プルアップ ON
nWPUEN = 0;
APFCONbits.RXDTSEL = 1; // RX/DT機能をRA5 に割当
//------------ Initialize UART -------------------
RCSTA = 0b10010000;
TXSTA = 0b00000100;
BAUDCON = 0b00001000;
SPBRGH = 0;
SPBRG = 103;
i2cintl();
LCD_int(); // LCDを初期化
LCD_ROMstr("LCD Test"); // LCD上段に""LCD Test"
LCD_posyx(1,1); // 下段にカーソル移動
LCD_ROMstr(" I2C"); // LCD下段に" I2C"
while(1){
while (!PIR1bits.RCIF); // 受信するまで待つ
if(RCSTAbits.OERR){ // Overrunエラーなら
RCSTAbits.CREN=0; // エラーをクリア
RCSTAbits.CREN=1; // 再起動
i = RCREG;
continue;
}
i = RCREG; // 受信データを取り込む
if(i == 1)LCD_cmd(0x01); // Clearコマンド出力
else if(i == 2)LCD_posyx(0,0); // 1行目先頭に移動
else if(i == 3)LCD_posyx(1,0); // 2行目先頭に移動
else if((i>=0x80)&&(i<=0x9F)) // 80-9Fはカーソル移動
LCD_posyx((i&0x10)>>4,i&0x0F);
else if(i>=0x20)LCD_dat(i); // 0x20以上は文字の表示
}
}
//********************************************************************
// SSP1を I2C Master mode、SCL 100kHz @ 4MHz に設定
//********************************************************************
void i2cintl(void){
SSP1CON1 = 0b00001000; // I2C Master modeにする
SSP1CON2 = 0x00; // PowerOn初期値にする
SSP1STAT = 0b10000000; // スルーレート制御はOff
SSP1ADD = 9; // クロックの設定 100k@4MHz
SSP1CON1bits.SSPEN = 1; // SSP 有効にする bit5
}
<プログラム> L_i2cLCD.h
//************************************************************* // I2C LCD ライブラリ 20141112 // 以下の機能を提供する // // LCD_int() ----- 初期化(I2C初期化を含む) // LCD_cmd(cmd) ----- コマンド出力 // LCD_dat(chr) ----- 1文字表示 // LCD_str(*str) ----- 文字列表示 // LCD_ROMstr(*str) -- ROM文字列表示 // LCD_hex(char); // LCD_posyx(y,x) ---- カーソル位置指定、行 y、横位置 x // LCD_clr() ----- 全消去 // LCD_icon_on(icn); -- 指定アイコン ON // LCD_icon_off(icn);-- 指定アイコン OFF // LCD_icon_clr();----- 全アイコン OFF // //液晶表示器とPICはI2Cにより接続される // 内部クロック 4MHz // // Copyright (c) 2012-2014 iwamoto All Rights Reserved //************* Delay ******************************************* // 必要とするディレイ時間をクロック周波数から計算し、 // 指定するために、クロック周波数を指定する。 //*************************************************************** #define _XTAL_FREQ 4000000 // //*************** Delay Define for 4MHz Clock********* #define Delay_50uS __delay_us(50) #define Delay_2mS __delay_ms(2) #define Delay_100mS __delay_ms(100) //******************************** // 調整用定数 //********************************* #define CONTRAST 0x28 // for 3.3V //#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 // 三重丸 //******************* 提供機能 ******************************* void LCD_dat(char chr); void LCD_cmd(char cmd); void LCD_clr(void); void LCD_int(void); void LCD_str(char *str); void LCD_posyx(char ypos,char xpos); void LCD_icon_on(int icn); void LCD_icon_off(int icn); void LCD_icon_clr(void); void LCD_ROMstr(const char *); void LCD_hex(char);
<プログラム> L_i2cLCD.c
////////////////////////////////////////////////////////////
// I2C LCD ライブラリ 20141112
// 秋月(ACM1602NI)I2C 液晶表示 および
// ストロベリーリナックス液晶表示 ライブラリ
// 以下の機能を提供
// LCD_int() ----- 初期化
// LCD_cmd(cmd) ----- コマンド出力
// LCD_dat(chr) ----- 1文字表示
// LCD_str(*str) ---- 文字列表示
// LCD_ROMstr(*str) -- ROM文字列表示
// LCD_hex(char);
// LCD_posyx(y,x) ---- カーソル位置指定、行 y、横位置 x
// LCD_clr() ----- 全消去
// LCD_icon_on(icn);--- 指定アイコンON
// LCD_icon_off(icn);-- 指定アイコンOFF
// LCD_icon_clrf();---- 全アイコンOFF
//液晶表示器とPICはI2Cにより接続される
// 内部クロック 4MHz
//
// Copyright (c) 2012-2014 iwamoto All Rights Reserved
////////////////////////////////////////////////////////////
#include <xc.h>
#include "L_i2cLCD.h"
void _EEByteWrite(char, char, char);
void _i2cTx(char);
void _EEByteWrite(char addr, char cont, char data){
SSP1CON2bits.SEN = 1; // Start condition 開始
while(SSP1CON2bits.SEN); // Start condition 確認
_i2cTx(addr); // アドレス送信
_i2cTx(cont); // 制御コード送信
_i2cTx(data); // データ送信
SSP1CON2bits.PEN = 1; // Stop condition 開始
while(SSP1CON2bits.PEN); // Stop condition 確認
}
void _i2cTx(char data){
PIR1bits.SSP1IF = 0; // 終了フラグクリア
SSP1BUF = data; // データセット
while(!PIR1bits.SSP1IF); // 送信終了待ち
}
//-------- 1文字表示
void LCD_dat(char chr){
_EEByteWrite(0x7C, 0x40, chr);
Delay_50uS; // 50μsec
}
//-------- コマンド出力
void LCD_cmd(char cmd){
_EEByteWrite(0x7C, 0x00, cmd);
if(cmd & 0xFC) // 上位6ビットに1がある命令
Delay_50uS; // 50usec
else
Delay_2mS; // 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){
const char hexch[] ="0123456789ABCDEF";
LCD_dat(hexch[c >> 4]);
LCD_dat(hexch[c & 0xF]);
}
//-------- 初期化
void LCD_int(void){
// SSP1CON1 = 0x28; //I2Cマスターモード指定
// SSP1STAT = 0x00;
// SSP1ADD = BaudConst; //Board Rate
Delay_100mS;
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_100mS;
Delay_100mS;
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); // 表示命令モード
}