---
---
秋月電子から販売されているI2CLCDモジュールを接続しました。ストロベリーリナックス製の物とほぼ同じですが、初期設定が少し異なっています。
i2cは双方向性でバスで受信(スレーブ)側の処理が間に合わないときに送信を遅らせたり、送受信の信号が衝突した場合などにエラーを検出する機能を持っていますが、パラレル接続のLCD表示器との接続のために、これら機能をすべて省略し、ただ、表示データや制御コードを一方的に送信するライブラリ L_i2cLCDa にまとめています。
文字やアイコンを画面に表示するだけのプログラムです。
プログラムは、メインプログラム(main.c)とLCD表示ライブラリ(L_i2cLCD.h、L_i2cLCD.c)から構成されています。
L_i2cLCD.c にLCD表示する手順が記載されており、
L_i2cLCD.h には、クロックを変更した場合に手直しをするべき、遅延定数が定義されています。メインプログラムは、これらライブラリに登録されている関数を呼び出して、文字やアイコンを表示させます。
具体的には、以下の手順で表示します。
登録されている関数は、パラレル接続のLCDライブラリと共通性を持っています。
<プログラム>
main.c
//*************************************************************** // 秋月(ACM1602NI)I2C LCD表示器への書き込みテスト // 「LCD Disp Test」と液晶表示する。 // 1)Define I/O PORT // PORTB(4)pin13 : SDA // PORTB(6)pin11 : SCL // 2)OSC // 内部クロック 4MHz // // Language: MPLABX XC8 // Target: PIC18F14K50 // Copyright (c) 2013 iwamoto All Rights Reserved //***************************************************************/ #include <xc.h> #include "L_i2cLCDa.h" //I2C接続LCD関数 //-------------- コンフィグレーション ------------------------ #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 Disp Test"; OSCCON = 0b01010010; // 内部クロック4Mhz PORTA = 0x00; PORTB = 0x00; PORTC = 0x00; TRISA = 0b11111111; //PortA すべて入力 TRISB = 0b11111111; //PortB すべて入力 TRISC = 0b11111111; //PortC すべて入力 ANSEL = 0b00000000; //すべてデジタル ANSELH = 0b00000000; LCD_int(); // LCDを初期化 LCD_str(msgStart); // LCD上段に"LCD Disp Test" LCD_posyx(1,1); // 下段にカーソル移動 LCD_dat('I'); // 下段に"I2C "表示 LCD_dat('2'); LCD_dat('C'); LCD_dat(' '); LCD_ROMstr("interface"); // 下段に"interface"追記 while(1); }
L_LCD.h
//************************************************************* // I2C LCD ライブラリ PIC18 Ver 2.0 20130512 // 秋月(ACM1602NI)I2C LCD表示器 // 以下の機能を提供する // // 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() ----- 全消去 // //液晶表示器とPICはI2Cにより接続される // 1)Define I/O PORT // PORTB(4)pin13 : SDA // PORTB(6)pin11 : SCL // 2)OSC // 内部クロック 4MHz // // Copyright (c) 2012-2013 iwamoto All Rights Reserved //************* Delay ******************************************* // 必要とするディレイ時間をクロック周波数から計算し、 // 指定するために、クロック周波数を指定する。 //*************************************************************** #define _XTAL_FREQ 4000000 //******************************************************** #define Delay_60uS __delay_us(60) #define Delay_3mS __delay_ms(3) #define Delay_100mS __delay_ms(100) //******************************** // ボーレート定数 //******************************** // --------- for 4MHz ------------ #define SlewCont SLEW_OFF // Slew Rate 100K #define BaudConst 0x09 // BRG Value for 4MHz // --------- for 48MHz ------------ //#define SlewCont SLEW_OFF // Slew Rate 100K //#define BaudConst 0x77 // BRG Value for 48MHz //******************* 提供機能 ******************************* void LCD_dat(char); void LCD_cmd(char); void LCD_clr(void); void LCD_int(void); void LCD_str(char *); void LCD_posyx(char,char); void LCD_ROMstr(const char *); void LCD_hex(char);
L_LCD.c
//////////////////////////////////////////////////////////// // 液晶表示ライブラリ for PIC18Fxxxx Ver 2.0 20130512 // 秋月(ACM1602NI)I2C LCD表示器 // 以下の機能を提供 // 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() ---- 全消去 // // Copyright (c) 2012 iwamoto All Rights Reserved //////////////////////////////////////////////////////////// #include <xc.h> #include "L_i2cLCDa.h" void _EEByteWrite(char, char, char); void _i2cTx(char); void _EEByteWrite(char addr, char cont, char data){ SSPCON2bits.SEN = 1; // Start condition 開始 while(SSPCON2bits.SEN); // Start condition 確認 _i2cTx(addr); // アドレス送信 _i2cTx(cont); // 制御コード送信 _i2cTx(data); // データ送信 PIR1bits.SSPIF = 0; // 終了フラグクリア SSPCON2bits.PEN = 1; // Stop condition 開始 while(SSPCON2bits.PEN); // Stop condition 確認 } void _i2cTx(char data){ PIR1bits.SSPIF = 0; // 終了フラグクリア SSPBUF = data; // データセット while(!PIR1bits.SSPIF); // 送信終了待ち } //-------- 1文字表示 void LCD_dat(char chr){ _EEByteWrite(0xA0, 0x80, chr); Delay_60uS; // 60μsec } //-------- コマンド出力 void LCD_cmd(char cmd){ _EEByteWrite(0xA0, 0x00, cmd); if(cmd & 0xFC) // 上位6ビットに1がある命令 Delay_60uS; // 60usec else Delay_3mS; // 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; 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){ SSPCON1 = 0x28; //I2Cマスターモード指定 SSPSTAT = 0x00; SSPADD = BaudConst; //Board Rate Delay_100mS; LCD_cmd(0x38); // 8bit 2行 表示命令モード LCD_cmd(0x0C); // Display on Cursor=0 Blink=0 LCD_cmd(0x06); // Entry Inc/Dec=1 Shift=0 LCD_cmd(0x01); // Clear Display }