Seeeduino Nano | キャラクタLCD パラレル編

スポンサーリンク

パラレル接続のキャラクタLCDを動かしてみる

Seeeduino Nanoを使ってパラレル接続のキャラクタLCDを動かします。
キャラクタLCDはHD44780というドライバを使っているものがほとんどなので
16文字2行でも8文字2行でも、何色の液晶でも、大体動かし方は同じです。

LCDライブラリも存在しますがあえて使わずに
LCDドライバHD44780とLCDのデータシートを読みながら作っていきます。
HD44780はシンプルなインターフェースなので勉強によい。かも。

今回使う「Seeeduino Nano」はこちら

Seeeduino Nanoのセットアップ方法はこちらで解説しています
I2C接続のキャラクタLCDについてはこちらで解説しています

必要なもの

  • パラレル接続のキャラクタLCD
     秋月電子などで400円くらいから購入できます。
     今回はACM1602K-NLW-BBWを使います。
  • Seeeduino Nano
     今回はSeeeduino Nanoを使いますが、他のマイコンでもOK。
  • 10kΩの半固定抵抗
     バックライトの明るさ調整に使います。
     バックライトがないLCDを使う場合は不要です。

接続を確認する

まずは使用するLCDのデータシートを確認してみてください。

I2CのI/O電圧は要確認。3.3Vだったり5Vだったりします。
異なる電圧のI/O同士を接続すると壊れてしまうことがあります。
その場合はレベル変換ICを使って接続します。

キャラクタLCDの回路図

LCDとの接続は左図のようにしました。

5V, E, RS, DB7~DB4の7本を
マイコンと接続します。

データ線は4本のみ接続していますが、
DB7~DB0の8本とも接続する場合は
この後説明する初期化のときに
8bitモードを指定してください。

今回はLCDからのReadはしないので
R/WピンはGNDに固定します。

接続するとこんな感じになりました。

Seeeduino NanoとLCDの接続図

プログラムをつくる

HD44780データシート
HD44780データシートより

まずはLCDドライバHD44780の
データシートから確認していきます。

左図が4bitモードの初期化の流れです。
起動後まずはこれに沿って順番に
コマンドを発行していきます。

データシートには
コマンドの一覧も載っているので
合わせてチェックしておきます。

8bitモードで使う場合は
I2CキャラクタLCDの記事に
8bitの初期化フローを載せているので
参考にしてみてください。

HD44780データシート
HD44780データシートより

タイミングスペックも確認しておきます。
Setup/Hold Time等が記載されています。

制御線の大まかな動作は以下。
E」の立下りでデータをラッチ、
RS」がLowだとコマンド送信、
RS」がHighだとデータ書き込み。

LCDに表示する文字は、
文字コードから
1バイトで指定します。

CGRAMにデータを書き込むことで
自分の好きな文字を
表示させることもできますが
ここでは割愛します。

文字を表示する場所のアドレス(DDRAM address)は上図のようにマッピングされています。

#define DB7PIN 3
#define DB6PIN 2
#define DB5PIN 1
#define DB4PIN 0
#define RSPIN  4
#define EPIN   5

使うマイコンのGPIOはこのように指定しました。
実際の接続に合わせてピン番号は書き換えてください。

まずはコマンド送信用の関数を作ります。

void send_command(byte command_data)
{
  delay(1);
  digitalWrite(RSPIN, LOW);
  delay(1);
  digitalWrite(EPIN, HIGH);
  delay(1);
  digitalWrite(DB7PIN, bitRead(command_data, 3));
  digitalWrite(DB6PIN, bitRead(command_data, 2));
  digitalWrite(DB5PIN, bitRead(command_data, 1));
  digitalWrite(DB4PIN, bitRead(command_data, 0));
  delay(1);
  digitalWrite(EPIN, LOW);
  delay(1);
}

コマンドは4bitずつ受け取ってLCDに送るようにしています。
タイミングは余裕をもって1msのdelayを所々に入れています。

次にDDRAM書き込み用(文字表示用)の関数を作ります。

void send_char(byte char_data)
{
  delay(1);
  digitalWrite(RSPIN, HIGH);
  delay(1);
  digitalWrite(EPIN, HIGH);
  delay(1);
  digitalWrite(DB7PIN, bitRead(char_data, 7));
  digitalWrite(DB6PIN, bitRead(char_data, 6));
  digitalWrite(DB5PIN, bitRead(char_data, 5));
  digitalWrite(DB4PIN, bitRead(char_data, 4));
  delay(1);
  digitalWrite(EPIN, LOW);
  delay(1);
  digitalWrite(EPIN, HIGH);
  delay(1);
  digitalWrite(DB7PIN, bitRead(char_data, 3));
  digitalWrite(DB6PIN, bitRead(char_data, 2));
  digitalWrite(DB5PIN, bitRead(char_data, 1));
  digitalWrite(DB4PIN, bitRead(char_data, 0));
  delay(1);
  digitalWrite(EPIN, LOW);
  delay(1);
  digitalWrite(RSPIN, LOW);
  delay(1);
}

こちらは1バイト(=8ビット)まとめて受け取ってから
4ビットずつLCDに送るようにしています。

これらの関数を使ってメイン関数をつくります。

void setup()
{
  pinMode(DB7PIN, OUTPUT);
  pinMode(DB6PIN, OUTPUT);
  pinMode(DB5PIN, OUTPUT);
  pinMode(DB4PIN, OUTPUT);
  pinMode(RSPIN,  OUTPUT);
  pinMode(EPIN,   OUTPUT);
  
  delay(100);
  send_command(B00000011); //Function set
  delay(100);
  send_command(B00000011); //Function set
  delay(100);  
  send_command(B00000011); //Function set
  delay(100);
  send_command(B00000010); //Function set
  send_command(B00000010); //Function set
  send_command(B00001100);
  send_command(B00000000); //Display off
  send_command(B00001000);
  send_command(B00000000); //Display clear
  send_command(B00000001);
  send_command(B00000000); //Entry mode set
  send_command(B00000110);
  send_command(B00000000); //Display on
  send_command(B00001100);

  send_command(B00001000); //set DDRAM address
  send_command(B00000000);
  send_char(B00110010);    // 2
  send_char(B01101011);    // k
  send_char(B01110101);    // u
  send_char(B01110010);    // r
  send_char(B01110101);    // u
  send_char(B00101110);    // .
  send_char(B01100011);    // c
  send_char(B01101111);    // o
  send_char(B01101101);    // m  

  send_command(B00001100); //set DDRAM address
  send_command(B00000000);
  send_char(B00110010);    // 2
  send_char(B01101011);    // k
  send_char(B01110101);    // u
  send_char(B01110010);    // r
  send_char(B01110101);    // u
  send_char(B00101110);    // .
  send_char(B01100011);    // c
  send_char(B01101111);    // o
  send_char(B01101101);    // m
}

実行する

コードを実行してみるとLCDに文字が表示されました!

キャラクタLCD

コード全文は以下です。

void send_command(byte command_data);
void send_char(byte char_data);

#define DB7PIN 3
#define DB6PIN 2
#define DB5PIN 1
#define DB4PIN 0
#define RSPIN  4
#define EPIN   5

void setup()
{
  pinMode(DB7PIN, OUTPUT);
  pinMode(DB6PIN, OUTPUT);
  pinMode(DB5PIN, OUTPUT);
  pinMode(DB4PIN, OUTPUT);
  pinMode(RSPIN,  OUTPUT);
  pinMode(EPIN,   OUTPUT);
  
  delay(100);
  send_command(B00000011); //Function set
  delay(100);
  send_command(B00000011); //Function set
  delay(100);  
  send_command(B00000011); //Function set
  delay(100);
  send_command(B00000010); //Function set
  send_command(B00000010); //Function set
  send_command(B00001100);
  send_command(B00000000); //Display off
  send_command(B00001000);
  send_command(B00000000); //Display clear
  send_command(B00000001);
  send_command(B00000000); //Entry mode set
  send_command(B00000110);
  send_command(B00000000); //Display on
  send_command(B00001100);

  send_command(B00001000); //set DDRAM address
  send_command(B00000000);
  send_char(B00110010);    // 2
  send_char(B01101011);    // k
  send_char(B01110101);    // u
  send_char(B01110010);    // r
  send_char(B01110101);    // u
  send_char(B00101110);    // .
  send_char(B01100011);    // c
  send_char(B01101111);    // o
  send_char(B01101101);    // m  

  send_command(B00001100); //set DDRAM address
  send_command(B00000000);
  send_char(B00110010);    // 2
  send_char(B01101011);    // k
  send_char(B01110101);    // u
  send_char(B01110010);    // r
  send_char(B01110101);    // u
  send_char(B00101110);    // .
  send_char(B01100011);    // c
  send_char(B01101111);    // o
  send_char(B01101101);    // m
}

void send_command(byte command_data)
{
  delay(1);
  digitalWrite(RSPIN, LOW);
  delay(1);
  digitalWrite(EPIN, HIGH);
  delay(1);
  digitalWrite(DB7PIN, bitRead(command_data, 3));
  digitalWrite(DB6PIN, bitRead(command_data, 2));
  digitalWrite(DB5PIN, bitRead(command_data, 1));
  digitalWrite(DB4PIN, bitRead(command_data, 0));
  delay(1);
  digitalWrite(EPIN, LOW);
  delay(1);
}

void send_char(byte char_data)
{
  delay(1);
  digitalWrite(RSPIN, HIGH);
  delay(1);
  digitalWrite(EPIN, HIGH);
  delay(1);
  digitalWrite(DB7PIN, bitRead(char_data, 7));
  digitalWrite(DB6PIN, bitRead(char_data, 6));
  digitalWrite(DB5PIN, bitRead(char_data, 5));
  digitalWrite(DB4PIN, bitRead(char_data, 4));
  delay(1);
  digitalWrite(EPIN, LOW);
  delay(1);
  digitalWrite(EPIN, HIGH);
  delay(1);
  digitalWrite(DB7PIN, bitRead(char_data, 3));
  digitalWrite(DB6PIN, bitRead(char_data, 2));
  digitalWrite(DB5PIN, bitRead(char_data, 1));
  digitalWrite(DB4PIN, bitRead(char_data, 0));
  delay(1);
  digitalWrite(EPIN, LOW);
  delay(1);
  digitalWrite(RSPIN, LOW);
  delay(1);
}

void loop()
{
  // put your main code here, to run repeatedly:
}

あとがき

LCDはいくつか持っていますが、
ものによっては同じコードで動かなかったりするような気がする。
一瞬だけ表示が出てすぐに消えちゃったりとか。

そういうときは手探りでいろんなコマンドを試し打ちしてます。
初期化の後とか、DDRAMへの書き込み後とか手当たり次第に試してみます。

どうにかして表示が出るところまで持っていくと、
次は一番最初のコードでも動いちゃったりとかする。
原因はよくわかってないですが深追いはしていません。

HD44780互換コントローラの中にはいろんな性格のやつがいるのだろうか。

I2C接続のキャラクタLCDの記事もあります

コメント

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