【番外編3】PIC16F1938でLCDのBusy Flagを使ってみる

はじめに

前回は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を読む流れ

  1. RA4~RA7を入力へ変更
  2. R/W=1
  3. RS=0
  4. E=1
  5. DB7を読む
  6. E=0
  7. 下位4bitを捨てるためにもう一度Eをトグル
  8. 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を差動通信へ発展させていきます。

コメント

タイトルとURLをコピーしました