汎用キャラクタLCDのI2C化(2) 試作、WSN318

既に基板化しているのですが、ここでは、まず最初にブレッドボードでCQカチャ(WSN282)を使ったI2C化キットをつくり作動させます。

●回路構成

I2C化コントローラの回路は、ArduinoでLCDに文字を出すだけのなんの変哲もない回路です。ArduinoにはI2CのI/Fがあるので、ArduinoをI2Cのスレーブにして、コマンドを受け取れるようにし、そのコマンドでLCDを制御するようなプログラム(ファームウェア)を作成します。

このコントローラはArduinoでなくても良いのですが、開発が簡単なので、Arduinoを利用します。ファームウェアの書き換えも簡単です。

次の図はI2C化回路の基本的なものです。代表的な14ピンタイプのLCDの結線例で、図左下は制御端子が1列に並んだタイプ、右下は2列×7のもっとも一般的なタイプのLCDの配線です。

lcd404-5

配線量を減らすため、LCDは4ビットモードで使用します。

次の写真は制御端子2列タイプで16文字×2行のLCDで製作したコントローラです。コンパクトにするために、WSN234 LCD BB直結アダプタを使用してLCDをブレッドボードに直結していますが、回路的には上図右下の回路と等価です。

I2cLcd-2

●制御コマンド

LCDを制御するコマンド(I2Cで受信する2バイトのデータ)は、1バイト目がレジスタセレクトの0×00(LCDコマンド)か0×01(LCDデータ)、2バイト目がコマンドコードか文字コードとなっています。

●プログラム/ファームウェア(I2CLcdCtrl.ino)

動作の概要は、まず、LCDを初期化して、I2Cスレーブに設定し、I2Cの受信を待ちます。I2Cでスレーブ受信したら、内容に応じてLCDへデータを送ります。

次にコードを示します。典型的なI2Cのスレーブ受信処理です。

//
//  I2C制御 LCDコントローラ
//    copyright (c) 2013  http://www.wsnak.com
//
//    汎用LCDモジュールのI2C化キット
//
//    12/11/15
//

/*
  汎用のLCDへ接続して、I2Cデバイス化する、Arduino使用のコントローラ
*/

#include <Wire.h>

/*
  LCD data PORTD D4~D7
  LCD E  D8
  LCD RS D9
*/

#define E_ON    digitalWrite(8, HIGH)
#define E_OFF   digitalWrite(8, LOW)
#define RS_CMD  digitalWrite(9, LOW)    // RS=0
#define RS_DATA digitalWrite(9, HIGH)   // RS=1

#define LCD_DAT PORTD     // LCD DB0~DB7

#define TST_SW  !(PINC&(1<<3))          // PC3 (A3) ジャンパショート時テスト

byte CmdCnt;
byte Cmd, Data;

// プロトタイプ
void writeCmd(void);
void WriteData(byte dat);
void WriteCmd(byte dat);
void Write4bitCmd(byte data);
void Write4bitData(byte data);
void LcdInit(void);
void E_Pulse(void);

void setup(void) {
  // 入力ポートのデジタルバッファをイネーブルにする
  DIDR0 &= ~(1<<ADC3D);   // ADC3

  // A3(PC3) ディジタル入力に再設定
  DDRC &= ~(1<<3);      // input
  PORTC |= (1<<3);      // pullup enable

//  Wire.begin(0x50);
  Wire.begin(0x20);
  Wire.onReceive(hSlvRcv);

  CmdCnt = 0;

  pinMode(4, OUTPUT);   // LCD DB4
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);   // LCD DB7

  pinMode(8, OUTPUT);   // LCD E
  pinMode(9, OUTPUT);   // LCD RS

  E_OFF;
  RS_CMD;

  LcdInit();

  // テスト表示(A3ポートのジャンパ設定による)
  if(TST_SW) {
    delay(100);
    WriteData('T');
    WriteData('E');
    WriteData('S');
    WriteData('T');
  }
}

// -----------------------
// メインループ
// -----------------------
void loop(void) {

}

// スレーブ受信ハンドラ
void hSlvRcv(int cnt) {
  int i;

  for(i = 0; i < cnt; i+=2) {
    Cmd = Wire.read();
    Data = Wire.read();
    writeCmd();
  }
}

// -----------------------
// コマンド書き込み
// -----------------------
void writeCmd(void) {
  if(Cmd == 0x00) {
    // LCDコマンド
    WriteCmd(Data);
  } else {
    // LCDデータ
    WriteData(Data);
  }
}

// *********************************
//  LCD初期化 (4ビットモード)
// *********************************
void LcdInit(void) {

  delay(15);

  Write4bitCmd(0x3);        //
  delay(5);
  Write4bitCmd(0x3);        //
  delay(5);
  Write4bitCmd(0x3);        //
  delay(5);
  Write4bitCmd(0x2);        //
  delay(5);

  WriteCmd(0x01);       // clear
  delay(5);

  WriteCmd(0x06);       // entry mode set
  delay(5);

  WriteCmd(0x0C);       // display on/off control
  delay(5);

  WriteCmd(0x1C);       // cursor/display shift
  delay(5);

  WriteCmd(0x28);       // function set
  delay(5);

  WriteCmd(0x02);       // home
  delay(5);
}

// LCDデータ書き込み
void WriteData(byte dat) {
  Write4bitData(dat >> 4);    // 上位4bit
  Write4bitData(dat);         // 下位4bit
}

// LCDコマンド書き込み
void WriteCmd(byte dat) {
  Write4bitCmd(dat >> 4);     // 上位4bit
  Write4bitCmd(dat);          // 下位4bit
}

// 4ビットLCDコマンド書き込み
void Write4bitCmd(byte data) {
  RS_CMD;

  LCD_DAT = data << 4;
  E_Pulse();
}

// 4ビットLCDデータ書き込み
void Write4bitData(byte data) {
  RS_DATA;

  LCD_DAT = data << 4;
  E_Pulse();
}

// eパルス出力
void E_Pulse(void) {
  E_OFF;
  delayMicroseconds(1);
  E_ON;
  delayMicroseconds(1);
  E_OFF;
  delayMicroseconds(100);
}

22~25行目は各制御信号を切り替えるマクロです。

45~49行目はA3(アナログ)をディジタル入力ポートに再設定して、プルアップも有効化しています。ここにジャンパを付けて、起動時のテスト表示の有無を切り替えます。

52行目でI2Cスレーブに設定しています。ここではスレーブアドレスは0×20にしています。

53行目はI2Cでスレーブ受信した時に呼び出されるハンドラ(処理関数)を登録しています。受信があると、”hSlvRcv()”という関数が呼び出されるた、そこで受信データを取り出して処理します。

57~63行目は使用するディジタルポートを出力に設定しています。

68行目の”LcdInit()”関数でLCDを4ビットモードに初期化して画面をクリアさせています。

71行目でA3(ディジタル入力に再設定済)の状態を読み出し、ジャンパショート時はテスト文字を表示させます。

88行目の”hSlvRcv()”はI2Cスレーブ受信時に呼び出されるハンドラです。2バイト読み出して、”Cmd”と”Data”というグローバル変数にデータを保存し、”writeCmd()”という関数へ渡します。

101行目の”writeCmd()”で”Cmd”の内容に応じて、LCDコマンド設定関数”WriteCmd()”またはLCDデータ設定関数”WriteData()”をよびだします。

114行目は起動直後にLCDを初期化する関数です。4ビットモード、画面クリア、カーソル位置クリアなど、LCDを初期化します。

●I2C化コントロール・プログラム ダウンロード

I2C化ファームウェア(40文字×4行専用) ZIPファイルI2CLcdCtrl

●WSN318(14ピンLCD)用プログラム

基板化した回路では、40文字×4行のC-51849NFJと回路を兼用にするため、ディジタルポートのアサインが上記プログラムと一部異なります。

LEDの”E”がD10が、”RS”がD12にアサインされています。前項のプログラム で一部を修正すれば使用できます。

22~25行目を次のように修正します。

#define E_ON    digitalWrite(10, HIGH)
#define E_OFF   digitalWrite(10, LOW)
#define RS_CMD  digitalWrite(12, LOW)    // RS=0
#define RS_DATA digitalWrite(12, HIGH)   // RS=1

62、63行目を次のように修正します。

  pinMode(10, OUTPUT);  // LCD E
  pinMode(12, OUTPUT);  // LCD RS

上記の修正をしたWSN318用のコントロールプログラムを掲載しておきます。

WSN318用I2C化ファームウェア(14ピン専用) ZIPファイル I2CLcdCtrl318

適当なフォルダに解凍して使ってください。他のファイルと同様、親フォルダも含めて日本語文字は使えないので注意してください。なお、このプログラムは40文字×4行のLCDには使えません。専用のプログラムは後述します。

次の写真は、プログラム書き込みの際にWSN283(P2:USB/電源部)をアダプタWSN319を通して接続したところです。この状態でWSN318はArduino Duemilanove互換となります。

注意:WSN318にはあらかじめArduinoファームウェアを書き込んでおく必要があります。

img_318_319_283-1


Arduinoを使ったLCDや7セグメントLEDのI2C化の記事は書籍「Arduino実験キットで楽ちんマイコン開発」でも取り扱っています。なお、同書籍では上記写真のように試作機をブレッドボードで製作しましたが、現在は次のような専用の小型基板を用意しています。それぞれ、Arduinoを専用コントローラとして使っていますが、プログラムは通常のArduinoとして作成し、そのまま作動します。

参考文献

コメントは受け付けていません。