目次

LCDデバイステスト

 自作機器には、2行x16桁のLCDを接続して
 使うことが多いです。



 このLCDには、データバスを4ビットで使うか
 8ビットで使うのかを初期化時に指定可能。

 配線数を少なくするため、マイコンとは10ピン
 のリボンケーブルで接続。



 多数所有しているLCDが使えるかを調べるため
 Arduinoを使うことにしました。



 Arduinoには、LCDを扱うライブラリが用意されて
 いるので、デジタルピンを次のように使うことに。

/* LCD rs , e , D4 , D5 , D6 , D7 */
LiquidCrystal lcd( 2, 3, 4, 5, 6, 7 );

 10ピンケーブルの1から10の信号割り当ては
 次のように指定。
  1. Vcc
  2. D7(7)
  3. D6(6)
  4. D5(5)
  5. D4(4)
  6. e (3)
  7. rs(2)
  8. GND
 信号線は、写真の上にあるコネクタの6ピンを利用。  電源は、写真の下にあるコネクタの2ピンを利用。  (5Vと0Vを使うことに。)  LCDは、コネクタを利用して、基板に取り付けられる  ようにしておきます。  10ピンコネクタを使い、リボンケーブルでArduinoと  接続できます。  コントラス調整の可変抵抗器を使い、トリマーを回して  文字と記号を見やすく調整できるようにしてあります。  ブレッドボードに使うワイヤーとリボンケーブルを  接続すると、次のようになります。  ブレッドボードのワイヤーだと、リボンケーブルから  抜けることもあるので、半田付けでコネクタワイヤー  を用意して対応しました。  ハードウエアができたので、Arduinoスケッチを作成。  ソースコードは、以下。 #include <MsTimer2.h> #include <LiquidCrystal.h> #define OFF 0 #define ON OFF+1 #define LED_BIT 5 #define XINTERVAL 1000 /* LCD rs , e , D4 , D5 , D6 , D7 */ LiquidCrystal lcd( 2, 3, 4, 5, 6, 7 ); /* function prototype */ void update_trigger(); void show_help(); void rs_putchar(char x); void rs_puts(char *ptr); void crlf(); void init_lcd(); /* variables */ boolean tflag ; boolean uflag ; boolean eflag ; char sbuf[8] ; byte sindex ; char cmd ; /* state machine */ byte state ; byte ycnt ; /* LED handling counter */ byte xcnt ; void setup() { /* initialize serial */ Serial.begin(9600); sindex = 0 ; rs_puts("Hello !"); crlf(); show_help(); /* clear flags */ tflag = OFF ; uflag = OFF ; eflag = OFF ; /* initialize port values */ PORTB = 0x04 ; PORTC = 0x00 ; PORTD = 0x00 ; /* initialize port direction */ DDRB = 0xf7 ; DDRC = 0x00 ; DDRD = 0xfe ; /* 1000ms period */ MsTimer2::set(XINTERVAL,update_trigger); /* enable */ MsTimer2::start(); /* initialize LCD */ init_lcd(); /* others */ state = 0 ; xcnt = 0 ; ycnt = 0 ; } void loop() { /* command interpreter */ if ( uflag == ON ) { /* clear flag */ uflag = OFF ; /* get command */ cmd = *(sbuf+0) ; /* help */ if ( cmd == '?' ) { show_help(); } /* LCD */ if ( cmd == 'I' ) { init_lcd(); } /* timer start */ if ( cmd == 'T' ) { state = 0 ; /* set execute flag */ eflag = ON ; } /* timer stop */ if ( cmd == 't' ) { /* clear execute flag */ eflag = OFF ; init_lcd(); } /* new line */ crlf() ; } /* timer handling */ if ( tflag == ON ) { /* clear flag */ tflag = OFF ; /* execute */ if ( eflag == ON ) { switch ( state ) { case 0 : lcd.setCursor(0, 0); lcd.print("*** TEST LCD ***"); lcd.setCursor(0, 1); lcd.print("----------------"); break ; case 1 : lcd.setCursor(0, 0); lcd.print("----------------"); lcd.setCursor(0, 1); lcd.print("*** TEST LCD ***"); break ; case 2 : lcd.setCursor(0, 0); lcd.print("--- test lcd ---"); lcd.setCursor(0, 1); lcd.print("****************"); break ; case 3 : lcd.setCursor(0, 0); lcd.print("****************"); lcd.setCursor(0, 1); lcd.print("--- test lcd ---"); break ; default : break ; } state++ ; if ( state >= 4 ) { state = 0 ; } } } } void update_trigger() { /* impress LED */ PORTB &= ~(1 << LED_BIT) ; if ( xcnt & ON ) { PORTB |= (1 << LED_BIT) ; } /* update */ xcnt++ ; /* judge */ if ( ycnt & ON ) { tflag = ON ; } ycnt++ ; } void show_help() { rs_puts("? help") ; crlf(); rs_puts("I initialize LCD"); crlf(); rs_puts("T timer start") ; crlf(); rs_puts("t timer stop") ; crlf(); } void rs_putchar(char x) { Serial.write(x); } void rs_puts(char *ptr) { while ( *ptr ) { rs_putchar( *ptr ); ptr++; } } void crlf() { rs_putchar('\r'); rs_putchar('\n'); } void init_lcd() { lcd.begin( 16, 2 ); lcd.clear(); lcd.setCursor(0, 0); lcd.print("+-+-+-+-+-+-+-+-"); lcd.setCursor(0, 1); lcd.print("-+-+-+-+-+-+-+-+"); } /* receive interrupt */ void serialEvent() { char ch; if ( Serial.available() > 0 ) { /* get 1 character */ ch = Serial.read(); /* store */ *(sbuf+sindex) = ch ; /* increment */ sindex++ ; /* judge */ if ( ch == '\r' ) { sindex = 0 ; uflag = ON ; } } }  端末ソフトを使い、次のコマンドでLCDに表示する  文字列を決定します。  LCDを初期化すると、次のように文字列が表示されます。 +-+-+-+-+-+-+-+- -+-+-+-+-+-+-+-+  2秒周期で表示文字列更新するときは、次の4パターン  を繰り返していきます。 *** TEST LCD *** ---------------- ---------------- *** TEST LCD *** --- test lcd --- **************** **************** --- test lcd --- ↓  最初にもどる  簡単なシーケンス処理ですが、LCDの動作試験には  充分役に立ちます。  通信プロトコルは、以下。  WindowsであればTeratermを使うと簡単に  LCDのGood、No Goodを判定できます。  Arduinoスケッチを見直すと、タイマーによる  LCD表示処理の一部が冗長だったので変更。  Arduinoが動作中であることがわかるように  基板上のLEDを点滅するように、専用関数を  用意。その内容は、以下。 void flash_led() { /* impress LED */ PORTB &= ~(1 << LED_BIT) ; if ( xcnt & ON ) { PORTB |= (1 << LED_BIT) ; } /* update */ xcnt++ ; }  この専用関数を呼び出すのは、タイマー割込みが発生した  ときとして、タイマー割込み処理の部分に埋め込みます。 if ( tflag == ON ) { /* clear flag */ tflag = OFF ; /* LED handling */ flash_led();  LED点滅は、LCDの動作試験には無関係ですが、周期的に  表示文字列を変更するために、上のようにしました。  これで、タイマー割込み発生のときには、フラグをセット  するだけで、loop()に処理を任せられます。 void update_trigger() { /* judge */ if ( ycnt & ON ) { tflag = ON ; } /* increment */ ycnt++ ; }  LCDに周期的に文字列を表示するとき、周期を1秒としたいので  MsTimer2に指定する周期を500msに変更。  変更は、マクロ定義してある数値を書き換えるだけ。 #define XINTERVAL 500  変更したArduinoスケッチは、以下。 #include <MsTimer2.h> #include <LiquidCrystal.h> #define OFF 0 #define ON OFF+1 #define LED_BIT 5 #define XINTERVAL 500 /* LCD rs , e , D4 , D5 , D6 , D7 */ LiquidCrystal lcd( 2, 3, 4, 5, 6, 7 ); /* function prototype */ void update_trigger(); void show_help(); void rs_putchar(char x); void rs_puts(char *ptr); void crlf(); void init_lcd(); void flash_led(); /* variables */ boolean tflag ; boolean uflag ; boolean eflag ; char sbuf[8] ; byte sindex ; char cmd ; /* state machine */ byte state ; byte ycnt ; /* LED handling counter */ byte xcnt ; void setup() { /* initialize serial */ Serial.begin(9600); sindex = 0 ; rs_puts("Hello !"); crlf(); show_help(); /* clear flags */ tflag = OFF ; uflag = OFF ; eflag = OFF ; /* initialize port values */ PORTB = 0x04 ; PORTC = 0x00 ; PORTD = 0x00 ; /* initialize port direction */ DDRB = 0xf7 ; DDRC = 0x00 ; DDRD = 0xfe ; /* 1000ms period */ MsTimer2::set(XINTERVAL,update_trigger); /* enable */ MsTimer2::start(); /* initialize LCD */ init_lcd(); /* others */ state = 0 ; xcnt = 0 ; ycnt = 0 ; } void loop() { /* command interpreter */ if ( uflag == ON ) { /* clear flag */ uflag = OFF ; /* get command */ cmd = *(sbuf+0) ; /* help */ if ( cmd == '?' ) { show_help(); } /* LCD */ if ( cmd == 'I' ) { init_lcd(); } /* timer start */ if ( cmd == 'T' ) { state = 0 ; /* set execute flag */ eflag = ON ; } /* timer stop */ if ( cmd == 't' ) { /* clear execute flag */ eflag = OFF ; init_lcd(); } /* new line */ crlf() ; } /* timer handling */ if ( tflag == ON ) { /* clear flag */ tflag = OFF ; /* LED handling */ flash_led(); /* execute */ if ( eflag == ON ) { switch ( state ) { case 0 : lcd.setCursor(0, 0); lcd.print("*** TEST LCD ***"); lcd.setCursor(0, 1); lcd.print("----------------"); break ; case 1 : lcd.setCursor(0, 0); lcd.print("----------------"); lcd.setCursor(0, 1); lcd.print("*** TEST LCD ***"); break ; case 2 : lcd.setCursor(0, 0); lcd.print("--- test lcd ---"); lcd.setCursor(0, 1); lcd.print("****************"); break ; case 3 : lcd.setCursor(0, 0); lcd.print("****************"); lcd.setCursor(0, 1); lcd.print("--- test lcd ---"); break ; default : break ; } state++ ; if ( state >= 4 ) { state = 0 ; } } } } void update_trigger() { /* judge */ if ( ycnt & ON ) { tflag = ON ; } /* increment */ ycnt++ ; } void show_help() { rs_puts("? help") ; crlf(); rs_puts("I initialize LCD"); crlf(); rs_puts("T timer start") ; crlf(); rs_puts("t timer stop") ; crlf(); } void rs_putchar(char x) { Serial.write(x); } void rs_puts(char *ptr) { while ( *ptr ) { rs_putchar( *ptr ); ptr++; } } void crlf() { rs_putchar('\r'); rs_putchar('\n'); } void init_lcd() { lcd.begin( 16, 2 ); lcd.clear(); lcd.setCursor(0, 0); lcd.print("+-+-+-+-+-+-+-+-"); lcd.setCursor(0, 1); lcd.print("-+-+-+-+-+-+-+-+"); } void flash_led() { /* impress LED */ PORTB &= ~(1 << LED_BIT) ; if ( xcnt & ON ) { PORTB |= (1 << LED_BIT) ; } /* update */ xcnt++ ; } /* receive interrupt */ void serialEvent() { char ch; if ( Serial.available() > 0 ) { /* get 1 character */ ch = Serial.read(); /* store */ *(sbuf+sindex) = ch ; /* increment */ sindex++ ; /* judge */ if ( ch == '\r' ) { sindex = 0 ; uflag = ON ; } } }  このスケッチは、ATmega8、ATmega168、ATmega328と  デバイスを載せかえても、問題なく動作しました。  ATmega8を利用したときだけ、端末ソフトでの起動が  ゆっくりでした。  TeraTermでの操作は、次のようになります。
目次

inserted by FC2 system