電源投入時に電源が特定の条件を満たしていれば、LCDは自動で初期設定されます。しかし本連載で使用しているボードでは、インターフェイスデータ長4ビットでLCDを制御するため、自動設定の値ではLCDの設定には合いません。このため、以下の手順で、LCDの初期設定を行います。
リスト1は、LCDを初期化するためのプログラムです。
void LcdInit(void) { /* P4は初期化されていること */ Wait(20); lcd_write_nibble(0, 0x03); /* Set 8bit Mode */ Wait(10); lcd_write_nibble(0, 0x03); /* Set 8bit Mode */ Wait(1); lcd_write_nibble(0, 0x03); /* Set 8bit Mode */ Wait(1); lcd_write_nibble(0, 0x02); /* Set 4bit Mode */ Wait(1); lcd_write_byte(0, 0x28); /* Set 4bit/2line/5x7dot */ lcd_wait(); lcd_write_byte(0, 0x0C); /* Set Display On/Cursor Off/Blink Off */ lcd_wait(); lcd_write_byte(0, 0x01); /* Clear Display */ lcd_wait(); lcd_write_byte(0, 0x06); /* Set Increment/Shift Off */ lcd_wait(); }
lcd_write_nibbleは、LCDが接続されたポート4に対して制御を行っている関数です。実際の関数は、リスト2のように記述しています。
/*------------------------------------------------*/ /* lcd_write_nibble */ /*------------------------------------------------*/ /* [説明] */ /* LCDに4ビットデータを書き込みます */ /* [入力] */ /* rs :RSビットを指定します */ /* data:出力するデータを指定します */ /* :下位4ビットがLCDに出力されます */ /* [出力] */ /* なし */ /* [戻り値] */ /* なし */ /*------------------------------------------------*/ static void lcd_write_nibble(int rs, char data) { char tmp; if(rs) tmp = LCD_RS_BIT; else tmp = 0; /* RS,DATA設定,E=0,R/W=0 */ tmp |= (data & 0x0F); P4.DR.BYTE = tmp; /* wait 40nsec */ /* E=1 */ tmp |= LCD_E_BIT; /* 40nsec < */ P4.DR.BYTE = tmp; /* wait 220nsec */ /* E=0 */ tmp &= ~LCD_E_BIT; /* 220nsec < */ P4.DR.BYTE = tmp; }
インターフェイスデータ長を4ビット、1/16duty、5×7ドット表示に設定するためのファンクションセット命令実行はlcd_write_byteで実行しています。これはリスト3に示すように、データをシフトさせてlcd_write_nibbleを2回呼び出していますので、最終的にはlcd_write_nibbleが実行されます。
/*------------------------------------------------*/ /* lcd_write_byte */ /*------------------------------------------------*/ /* [説明] */ /* LCDに8ビットデータを書き込みます */ /* [入力] */ /* rs :RSビットを指定します */ /* data:出力するデータを指定します */ /* [出力] */ /* なし */ /* [戻り値] */ /* なし */ /*------------------------------------------------*/ static void lcd_write_byte(int rs, char data) { lcd_write_nibble(rs, data >> 4); /* 上位4ビットをライト */ lcd_write_nibble(rs, data); /* 下位4ビットをライト */ }
なお、電源ONした後、電源が落ち着くまでの待ちやファンクションセット実行後のウェイトは、wait関数で実現しています。リスト4はwait関数の記述例です。
/*------------------------------------------------*/ /* Wait */ /*------------------------------------------------*/ /* [説明] */ /* ウェイトします */ /* [入力] */ /* count :ウェイトする回数を指定します */ /* [出力] */ /* なし */ /* [戻り値] */ /* なし */ /*------------------------------------------------*/ void Wait(int count) { unsigned int curr; int i; for(i=0; i<count; i++) { for(curr=0; curr<2000; curr++) ; } }
例えば、LCDに「LED TEST」という文字列を表示する場合は、以下の関数を実行します。
LcdPutString("LED TEST");
呼び出し側が送ってきた文字列(strで指定された文字列)を「\0」まで表示します。文字列はLcdPutChar(char c)に1文字ずつ送られます(リスト5)。
/*------------------------------------------------------------*/ /* LcdPutString */ /*------------------------------------------------------------*/ /* [説明] */ /* 文字列をLCDに表示します */ /* strで指定された文字列を'\0'まで表示します */ /* 改行などは行いません */ /* [入力] */ /* str :表示する文字列が格納されているポインタを指定します */ /* :文字列の最後は'\0'とします */ /* [出力] */ /* なし */ /* [戻り値] */ /* なし */ /*------------------------------------------------------------*/ void LcdPutString(char *str) { while(*str != '\0') LcdPutChar(*str++); }
LCDに1文字表示するための関数です。lcd_wait()を呼び出すことで、ビジーフラグ(BF)のチェックを行います(リスト6)。
/*-------------------------------------------------*/ /* LcdPutChar */ /*-------------------------------------------------*/ /* [説明] */ /* LCD画面に1文字表示します */ /* 1文字表示後、次の表示位置は1文字右に移動します */ /* [入力] */ /* c :表示する文字を指定します */ /* [出力] */ /* なし */ /* [戻り値] */ /* なし */ /*-------------------------------------------------*/ void LcdPutChar(char c) { lcd_wait(); lcd_write_byte(1, c); /* DDRAM Data Write */ }
LCDのビジーフラグ(BF)を確認し、LCDが利用可能(BFビットが0)になるまで待ちます(リスト7)。
/*--------------------------------------------------------*/ /* lcd_wait */ /*--------------------------------------------------------*/ /* [説明] */ /* LCDのBFビットを確認し、BFビットが0になるまで待ちます */ /* [入力] */ /* なし */ /* [出力] */ /* なし */ /* [戻り値] */ /* なし */ /*--------------------------------------------------------*/ static void lcd_wait(void) { char data; while(1) { data = lcd_read_byte(0); /* ステータスを読み出す */ if((data & LCD_BF_BIT) == 0) /* BFビットが0のとき終了 */ break; } } /*------------------------------------------------*/ /* lcd_read_byte */ /*------------------------------------------------*/ /* [説明] */ /* LCDに8ビットデータを読み出します */ /* [入力] */ /* rs :RSビットを指定します */ /* [出力] */ /* なし */ /* [戻り値] */ /* 読み出されたデータを返します */ /*------------------------------------------------*/ static char lcd_read_byte(int rs) { char data; data = lcd_read_nibble(rs); /* 上位4ビットをリード */ data <<= 4; data |= lcd_read_nibble(rs); /* 下位4ビットをリード */ return data; } /*------------------------------------------------*/ /* lcd_read_nibble */ /*------------------------------------------------*/ /* [説明] */ /* LCDに4ビットデータを読み出します */ /* [入力] */ /* rs :RSビットを指定します */ /* [出力] */ /* なし */ /* [戻り値] */ /* 読み出されたデータを返します */ /* 下位4ビットが読み出されたデータとなります */ /*------------------------------------------------*/ static char lcd_read_nibble(int rs) { char tmp; char data; /* 入力ポートに変更 */ P4.DDR = 0x70; if(rs) tmp = LCD_RS_BIT; else tmp = 0; /* RS,DATA設定,E=0,R/W=1 */ tmp |= LCD_RW_BIT; P4.DR.BYTE = tmp; /* wait 40nsec */ /* E=1 */ tmp |= LCD_E_BIT; /* 40nsec < */ P4.DR.BYTE = tmp; /* wait 220nsec */ /* データ取得 */ data = 0; /* 220nsec < */ data = P4.DR.BYTE & 0x0F; /* E=0/RW=0 */ P4.DR.BYTE = 0; /* 出力ポートに変更 */ P4.DDR = 0x7F; return data; }
今回はLCD制御について解説しました。次回は、モータ類の制御について解説します。(次回に続く)
Copyright © ITmedia, Inc. All Rights Reserved.