はじめに
前回はLCDを8bitモード・4bitモードで表示しました。
しかし、これでは、LCDへの命令を送った後、
delay()関数で必ず50μ秒の待ちが発生してしまい、
その間、さまざまな仕事ができるCPUが停止してしまいます。
できるだけCPUの稼働を止めないために、
今回はLCDのBusy Flagを読み取り、
LCDの処理完了を確認してから
次の命令を送る方法を試してみます。
Busy Flagとは
LCD内部が処理中かどうかを示すフラグです。
Busy中
c
DB7 = 1
待機・処理可能
DB7 = 0
となります。
Busy Flagを使うために必要なもの
これまでは、
データピンと電源ピン、コントラストピン、RS・E を使用し、
R/WピンはGNDに落としていました。
Busy Flagを読むために今回は
R/WピンもPICへ接続します。

タイミングチャートを読む
LCDコントローラICのST7066Uのデータシートには、
下のようなタイミングチャートが記載されています。

タイミングチャートをみると、
RS=0、R/W(Read/Write)=1、E(Enable:読取OK)=1
の時にDBを読み取りモードにしている時および、
上位4bitの読み取り時のみ、
Busy Flagがチェック可能ということが読み取れます。
4bitモードでBusy Flagを読む流れ
- RA4~RA7を入力へ変更
- R/W=1
- RS=0
- E=1
- DB7を読む
- E=0
- 下位4bitを捨てるためにもう一度Eをトグル
- RA4~RA7を出力へ戻す。
実装したコードと結果
c
unsigned char lcd_read_busy(void)
{
unsigned char busy;
TRISA |= 0xF0; //RA4-7 input
LATCbits.LATC1 = 0; //RS=1
LATCbits.LATC3 = 1; //R/W read mode
LATCbits.LATC2 = 1; //E=1
__delay_us(1);
busy = PORTAbits.RA7; //Busy Flag
LATCbits.LATC2 = 0; //E=0
LATCbits.LATC2 = 1;
__delay_us(1);
LATCbits.LATC2 = 0;
LATCbits.LATC3 = 0; //R/W write mode
TRISA &= 0x0F; //RA4-7 output
return busy;
}
上記でBusy Flagを読む流れをそのままコードにし、
下記のコードで実際に動かします。
c
void lcd_wait_busy(void)
{
while(lcd_read_busy())
{
}
}
Busy Flagが消えるまで、
”待つ”
ですね。
これを前回の記事のコードにうまく織り交ぜて動かしました。
c
void lcd_cmd(unsigned char cmd)
{
LATCbits.LATC1 = 0; //RS=0
LATCbits.LATC3 = 0; //write
lcd_send_nibble(cmd >> 4);
lcd_send_nibble(cmd & 0x0F);
lcd_wait_busy();
}
void lcd_cmd_no_busy(unsigned char cmd)
{
LATCbits.LATC1 = 0; //RS=0
lcd_send_nibble(cmd >> 4);
lcd_send_nibble(cmd & 0x0F);
}
void lcd_data(unsigned char data)
{
LATCbits.LATC1 = 1; //RS=1
LATCbits.LATC3 = 0; //write
lcd_send_nibble(data >> 4);
lcd_send_nibble(data & 0x0F);
lcd_wait_busy();
}
上記コードの真ん中の
lcd_cmd_no_busy()関数についてです。
LCDの初期化でBusy Flagを見てはならぬ
とデータシートにあるため、
Busy Flagを見ないための関数も用意しました。
結果は

またしても世界で最もよく表示されている
「Hello World」
を表示させることができました。
実際にやってみて
これまでは、タイミングチャートを見ても
意味が全く分からなかったので
拒否反応が出てしまってました。
しかし、今回初めて
「えっ?!読めるかも?!?!」
と感じました。
少し読みが甘い部分もあり、
なかなかコードを書くことにも苦戦を強いられましたが、
ChatGPTの甘~いヒントを頂き、
最終は血だらけの修正を受け悔しい思いもしながら
何とか漕ぎつけることができました。
次回予告
Busy Flagを使うことで、
LCDが処理完了するまで待つ仕組みが作れました。
お陰で、一処理ずつに使われていた
__delay_us(50)
を削除させることに成功しました。
次回はRS485通信へ戻り、
UARTを差動通信へ発展させていきます。

コメント