LCDキャラクタ表示のプログラムにおけるPortの操作に関する初歩的な質問

皆様

先般は,CAN通信で貴重な情報をいただきありがとうございました.おかげ様でMCP2521を使い,基地局に使用されているPSUのCANデータを読み取ることができました.

今回ご教示いただきたいのは基本的なPortのコーディング方法です.下記の引用コードは,G13のStarter KitのLCD表示に関するものです.4bitインターフェースで,LCDのDB7,DB6, DB5, DB4に接続されているポートP73, P72, P71, P70にデータをセットし,Enable信号を短時間Onにするプログラムです.

ここで,ucStore = DATA_PORT; は何を意味しているのでしょうか? このような使い方は一般的でしょうか? 私は,これまでP7_bit.no0 のようにしポート制御していました.

ご教示よろしくお願いします.

=== QUOTE ===

/* RS Register Select pin */
#define RS_PIN                  P5_bit.no5
/* Display Enable pin */
#define EN_PIN                  P5_bit.no4
/* Data bus port */
#define DATA_PORT               P7
/* Bit mask from entire port */
#define DATA_PORT_MASK          0x0F
/* Number of bits data needs to shift */
#define DATA_PORT_SHIFT         0

#define DATA_WR 1
#define CTRL_WR 0

void LCD_nibble_write(uint8_t data_or_ctrl, int8_t value)
{
    int8_t ucStore;

    /* Set Register Select pin high for Data */
    if (data_or_ctrl == DATA_WR)
    {
        RS_PIN = SET_BIT_HIGH;
    }
    else
    {
        RS_PIN = SET_BIT_LOW;
    }

    /* There must be 40ns between RS write and EN write */
    DisplayDelay(1);

    /* EN enable chip (HIGH) */
    EN_PIN = SET_BIT_HIGH;

    /* Tiny delay */
    DisplayDelay(1);

    /* Clear port bits used */
    ucStore = DATA_PORT;
    ucStore &= (int8_t) ~DATA_PORT_MASK;

    /* OR in data */
    ucStore |= (int8_t) ((value << DATA_PORT_SHIFT) & DATA_PORT_MASK );

    /* Write data to port */
    DATA_PORT = ucStore;

    /* write delay while En High */
    DisplayDelay(20);

    /* Latch data by dropping EN */
    EN_PIN = SET_BIT_LOW;

    /* Data hold delay */
    DisplayDelay(20);

    if (data_or_ctrl == CTRL_WR)
    {
        /* Extra delay needed for control writes */
        DisplayDelay(0x7FF);
    }
}

=== UNQUOTE ===

Parents
  • tok2010さん、こんにちは。NoMaYです。#お久しぶりです。

    正直なところ、文面からだけでは何に困惑しているのか分からなくて確認したいのですが、こういうことですか?

    (1) 今までは、ポートを操作する時は1ビットずつ(1本ずつ)操作していた
    (2) 今回、数ビットまとめて(数本まとめて)同時に操作出来るらしいことを知って驚いた?

  • チョコです。

    NoMaYさんに追加しておくと、「#define DATA_PORT               P7」で、下位4ビットがLCDのDB7,DB6, DB5, DB4に接続されているポート7をDATA_PORTと名前を付けています。

    P7の上位4ビットは別の用途で使われているようなので、上位4ビットの値が変わらないように、LCDにデータをセットするためにP7に書き込みを行う前に、P7の上位データを読み出しているのが問題の処理です。

    次の"ucStore &= (int8_t) ~DATA_PORT_MASK;"でLCD用のデータ領域である下位4ビットをクリアしておきます。

    その次の"ucStore |= (int8_t) ((value << DATA_PORT_SHIFT) & DATA_PORT_MASK );"で出力したいデータを下位4ビットにセットして、"DATA_PORT = ucStore;"で、P7の上位4ビットの状態とマージしたデータをP7に書き戻すことで、LCDにデータをセットしても別の用途で使用しているP7上位4ビットが変化しないようにしているだけですね。

    これは、一般的に用いられる方法ですね。

    以上

Reply
  • チョコです。

    NoMaYさんに追加しておくと、「#define DATA_PORT               P7」で、下位4ビットがLCDのDB7,DB6, DB5, DB4に接続されているポート7をDATA_PORTと名前を付けています。

    P7の上位4ビットは別の用途で使われているようなので、上位4ビットの値が変わらないように、LCDにデータをセットするためにP7に書き込みを行う前に、P7の上位データを読み出しているのが問題の処理です。

    次の"ucStore &= (int8_t) ~DATA_PORT_MASK;"でLCD用のデータ領域である下位4ビットをクリアしておきます。

    その次の"ucStore |= (int8_t) ((value << DATA_PORT_SHIFT) & DATA_PORT_MASK );"で出力したいデータを下位4ビットにセットして、"DATA_PORT = ucStore;"で、P7の上位4ビットの状態とマージしたデータをP7に書き戻すことで、LCDにデータをセットしても別の用途で使用しているP7上位4ビットが変化しないようにしているだけですね。

    これは、一般的に用いられる方法ですね。

    以上

Children
  • チョコです。

    蛇足ながら、少し追加しておきます。

    RL78のポートに対するビット処理はリード・モディファイ・ライトと呼ばれている手順で、最初にポートの状態の読み出し(リード)、次に読み出したデータの一部の変更(モディファイ)、最後に変更した結果のポートへの書き戻し(ライト)の3段階で処理されています。

    今回の処理もリード・モディファイ・ライトです。その中のリード部分が"ucStore = DATA_PORT;"です。

    ビット処理命令がなかった時代から使われている手順です。この手順をソフトで行う場合には、割り込みで対象のポートへの書き込みがあると期待した動作と異なることになるので、排他的に処理する必要があります。ちなみにビット操作命令では、処理中に割り込みを受け付けることはないので、この問題はありませんが。

    以上