//ファイル名main.txt を main.c に書き換えてください。 /***************************************************** * LCD(I2C)20文字x4行のテストプログラム for 12f683 * 3行1文字の BigFont を表示する * 開発環境 MPLAB IDE Ver8.84, HI-TECH C v9.83 * 1秒ごとにカウントアップするが、ボタン(GP1)を * 押すとカウントアップを一時停止する。 * I2CインターフェースPCF8574Tで接続 ******************************************************/ #include #define _XTAL_FREQ 4000000 // クロック周波数設定 // I2c スレーブ・アドレス 0x27 + "0" => 0x4E // 0x27を左に1ビットシフトし、右端にwrite=0 を付加 // (010 0111)+(出力"0"を右端に付ける)⇒0100 1110 #define ADDR 0x4E // スレーブアドレス #define SDA GP5 #define SCL GP4 #define TRISSDA TRISIO5 /***** コンフィギュレーションの設定 ********/ __CONFIG(FOSC_INTOSCIO // INTOSCIO oscillator I/O function & WDTE_OFF // Watchdog Timer disabled & PWRTE_ON // Power-up Timer enabled & BOREN_ON // Brown Out enabled & MCLRE_ON // MCLR RA5はリセット & CP_OFF // Program memory code protection is disabled & IESO_OFF //Internal External Switchover mode is disabled & FCMEN_OFF);// Fail-Safe Clock Monitor is disabled void I2c_Start(void); void I2c_Stop(void); unsigned char I2c_Out(unsigned char data); void lcd_common(unsigned char data); void lcd_data(unsigned char data); void lcd_cmd(unsigned char data); void lcd_init(void); void lcd_str(char* ptr); void lcd_clear(void); void delay_10ms(unsigned int t1); void delay_10us(unsigned int t2); void keisan(); // 数値を文字に void Hyouji(); // BigFont表示関数 // BigFontの部品:CGRAM(5x8ドット)に格納する内容(下側の5ビット) const char custom[][8] = { // 0x1F→0b11111 { 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00 },// 0x00上3行 { 0x18, 0x1C, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F },// 0x01右上角空 { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x07, 0x03 },// 0x02左下角空 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F },// 0x03下3行 { 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1C, 0x18 },// 0x04右下角空 { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x1F },// 0x05左上大空 { 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00 },// 0x06中3行 { 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F } // 0x07左上角空 }; // CGRAM(0x00-07)を組み合わせて作る数字(0-9)とコロン // 0x20は空白、0xFFは塗りつぶし // 左3つが1行目、中3つが2行目、右3つが3行目 const char BigNum[11][9] = { // キャラクターのアドレス { 0x07, 0x00, 0x01, 0xFF, 0x20, 0xFF, 0x02, 0x03, 0x04 }, // 0 { 0x00, 0x01, 0x20, 0x20, 0xFF, 0x20, 0x03, 0xFF, 0x03 }, // 1 { 0x00, 0x00, 0x01, 0x03, 0x05, 0x04, 0xFF, 0x03, 0x03 }, // 2 { 0x00, 0x00, 0x01, 0x20, 0x06, 0xFF, 0x03, 0x03, 0x04 }, // 3 { 0xFF, 0x20, 0xFF, 0x02, 0x03, 0xFF, 0x20, 0x20, 0xFF }, // 4 { 0xFF, 0x00, 0x00, 0x00, 0x06, 0x03, 0X03, 0X03, 0X04 }, // 5 { 0x07, 0x00, 0x00, 0xFF, 0x06, 0x03, 0X02, 0X03, 0X04 }, // 6 { 0x00, 0x00, 0x01, 0x20, 0x05, 0x04, 0X20, 0XFF, 0X20 }, // 7 { 0x07, 0x00, 0x01, 0xFF, 0x06, 0xFF, 0X02, 0X03, 0X04 }, // 8 { 0x07, 0x00, 0x01, 0x00, 0x06, 0xFF, 0X03, 0X03, 0X04 }, // 9 { 0x20, 0x03, 0x20, 0X20, 0X20, 0X20, 0x20, 0x00, 0x20 } // : }; // { 0xFF, 0x06, 0x06, 0xFF, 0x03, 0x03, 0X03, 0X03, 0X04 }, // 5 // CGRAM用のデータ(custom)をメモリに格納する関数 void lcd_BF_dat(char adrs, char *pattern){ lcd_cmd(0x40 | (adrs << 3)); //CGRAMアドレス (adrs: 0-7) for(char i=0; i<8; i++){ lcd_data(pattern[i]); } } // 数値をASCII文字に変換する関数 void i_to_str(char digit, unsigned int data, char *buffer); unsigned char Msg[11] = "Cnt = xxxx"; // ひな形 unsigned char Settei[12] = "Time = x:xx"; unsigned char FLG; // 通常文字⇔BigFont フラグ unsigned int Time; // カウンタ unsigned char s[4]; // s[0]分:s[2],s[3]秒 /******** メイン関数 ************/ void main(void){ OSCCON = 0x60; // Set to 4MHz GPIO = 0x31; // GP4,5 default High TRISIO = 0x02; // GP1(in) 他全出力設定 ANSEL = 0x00; // デジタルに設定 CMCON0 = 0x07; // コンパレータオフ /* 液晶表示器の初期化 */ lcd_init(); // CGRAM0x00〜07へ配列customのフォントデータ書込み for(char i=0; i<8; i++){ lcd_BF_dat(i, &custom[i][0]); } // 初期値設定 FLG = 0; Time = 0; GP2 = 0; // 動作確認用LED lcd_cmd(0x80); lcd_str("LCD Test"); // メインループ while(1){ if(GP1 == 0){ // タクトSWを押したら while(GP1 == 0)delay_10ms(1);// チャタリング防止 FLG ^=1; } if(FLG == 1){ continue; // 一時停止 }else{ Time++; } keisan(); Hyouji(); delay_10ms(100); // 約1秒ずつ GP2 ^= 1; if(Time > 599)Time = 0; } } // Time(秒数)を分(s[0])+コロン(s[1])+秒(s[2]s[3])に void keisan(){ // s[0]〜[3]はアドレスの数値、n1〜n4は文字を入れる if(Time < 60){ s[0] = ' '; // 'N'は記号 s[1] = ' '; // コロン無し }else{ s[0] = (Time / 60); s[1] = 10; // コロン有り } if(Time < 10){ s[2] = ' '; }else{ s[2] = (Time % 60) / 10; } s[3] = Time % 10; } // 表示用関数 void Hyouji(){ // 表示は左から(Set DDRAM Address 0b1xxxxxxx + position) unsigned char adr1 = 0xC0; // 2行目左 unsigned char adr2 = 0x94; // 3行目左 unsigned char adr3 = 0xD4; // 4行目左 for(char k=0; k<4; k++){ // 4文字分 if(s[k] == ' '){ // 値が無い時は adr1 += 4; // 4桁(文字3桁+空白1桁)右へ adr2 += 4; adr3 += 4; continue; } lcd_cmd(adr1); // 書き始め:左上へ unsigned char Ban; Ban = s[k]; for(char m=0; m<3; m++){ // 上3桁表示 lcd_data(BigNum[Ban][m]); } lcd_cmd(adr2); // 中3桁表示 for(char n=3; n<6; n++){ lcd_data(BigNum[Ban][n]); } lcd_cmd(adr3); // 下3桁表示 for(char l=6; l<9; l++){ lcd_data(BigNum[Ban][l]); } adr1 += 4; // 4桁(文字3桁+空白1桁)右へ adr2 += 4; adr3 += 4; } } /*************************************** * int整数からASCII文字に変換 ****************************************/ void i_to_str(char digit, unsigned int data, char *buffer){ char i; buffer += digit; // 最後の数字位置 for(i=digit; i>0; i--) { // 変換は下位から上位へ buffer--; // ポインター1 *buffer = (data % 10) + '0'; // ASCIIへ data = data / 10; // 次の桁へ } } /** Start Condiotion **/ void I2c_Start(void){ // SCL,SDAは通常:High SDA = 0; // 先に SDA=Low TRISSDA = 0; // SDA出力 } /** Stop Condition **/ void I2c_Stop(void){ SCL = 0; // SCL Low SDA = 0; // SDA Low TRISSDA = 0; // 出力モードに戻す SCL = 1; // 先にSCLをHigh SDA = 1; // 後からSDAをHigh } /** I2c_で1バイト出力(1ビットずつ) **/ unsigned char I2c_Out(unsigned char data){ int i; unsigned char BitPos, ACK; TRISSDA = 0; // SDA出力モード BitPos = 0x80; // ビット位置初期値(左端) for(i=0; i<8; i++) // 8ビット繰り返し { SCL = 0; // SCL Low if((data & BitPos) != 0) // ビット出力 SDA = 1; // SDA High else SDA = 0; // SDA Low BitPos = BitPos >> 1; // ビット位置移動 SCL = 1; // SCL Highに戻す } /* Ack チェック */ SCL = 0; // クロック1Low TRISSDA = 1; // 入力モードにしてACK入力 ACK = SDA; // ACKチェック for delay ACK = SDA; // ACKチェック SCL = 1; // クロックHighに戻す return(ACK); // ACKを戻り値とする } /** アダプターへデータ送信(基本) **/ void lcd_common(unsigned char data){ I2c_Start(); // スタート I2c_Out(ADDR); // アドレス I2c_Out(data); // 表示データ出力 I2c_Stop(); // ストップ delay_10us(3); // 30μsec待ち } /** 液晶へ1文字表示データ出力 **/ void lcd_data(unsigned char data){ unsigned char hydata; // 上位4ビット hydata = data & 0xf0 | 0x0D; // +Backlight,EN,RS lcd_common(hydata); delay_10us(1); lcd_common(hydata & ~0x04); // Enable_Pulse -> Low delay_10us(1); // 下位4ビット hydata = (data << 4) & 0xf0 | 0x0D; // +Backlight,EN,RS lcd_common(hydata); delay_10us(1); lcd_common(hydata & ~0x04); // Enable_Pulse -> Low delay_10us(5); } /** 液晶へ1コマンド出力 **/ void lcd_cmd(unsigned char data){ unsigned char command; // 上位4ビット command = data & 0xf0 | 0x0C; // +Backlight,EN,(RS:0) lcd_common(command); delay_10us(1); lcd_common(command & ~0x04); // Enable_Pulse -> Low delay_10us(1); // 下位4ビット command = (data << 4) & 0xf0 | 0x0C;// +Backlight,EN lcd_common(command); delay_10us(1); lcd_common(command & ~0x04); // Enable_Pulse -> Low delay_10us(5); } /** 初期化関数 **/ void lcd_init(void){ delay_10ms(10); // 8ビットモード lcd_common(0x34); delay_10us(1); lcd_common(0x34 & ~0x04);// Enable→0 // 4bit_mode & BackLight,EN lcd_common(0x2C); // '2'のデータと'1100' delay_10us(1); lcd_common(0x2C & ~0x04);// Enable を 0 に delay_10us(5); // ここから4ビット通常モード delay_10us(10); lcd_cmd(0x28); // 4ビット × 2, 2line delay_10us(10); lcd_cmd(0x08); // Display off,Cutsor off Blink off delay_10us(10); lcd_cmd(0x01); // Display clear delay_10ms(1); lcd_cmd(0x06); // Entry mode delay_10us(10); lcd_cmd(0x0c); // Display on,Cursor off delay_10us(10); } /** 全消去関数 **/ void lcd_clear(void){ lcd_cmd(0x01); //初期化コマンド出力 } /** 文字列表示関数 **/ void lcd_str(char *ptr){ while(*ptr != 0) //文字取り出し lcd_data(*ptr++); //文字表示 } /** 遅延関数 **/ void delay_10ms(unsigned int t1){ while(t1--){ __delay_ms(10); } } void delay_10us(unsigned int t2){ while(t2--){ __delay_us(10); } }