カテゴリ
リンク

当サイトは、玄箱PRO (KURO-BOX/Pro)を中心とした組み込み、Linuxと電子工作を扱っています。
会社案内

情報セキュリティおよび個人情報の取り扱いについて


コメントとトラックバックは、spamを予防するために、編集担当が公開の作業をするまで非公開になっています。コメントはそれぞれ投稿した人のものです。

■グラフィック液晶を使って時計を作る
 秋月のグラフィック液晶に時刻を表示して時計にしてみることにしました。NTP を使っていれば、かなり正確な時刻を表示してくれます。せっかくのグラフィック液晶なので、時刻を表示するだけではなく、アイコンを動かしてみます。

LCDに時刻表示

■プログラムの概要
 プログラムの流れは次のようにします。
    (1) シリアル通信の初期化
   (2) 液晶のリセット
   (3) 液晶のバックライトを点滅する
   (4) 時刻を調べて、1秒経過するまで待つ
   (5) 液晶に時刻を表示
   (6) 車アイコンを表示
   (7) (4) へ 
 1秒ごとに、液晶に表示データを送りますが、1秒待ちをするために、0.1秒後とに時刻を調べることで、秒の変化と表示の変化の遅れを減らします。 

■シリアル通信の初期化
 シリアル通信の初期化は、asy_init()関数で行っています。秋月のグラフィック液晶の通信条件は、ボーレート 38400bps, 8ビット, パリティなし、stop ビット1, フロー制御なしです。
  asy_init()関数は次のようにしました。設定は入力、出力、ローカル、制御、制御文字に分かれています。制御文字は直訳なのでわかりにくい表現ですが、拡張設定の項目と思ってよいかもしれません。
int

asy_init(int fd, speed_t speed)

{

 struct termios	t;

 int modemline;	/* 現在の設定を読む */

 tcgetattr(fd, &t);
 ここで、現在の設定を構造体 t に読み込みます。
 /* ボーレートのセット */

 cfsetspeed(&t, speed);
 ボーレートを設定します。asy_init()を呼び出すときに speed で指定されたものをそのまま cfsetspeed() に渡しています。speed は、数値ではなく、 B38400 など、ボーレートに B をつけたもので指定します。B38400 などはヘッダ・ファイル内で定義されています。
 /* raw モードのセット(パリティ・チェックなし) */

 cfmakeraw(&t);	/* 入力モードの設定 */

 t.c_iflag = (IGNBRK | IGNPAR);
 ブレーク信号やパリティ・エラーが発生しても無視します。
 /* 制御モードの設定 */

 t.c_cflag = (CS8 | CREAD | CLOCAL);
 8ビット, 受信許可, フロー制御なしとします。CREAD を設定しないと受信できないことに注意します。ここで CSTOPB を指定しなければストップ・ビットは'1'になります。
 /* 制御文字の設定, 0.1 秒が経過するか 1 文字受信するまでブロックする */

 t.c_cc[VTIME] = 1; /* 0.1 sec */

 t.c_cc[VMIN] = 1;  /* 1 char */
 データを受信しなかったときに、 read() 関数があきらめるまでの設定をします。VTIME はあきらめるまでの時間を 0.1秒単位で指定します。VMIN は最低読み込む文字数です。ここでは、0.1秒間 1 文字以上受信できるまで read() 関数はあきらめません。その間、read() 関数を呼び出した側はブロックされます。  両方とも '0' を設定すると、受信バッファがからのときも read() 関数はすぐに戻ってきます。
 /* 上記の設定をする */

 tcsetattr(fd, TCSANOW, &t);
 tcsetattr() を使うことで設定をします。TCSANOW を指定しているのですぐに設定が反映されます。
 /* バッファをフラッシュする */

 tcflush(fd, TCIOFLUSH);
 送受信バッファを消してしまいます。
 return 0;

}

■液晶へのデータの送信
 シリアル通信では、write() 関数でデータを送信します。fputc() などバッファする関数は送信タイミングがつかみにくくなるので使いません。また、秋月のグラフィック液晶は3文字以上連続して送信するとデータを取りこぼすようでしたので、1文字送るごとにしばらく待つ関数 mywrite() を用意しました。
int

mywrite(int fd, const void *buf, int count)

{

  int i;  for (i=0; i

    write(fd, buf, 1);

    buf ++;

    usleep(1*1000);

  }

return i;

}

■液晶からのデータの受け取り
 シリアル通信では、read() 関数でデータを受信します。fgetc(), fgets() などバッファする関数は使いません。ここでは初期化時に VTIME, VMIN を共に '1' を指定しているので、 液晶からデータが送られない場合、最大0.1秒 read() から戻ってくるまで時間がかかります。
  ここでは、グラフィック液晶から、1文字受信して期待するものと一致するかを調べる関数 checkret() を用意しました。ここで、文字が期待するものと一致しない場合、0.1秒以内に返事がない場合はエラーとして、プログラムを終了しています。
void

checkret(int fd, char c)

{

  char r;  if (read(fd, &r, 1) < = 0) {

    fprintf(stderr, "Read timeoutn");

    exit(1);

  }

  if (r != c) {

    fprintf(stderr, "Unexpected char returnedn");

    exit(1);

  }

}

■時刻を読む
 現在の時刻は gettimeofday() で読みます。tv.tv_sec には、UNIX TIME (世界協定時(UTC) で 1970 年1月1日 00:00 よりの経過秒数) が入っているので、localtime() 関数(localtime_r()関数)で、日本標準時 (JST)に変換しています(玄箱PROのタイムゾーンの設定が正しいと仮定している)。そして sprintf() で表示するフォーマットを決めています。ここでは、「月/日 時:分 秒」です。
    struct timezone tz;

    struct tm tm_;    gettimeofday(&tv, &tz);

    localtime_r(&tv.tv_sec, &tm_);

sprintf(buf, "%02d/%02d %02d:%02d %02d", tm_.tm_mon + 1, tm_.tm_mday,

     tm_.tm_hour, tm_.tm_min, tm_.tm_sec);

■アニメーション
 秋月のグラフィック液晶の漢字フォント用のページ1に、二つの 16×8 のフォントを用意し、交互に表示することでアニメーションにしてみました。図は右方向ですが、左方向も用意してあります。

車アイコン


■動かしてみる
 まず font-clock.txt をダウンロードして、秋月のツールを使ってフォントとして書き込んでください。つぎにclock.c をダウンロードして、
cc -o clock clock.c
または、

make clock

でコンパイルしてください。グラフィック液晶をつないだポートを指定し、実行します。
./clock /dev/ttyUSB0
 /dev/ttyUSB0 の場合は省略可能です。実行すると動画のように表示されます。

LCDに時刻表示(ビデオの最初のフレーム) グラフィックLCD に時刻を表示している様子(クリックすると動画が表示される)

 カテゴリ 

 

トラックバック(0)

このブログ記事を参照しているブログ一覧: シリアル・ポートを使ってLCDに時刻を表示してみる

このブログ記事に対するトラックバックURL: http://www.eleki-jack.com/mt/mt-tb.cgi/1089

コメントする

おすすめ書籍
Powered by
Movable Type 4.1