パラレル接続のキャラクタLCDを動かしてみる
Seeeduino Nanoを使ってパラレル接続のキャラクタLCDを動かします。
キャラクタLCDはHD44780というドライバを使っているものがほとんどなので
16文字2行でも8文字2行でも、何色の液晶でも、大体動かし方は同じです。
LCDライブラリも存在しますがあえて使わずに
LCDドライバHD44780とLCDのデータシートを読みながら作っていきます。
HD44780はシンプルなインターフェースなので勉強によい。かも。
必要なもの
- パラレル接続のキャラクタLCD
秋月電子などで400円くらいから購入できます。
今回はACM1602K-NLW-BBWを使います。 - Seeeduino Nano
今回はSeeeduino Nanoを使いますが、他のマイコンでもOK。 - 10kΩの半固定抵抗
バックライトの明るさ調整に使います。
バックライトがないLCDを使う場合は不要です。
接続を確認する
まずは使用するLCDのデータシートを確認してみてください。
LCDとの接続は左図のようにしました。
5V, E, RS, DB7~DB4の7本を
マイコンと接続します。
データ線は4本のみ接続していますが、
DB7~DB0の8本とも接続する場合は
この後説明する初期化のときに
8bitモードを指定してください。
今回はLCDからのReadはしないので
R/WピンはGNDに固定します。
接続するとこんな感じになりました。
プログラムをつくる
まずはLCDドライバHD44780の
データシートから確認していきます。
左図が4bitモードの初期化の流れです。
起動後まずはこれに沿って順番に
コマンドを発行していきます。
データシートには
コマンドの一覧も載っているので
合わせてチェックしておきます。
8bitモードで使う場合は
I2CキャラクタLCDの記事に
8bitの初期化フローを載せているので
参考にしてみてください。
タイミングスペックも確認しておきます。
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に文字が表示されました!
コード全文は以下です。
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互換コントローラの中にはいろんな性格のやつがいるのだろうか。
コメント