目次

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

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

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

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

 場合によっては、10ピンを利用できないこともある。シフトレジスタ
 74HC164を利用し、データを2ビットで一度レジスタにラッチ後
 LCDに転送すれば、4ピンで制御できる。

 回路は、下図のようにする。



最下層処理

 74HC164のデータ入力A、Bに同じデータを入力し、クロックを  与えれば8ビットのデータを転送できる。  LCDにデータを転送するシーケンスは、以下とする。
  1. シフトレジスタにデータを転送する
  2. EをLにする
  3. RSを、HかLのどちらかに設定
  4. データ8ビットを出力
  5. EをHにする
  6. EをLにする
シフトレジスタにデータを転送するシーケンスは、以下とする。
  1. シフトレジスタのCLKをLにする
  2. 2^7(MSB)ビットを出力
  3. シフトレジスタのCLKをHにする
  4. シフトレジスタのCLKをLにする
  5. 2^6ビットを出力
  6. シフトレジスタのCLKをHにする
  7. シフトレジスタのCLKをLにする
  8. 2^5ビットを出力
  9. シフトレジスタのCLKをHにする
  10. シフトレジスタのCLKをLにする
  11. 2^4ビットを出力
  12. シフトレジスタのCLKをHにする
  13. シフトレジスタのCLKをLにする
  14. 2^3ビットを出力
  15. シフトレジスタのCLKをHにする
  16. シフトレジスタのCLKをLにする
  17. 2^2ビットを出力
  18. シフトレジスタのCLKをHにする
  19. シフトレジスタのCLKをLにする
  20. 2^1ビットを出力
  21. シフトレジスタのCLKをHにする
  22. シフトレジスタのCLKをLにする
  23. 2^0ビットを出力
  24. シフトレジスタのCLKをHにする
  25. シフトレジスタのCLKを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 ; /* send 8 bit data */ SHF_CLK = OFF ; for ( i = 0 ; i < 8 ; i++ ) { SHF_DAT = OFF ; if ( dat & 0x80 ) { SHF_DAT = ON ; } SHF_CLK = ON ; dat <<= 1 ; SHF_CLK = OFF ; } /* 0 -> E */ LCD_E = OFF ; /* RS */ LCD_RS = which ; /* 1 -> E */ LCD_E = ON ; /* 0 -> E */ LCD_E = OFF ; }  I/OマップドI/Oの場合 void put_lcd_primitive(UBYTE which,UBYTE dat) { UBYTE i ; UBYTE ctmp; /* send 8 bit data */ ctmp &= ~SHF_CLK ; outp( LCD_CP , ctmp ); for ( i = 0 ; i < 8 ; i++ ) { ctmp &= ~SHF_DAT ; if ( dat & 0x80 ) { ctmp |= SHF_DAT ; } outp( LCD_CP , ctmp ); ctmp |= SHF_CLK ; outp( LCD_CP , ctmp ); dat <<= 1 ; ctmp &= ~SHF_CLK ; outp( LCD_CP , ctmp ); } /* 0 -> E */ ctmp &= ~LCD_E ; outp( LCD_CP , ctmp ); /* RS */ ctmp &= ~LCD_RS ; if ( which ) { ctmp |= LCD_RS ; } outp( LCD_CP , 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. RS=L状態で、0x01を転送
  11. 最短2ms待ち
  12. RS=L状態で、0x06を転送
  13. 最短2ms待ち
  14. RS=L状態で、0x0cを転送
  15. RS=L状態で、0x02を転送
  16. RS=L状態で、0x80を転送
 ms単位での時間待ちをすることができる関数があるとして  次のように、初期化コードを記述する。 void init_lcd(void) { /* initialize hardware */ mwait_by(15) ; /* 25ms */ put_lcd_primitive(OFF,0x30); mwait_by(5) ; /* 5ms */ put_lcd_primitive(OFF,0x30); mwait_by(1); /* 1ms */ put_lcd_primitive(OFF,0x30); mwait_by(1); /* 1ms */ put_lcd_primitive(OFF,0x20); mwait_by(1); /* 1ms */ /* set function */ put_lcd_primitive(OFF,0x28); put_lcd_primitive(OFF,0x08); put_lcd_primitive(OFF,0x01); mwait_by(2); /* 2ms */ put_lcd_primitive(OFF,0x06); mwait_by(2); /* 2ms */ put_lcd_primitive(OFF,0x0c); put_lcd_primitive(OFF,0x02); put_lcd_primitive(OFF,0x80); }  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++ ; } }

目次

inserted by FC2 system