今日は表示バッファを作ってそれで表示させるように改造
バッファを使う利点は同じ表示の場合その都度コマンドを送る必要が無いって事。
結果、描画速度が向上する。
まずは、キャラクタ液晶の仕様を再確認。
今回使っているのはGMD2020Bってやつで、20文字×2行表示ができるやつ。
DD RAMとしてはこんな感じになっている。
かつ、1つの場所には1文字(1バイト)分の領域があればいいんだから
バッファとしてはchar型の2,20の2次元配列を確保すればいいって事になる。
よって、変数宣言はこんな感じ。
char DispBuf[2][20]; //ディスプレイバッファ
加えて、今表示している状態を記憶しておかないといけないから、同じ領域でもう一つ必要。
char DispData[2][20]; //ディスプレイ表示中データ
これで、準備完了。
考え方は、表示中データとバッファを比較して、
違っている場所をLCDに転送&表示中データ更新を全部の表示に行う感じかな。
本当は厳密にやるなら、LCDの方から表示中のデータを読み込んだほうが良いんだろうけど
めんどくさいし、時間もかかりそうだからこれの方法でいいや。
自分で使うだけだし(笑)
//ディスプレイバッファから表示
void LCD_DataBufWrite() {
int i; int k; // i:処理中文字場所,k:処理中行
k = 0;
for (i=0;i<20;i++) {
if(DispBuf[k][i] != DispData[k][i]) {
LCD_DD_Adr_Set(0x00 + i);
LCD_DataWrite(DispBuf[k][i]);
DispData[k][i] = DispBuf[k][i];
}
}
k = 1;
for (i=0;i<20;i++) {
if(DispBuf[k][i] != DispData[k][i]) {
LCD_DD_Adr_Set(0x40 + i);
LCD_DataWrite(DispBuf[k][i]);
DispData[k][i] = DispBuf[k][i];
}
}
LCD_GPIOPin_AllOff(); // Output data all off
}
これで、DispBufにデータを書き込んで、
表示を切り替えたいときにLCD_DataBufWrite()を実行すれば
表示が切り替わってくれるはず。
これを組み込んでテストしてみよう!
メインプログラムはこんな感じでテスト。
DispBuf[0][0] = 'A';
DispBuf[0][5] = 'B';
DispBuf[0][16] = 'C';
DispBuf[1][3] = 'D';
DispBuf[1][10] = 'E';
DispBuf[1][19] = 'F';
LCD_DataBufWrite();
OKOKちゃんと動いてる。
とはいうものの、1文字1文字入力していくのも大変だから
やっぱり文字列で表示できるようにしたい。
ので、文字列をバッファに書き込む専用命令を作ってみる。
//バッファに文字列書込み
// 引数1:書込み文字列へのポインタ
// 引数2:書き込む位置
// 引数3:文字列長
// 引数4:書込む行
void LCD_DataBuf(char *strData, int Pos, int Len, int Col) {
int i; int j = 0;
int flag=0;
//引数チェック
if (Pos > 19) Pos = 19;
if (Len > 20) {
Len = 20;
} else if ((Len + Pos) > 20) {
Len = 20 - (Pos);
}
//ディスプレイバッファに書き込み
for (i=Pos ; i < Pos+Len; i++){
DispBuf[Col][i] = strData[j];
j++;
}
//改行コードまたはヌルがあった場合はそれ以降をスペースで埋める
for (i=Pos ; i < Pos+Len; i++){
if (DispBuf[Col][i] == '\n' || DispBuf[Col][i] == '\0') flag =1;
if (flag == 1) DispBuf[Col][i] = ' ';
}
}
文字列と書き込む位置を指定してやるとバッファに書き込んでくれるようにしてみた…んだけど、これでいいのかなぁ。
とりあえず組み込んでテスト。
メインプログラムはこんな感じにしてみた。
LCD_DataBuf("Write Test",0,10,0);
LCD_DataBuf("01234",15,5,0);
LCD_DataBuf("HOGE_Hoge",5,9,1);
LCD_DataBufWrite();
何とか表示しているみたいだね(^^;)
ここまで作ったから、ちょっと遊びで時計でも表示させてみようかな…
現在時刻を取得する方法はこのサイトを参考にした。
時計を標準入主力で表示するためには…
#include<stdio.h>
#include<time.h>
int main(void)
{
time_t timer;
struct tm *date;
timer = time(NULL);
date = localtime(&timer);
printf("%s\n", asctime(date));
}
って感じに書けばいいらしいから、これを応用して。
メインプログラムをこんな感じにしてみた。
#include<time.h>
int main(void)
{
int i;
time_t timer;
struct tm *date;
if(wiringPiSetupGpio() == -1) return 1;
LCD_Initialize();
while(i<500){
timer = time(NULL);
date = localtime(&timer);
LCD_DataBuf(asctime(date),0,20,0);
LCD_DataBufWrite();
delay(10);
i++;
}
return 0;
}
ちなみにasctime関数は、25文字で曜日と月時間年とかを返してくれるみたいだけど
この20文字LCDではちょうどいい表示「Thu Oct 27 12:34:56 」になってくれた。
16文字だと「Thu Oct 27 12:34」ってかんじになるから、
もし好きな感じに表示したい場合はstrftime関数を使うといいみたい。
char str[256];
strftime(str, 255, "%b, %d, %H:%M:%S", date);
LCD_DataBuf(str,0,20,0);
こんな感じにすれば「Oct, 27, 12:34:56」って感じになる。
と、こんな感じでとりあえず、バッファで表示させるのは成功ってことで…
実際は色々不具合ありそうだけど、自分で使うだけだからその辺は目をつぶるって事で(^^;)
次は、表示バッファの処理も含めてファイルを分け用と思う。
ほとんどLCD表示用の関数ばっかりで管理が大変だよ…