Seeeduino XIAO | キャラクタLCD シリアル編

スポンサーリンク

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

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

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

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

 

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

必要なもの

  • I2C接続のキャラクタLCD
     秋月電子などで300円くらいから購入できます。
     今回はACM0802C-NLW-BBW-IICを使います。
  • Seeeduino XIAO
     今回はSeeeduino XIAOを使いますが、I2Cが使えるマイコンなら何でもOK。
  • 10kΩの半固定抵抗
     バックライトの明るさ調整に使います。
     バックライトがないLCDを使う場合は不要です。
  • レベル変換モジュール
     Seeeduino XIAOのI/O電圧は3.3Vに対し、
     LCDのIO電圧は5Vなのでレベル変換モジュールを挟んで接続します。
     マイコンとLCDでI2CのI/O電圧が同じ場合は不要です。

接続を確認する

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

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

今回はLCDが5V、マイコンが3.3VのI/Oなのでレベル変換モジュールを使います。

続いて秋月の商品ページのよくある質問をチェック。
このLCDは基板上にすでにI2Cのプルアップ抵抗が実装されているようです。

LCDよくある質問

以上から回路図を書いてみました。

LCD回路図

回路図中の「+5V」「+3.3V」「SDA」「SCL」「GND」は
Seeeduino XIAOの対応する端子と接続します。
LCDのSA0, SA1をHigh/LowどちらにするかでI2Cアドレスを調整できます。

LCD接続図

ブレッドボード上で接続するとこんな感じになりました。

プログラムをつくる

HD44780 Datasheet
HD44780データシートより

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

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

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

HD44780 Datasheet
HD44780データシートより

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

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

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

LCDのデータシートより

具体的なI2Cを使った制御方法はLCDのデータシートに書いてあります。
コントロールバイト(1バイト)とデータバイト(1バイト)で1セットのようです。
A0はコマンドを送るときは0、DDRAMに書き込むときは1です。

まずはコマンド用の関数を作っておきます。
今回はLCDのSA0, SA1をHighに接続したのでI2Cアドレスは0x3Fになります。

void send_command(byte command_data)
{
  Wire.beginTransmission(0x3F); //I2C Address
  Wire.write(B00000000);        //controll byte
  Wire.write(command_data);     //data byte
  Wire.endTransmission();
}

ちなみに Wire.write() でこまめにデータを送っているのではなく、
データは溜めておいて Wire.endTransmission() でまとめて送信しているようです。

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

void send_char(byte char_data)
{
  Wire.beginTransmission(0x3F); //I2C Address
  Wire.write(B01000000);        //control byte
  Wire.write(char_data);        //data byte
  Wire.endTransmission();
}

作った関数を使ってメインのコードを書くとこんな感じ。

void setup()
{
  Wire.begin();
  delay(100);
  send_command(B00111100); //Function set
  delay(100);
  send_command(B00111100); //Function set
  delay(100);  
  send_command(B00111100); //Function set
  delay(100);
  send_command(B00111100); //Function set
  send_command(B00001000); //Display off
  send_command(B00000001); //Display clear
  send_command(B00000111); //Entry mode set
  send_command(B00001100); //Display on
  
  send_command(B10000000); //set DDRAM address
  send_char(B11000010);    // ツ
  send_char(B10111000);    // ク
  send_char(B10101111);    // ッ
  send_char(B11000011);    // テ
  send_char(B11010000);    // ミ
  send_char(B11011001);    // ル

  send_command(B11000000); //set DDRAM address
  send_char(B01001000);    // H
  send_char(B01000100);    // D
  send_char(B00110100);    // 4
  send_char(B00110100);    // 4
  send_char(B00110111);    // 7
  send_char(B00111000);    // 8
  send_char(B00110000);    // 0
  
  send_command(B00001100); //Display on
}

実行する

プログラムをマイコンに書き込んで実行してみると文字が表示されました。
表示のコントラストは半固定抵抗をドライバーで回して調節します。
一番文字が見やすくなるところで止めます。

今回のコード全文は以下。

#include <Wire.h>

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

void setup()
{
  Wire.begin();
  delay(100);
  send_command(B00111100); //Function set
  delay(100);
  send_command(B00111100); //Function set
  delay(100);  
  send_command(B00111100); //Function set
  delay(100);
  send_command(B00111100); //Function set
  send_command(B00001000); //Display off
  send_command(B00000001); //Display clear
  send_command(B00000111); //Entry mode set
  send_command(B00001100); //Display on
  
  send_command(B10000000); //set DDRAM address
  send_char(B11000010);
  send_char(B10111000);
  send_char(B10101111);
  send_char(B11000011);
  send_char(B11010000);
  send_char(B11011001);

  send_command(B11000000); //set DDRAM address
  send_char(B01001000);
  send_char(B01000100);
  send_char(B00110100);
  send_char(B00110100);
  send_char(B00110111);
  send_char(B00111000);
  send_char(B00110000);
  
  send_command(B00001100); //Display on
}

void send_command(byte command_data)
{
  Wire.beginTransmission(0x3F);
  Wire.write(B00000000);
  Wire.write(command_data);
  Wire.endTransmission();
}

void send_char(byte char_data)
{
  Wire.beginTransmission(0x3F);
  Wire.write(B01000000);
  Wire.write(char_data);
  Wire.endTransmission();
}

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

あとがき

パラレル接続のキャラクタLCDについても以下の記事で解説しました。

ここで使っているSeeeduino Nanoを使うと
レベル変換モジュールも必要なく接続が簡単になります。
(シリアル編でもSeeeduino Nano使えばよかった。)

コメント

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