目次

キャラクタLCDの6ピン制御

 キャラクタLCDは、14ピンをもち、4種類に分けられる。

 通常は、キャラクタLCDからデータを入力することは殆どないので
 WRピンを、0Vに固定し、書き込みだけできるようにすればよい。

 制御ピンがE RS の2本、データピンが8本の合計10ピンで、表示を
 制御できる。

 LCD制御のデファクトスタンダードのHD47780では、データを
 4ビット2回に分けて転送するモードをもつ。このインタフェースを
 もつLCDでは、10ピンから、さらに4ピン減らした6ピン制御が
 できる。

最下層処理

 LCDにデータを転送するシーケンスは、以下とする。
  1. EをLにする
  2. RSを、HかLのどちらかに設定
  3. データの上位4ビットを出力
  4. EをHにする
  5. EをLにする
  6. データの下位4ビットを出力
  7. EをHにする
  8. EをLにする

最下層処理関数

 メモリマップドI/OとI/OマップドI/Oで、動作の違いがあるので  それぞれの関数を定義する。  メモリマップドI/Oの場合 typedef unsigned char UBYTE ; #define OFF 0 #define ON OFF+1 void put_lcd_primitive(UBYTE which,UBYTE dat) { UBYTE i,tmp ; tmp = dat ; LCD_E = OFF ; LCD_RS = which ; /* upper nibble */ LCD_NIBBLE = (tmp >> 4) & 0x0f ; LCD_E = ON ; LCD_E = OFF ; /* lower nibble */ tmp &= 0x0f ; LCD_NIBBLE = tmp ; LCD_E = ON ; LCD_E = OFF ; }  I/OマップドI/Oの場合 #define LCD_E 0x20 #define LCD_RS 0x10 void put_lcd_primitive(UBYTE which,UBYTE dat) { UBYTE ctmp; /* 0 -> E */ ctmp &= ~LCD_E ; outp( LCD_CP , ctmp ); /* RS */ ctmp &= ~LCD_RS ; if ( which ) { ctmp |= LCD_RS ; } outp( LCD_CP , ctmp ); /* upper nibble */ ctmp &= 0xf0 ; ctmp |= ((dat >> 4) & 0x0f) ; outp( LCD_DP , ctmp ); /* 1 -> E */ ctmp |= LCD_E ; outp( LCD_CP , ctmp ); /* 0 -> E */ ctmp &= ~LCD_E ; outp( LCD_CP , ctmp ); /* lower nibble */ ctmp &= 0xf0 ; ctmp |= dat & 0x0f ; outp( LCD_DP , ctmp ); /* 1 -> E */ ctmp |= LCD_E ; outp( LCD_CP , ctmp ); /* 0 -> E */ ctmp &= ~LCD_E ; outp( LCD_CP , ctmp ); }

初期化処理

 8ビットデータアクセスの場合は、以下のように初期化する。
  1. 最短15ms待ち
  2. RS=L状態で、0x30を転送
  3. 最短4.1ms待ち
  4. RS=L状態で、0x30を転送
  5. 最短100us待ち
  6. RS=L状態で、0x30を転送
  7. RS=L状態で、0x20を転送
  8. RS=L状態で、0x28を転送
  9. RS=L状態で、0x08を転送
  10. 最短2ms待ち
  11. RS=L状態で、0x0eを転送
  12. 最短1ms待ち
  13. RS=L状態で、0x06を転送
  14. 最短1ms待ち
  15. RS=L状態で、0x01を転送
  16. 最短1ms待ち
 ms単位での時間待ちをすることができる関数があるとして  次のように、初期化コードを記述する。 void init_lcd(void) { /* initialize hardware */ delay_ms(45) ; put_lcd_p4(OFF,0x30); /* select 8 bits */ delay_ms(5) ; put_lcd_p4(OFF,0x30); /* select 8 bits */ delay_ms(1); put_lcd_p4(OFF,0x30); /* select 8 bits */ delay_ms(1); /* set function */ put_lcd_p4(OFF,0x20); /* select 4 bits */ delay_ms(1); /* select 2 line display */ put_lcd_function(0x28); delay_ms(1); /* display off */ put_lcd_function(0x08); delay_ms(1); /* display on , cursor appear */ put_lcd_function(0x0e); delay_ms(1); /* entry mode*/ put_lcd_function(0x06); delay_ms(1); /* clear */ put_lcd_function(0x01); delay_ms(1); }  8ビットのバスインタフェースの場合  初期化関数は、以下となります。 void init_lcd(void) { /* initialize hardware */ delay_ms(15) ; /* 15ms */ put_lcd_primitive(OFF,0x30); delay_ms(5) ; /* 5ms */ put_lcd_primitive(OFF,0x30); delay_ms(1); /* 1ms */ put_lcd_primitive(OFF,0x30); delay_ms(1); /* 1ms */ /* set function */ put_lcd_primitive(OFF,0x38); put_lcd_primitive(OFF,0x08); put_lcd_primitive(OFF,0x01); delay_ms(2); /* 2ms */ put_lcd_primitive(OFF,0x0c); }

文字列表示

 行と桁を指定し、文字列を表示するには、次のシーケンスを実行する。
  1. 桁と行から、LCD内部のメモリアドレスを求める
  2. メモリアドレスを転送
  3. 1文字ずつ転送
 2行のLCDでは、次のようにアドレスがエントリーを指定されている  0行0桁 → 0x00  1行0桁 → 0x40  4行のLCDでは、次のようにアドレスがエントリーを指定されている  0行0桁 → 0x00  1行0桁 → 0x40  2行0桁 → 0x14  3行0桁 → 0x54 文字列表示の関数を定義すると、次のようになる。 #define MASK80 0x80 void put_lcd_str(UBYTE r,UBYTE c,UBYTE *ptr) { UBYTE adr ; /* check range */ #ifdef LCD_4LINES if ( r > 3 ) return ; if ( c > 19 ) return ; #else if ( r > 1 ) return ; if ( c > 15 ) return ; #endif /* set address */ switch ( r ) { case 1 : adr = 0x40 ; break ; case 2 : adr = 0x14 ; break ; case 3 : adr = 0x54 ; break ; default : adr = 0x00 ; break ; } adr += c ; adr |= MASK80 ; put_lcd_primitive(OFF,adr); while ( *ptr != '\0' ) { put_lcd_primitive(ON,*ptr); ptr++ ; } }  AVRで利用できる、初期化、最下層処理  ラッパー関数をまとめると、以下。 void init_lcd(void) { /* initialize hardware */ delay_ms(45) ; put_lcd_p4(OFF,0x30); /* select 8 bits */ delay_ms(5) ; put_lcd_p4(OFF,0x30); /* select 8 bits */ delay_ms(1); put_lcd_p4(OFF,0x30); /* select 8 bits */ delay_ms(1); /* set function */ put_lcd_p4(OFF,0x20); /* select 4 bits */ delay_ms(1); /* select 2 line display */ put_lcd_function(0x28); delay_ms(1); /* display off */ put_lcd_function(0x08); delay_ms(1); /* display on , cursor appear */ put_lcd_function(0x0e); delay_ms(1); /* entry mode*/ put_lcd_function(0x06); delay_ms(1); /* clear */ put_lcd_function(0x01); delay_ms(1); } void put_lcd_function(UBYTE xdat) { put_lcd_primitive(OFF,xdat); } void put_lcd_data(UBYTE xdat) { put_lcd_primitive(ON,xdat); } void put_lcd_primitive(UBYTE which,UBYTE dat) { put_lcd_p4(which,dat & MASKF0); put_lcd_p4(which,(dat << 4) & MASKF0); } void put_lcd_p4(UBYTE which,UBYTE dat) { /* LCD_E : OFF */ PORTD &= ~(1 << LCD_E) ; /* LCD_RS : ON or OFF */ PORTD &= ~(1 << LCD_RS) ; if ( which ) { PORTD |= (1 << LCD_RS) ;} /* nibble */ { /* clear upper nibble */ PORTD &= MASK0F ; /* impress upper nibble */ PORTD |= (dat & MASKF0) ; /* trigger H */ PORTD |= (1 << LCD_E) ; /* delay */ delay_ms(1); /* trigger L */ PORTD &= ~(1 << LCD_E) ; } } void put_lcd_str(UBYTE r,UBYTE c,UBYTE *ptr) { UBYTE adr ; /* check range */ if ( r > 1 ) return ; if ( c > 7 ) return ; /* set address */ adr = 0x00 ; if ( r ) { adr += 0x40 ; } adr += c ; adr |= MASK80 ; put_lcd_function(adr); /* send character */ for ( adr = c ; adr < 16 ; adr++ ) { put_lcd_data(*ptr); ptr++ ; } }

目次

inserted by FC2 system