---
---
16F1455に、秋月電子から販売されているI2CLCDモジュールを接続しました。ストロベリーリナックス製の物とほぼ同じですが、初期設定が少し異なっています。 i2cは双方向性でバスで受信(スレーブ)側の処理が間に合わないときに送信を遅らせたり、送受信の信号が衝突した場合などにエラーを検出する機能を持っていますが、これら機能をすべて省略し、ただ、表示データや制御コードを一方的に送信するプログラムです。
文字やアイコンを画面に表示するだけのプログラムです。プログラムは、メインプログラムとLCD表示関数から構成されています。メインプログラムは、これら関数を呼び出して、文字やアイコンを表示させます。具体的には、以下の手順で表示します
*注意*
PIC16F1455のI2Cピンは、ICSPピンと同一です。 PICにプログラムするためPICkit3を接続したままにすると、このピンがPICkit3内部で4.7kΩの抵抗でプルダウンされるため、I2C機能が動作しません。 正常に動作させるには、PICにプログラムを書き込んだ後で、PICkit3を回路から取り外す必要があります。
<プログラム>
// データをLCDに表示する。 // 秋月(ACM1602NI)I2C 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 //********************************************************* #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); // 16進文字変換表示 //////////// 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_str(msgStart); // 1行目に表示 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(0xA0, 0x80, chr); __delay_us(60); // 60μsec } //-------- コマンド出力 -------------------------------------- void LCD_cmd(char cmd){ i2cByteWrite(0xA0, 0x00, cmd); if(cmd & 0xFC) // 上位6ビットに1がある命令 __delay_us(60); // 60usec else __delay_ms(3); // 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(0x0C); // Display on Cursor=0 Blink=0 LCD_cmd(0x06); // Entry Inc/Dec=1 Shift=0 LCD_cmd(0x01); // Clear Display }