以前、RaspberryPi 3B+にLCD1602をI2Cで接続して、
下記で、パソコンと簡易ロジックアナライザーでI2C波形を見る手順を書きました。
RaspberryPi 3B+でロジックアナライザを使ってI2Cの波形を取得する方法 - 水瓶座列車
その記事で使用したプログラムは、
OSOYOOのセンサーセットに含まれているサンプルプログラムで、
動作確認としてはそれをただ実行しただけでした。
そのプログラムが一体どういう風にデータを作って送信しているのか、
理解していなかったので、今回はその理解も兼ねて解析や調査をしてみました。
1.LCD1602のデータシートの入手
LCD1602の制御方法を理解するためには、そのデバイスのデータシートが必要になります。
インターネットで検索すると、似たようなものはたくさんあるのですが、
私が買ったOSOYOOのLCDがどれに該当するのかわかりませんでした。
また、LCDに付けられたI2Cモジュールによって、データフォーマットが様々のようで、
やはり詳細な制御方法については、サンプルコードを解析するしかありませんでした。
ただ、LCDの制御コマンドは、どれもほぼ一緒だったので、参考にしたいと思います。
参考にしたデータシートは、下記です
https://www.openhacks.com/uploadsproductos/eone-1602a1.pdf
2.データシートの解説
私が参考にしたデータシートは英語で書かれているので、この時点で読むのが面倒になりますが、
それでも頑張って読んで制御方法を理解していきます。
ただ、全部を理解する必要は無いと思っていて、
必要なのはプログラムを書くための要所だけを抑えなければなりません。
またI2Cのことは一切記載されていません。
もともとGPIO経由で制御しているものにI2Cモジュールを付加した感じです。
それでは解説していきます。
ピンアサイン
まずラズパイとLCD1602を接続するために把握しておかなければならないのが、ピンアサイン。
ピンの場所は、この赤枠の部分になります。黄枠は、I2Cと電源の線になります。
画像ではLCDがブレッドボードに刺さっているように見えますが、刺さっていません。
ダウンロードしてきたデータシートを読むとピンアサインは、こんな感じです。
LCDのコントロール
次にLCDを制御するために必要な制御コマンドも把握する必要があります。
それは、データシートを参考にすると下表のようになっています。
サンプルプログラムを見てみると、上記のコマンドを全て使っているわけではなさそうで、
ここでは、使われているコマンドだけ説明していきたいと思います。
あと、基盤ではピン名がD7~D0で、参考にしたデータシートではピン名がDB7~DB0と、
ピン名が少し違いますが多分同じです。
Clear Display
画面をクリアするには、D0に1を書き込みます。
Display ON/OFF
LCDとカーソルとブリンクのON/OFFを制御するレジスタです。
先ほどのコマンド制御表のD2,D1,D0ピンに書き込む値に、D,C,Bとありますが、
1と0を書き込んだ時にどういう機能があるかが下記になります。
D:Display ON/OFF control bit
D = 1 (High) : ディスプレイをONにします。
D = 0 (Low) : ディスプレイをOFFにしますが、
表示されていたデータはそのままの状態になっています。
C: Cursor ON/OFF control bit
C = 1 (high) : カーソルをONします。
C = 0 (Low) : カーソルをOFFにしますが、
カーソル位置はそのままの状態になっています。
B:Cusor Blink ON/OFF control bit
B = 1 (high) : カーソルの点滅をONにします。
B = 0 (Low) : カーソルの点滅をOFFにします。
Function Set
ディスプレイの表示形式をレジスタにセットします。
先ほどのコマンド制御表のD4,D3,D2ピンに書き込む値に、DL,N,Fとありますが、
1と0を書き込んだ時にどういう機能があるかが下記になります。
DL:Interface data length control bit
DL = 1 (High) : 8ビットバスモード
DL = 0 (Low) : 4ビットバスモード
N: Display line number control bit
N = 1 (High) : 1行の表示モード
N = 0 (Low) : 2行の表示モード
F: Display font type control bit
F = 1 (High) : 5x8ドットモード
F = 0 (Low) : 5x11ドットモード
サンプルプログラムのコメント文では、8Lineや4Line、5x7と書かれていましたが、
このコメント文が間違っていると思われます。
5x7ドットなのか液晶をドット数を見ましたが、どうみても5x8ドットでした。
また、8Lineや4Lineも間違いでバスモードのことを言っていると思います。
Set DDRAM address
文字を表示するアドレスをセットします。
LCDのアドレスは、2列表示で1列16文字の場合、
1列目:0x00~0x1f
2列目:0x40~0x4f
になっています。
1列目に順番に文字を表示していくには、表示位置を0x00にセットしてから、
続いて文字データを送信すると表示されます。
Write data to RAM
表示したい文字データをこのレジスタにセットします。
8ビットで文字が構成されているので、ここで設定した4ビットバスモードだと、
2回データを書き込む必要があります。
文字データは、下表のようになっています。
特殊文字については、記載するのが難しかったので、参考にしたデータシートの方を見てください。
また、プログラムで書くときには、アスキーコード表に載っている文字は、
自動的に文字データとして変換され、そのまま文字表示することができます。
それ以外の文字(例えばア、ァ、特殊文字)は自分で文字データ値をセットしなければなりません。
アは0xb1、ァは0xa7というふうにプログラムで書く際に自分で変換する必要があります。
3.I2C通信の制御フォーマット
I2C通信でデバイスを制御するので、I2Cで送信するデータ構造を把握する必要があります。
完全なデータフォーマットは、対応したデータシートが無いのでわかりませんが、
サンプルプログラムから解析していきます。
ここでは4ビットバスモードにセットしているので、
コマンドデータや文字データを2回に分けて送信しなければなりません。
自分で入れた通信ログを解析してみるとコマンド/文字データ送信の基本的な構造は、
スレーブアドレスを含めた2バイトデータを4回送信することで成り立っていました。
その時のI2C通信フォーマットは、おそらくこんな感じです。
例えば、表示クリアのデータは、こんな感じ上から順に送信していました。
RSビットは、制御コマンドを送信する場合は0に、
文字データを送信する場合には1をセットします。
またサンプルプログラムには、EN、R/W、RSの記載はありましたが、
Eの記載がありませんでしたので、フォーマットはあくまで参考として見てください。
4.調査・解析結果と感想
調査・解析から理解できたことは、
・LCD制御について制御コマンドと文字データの2つで行っている。
・4ビットバスモードのI2C通信フォーマットが大体把握できた。
・I2C通信部分は、WiringPiのライブラリを使用していた。
・アスキーコードにある文字は、プログラム上にそのまま書いて表示できる。
・アスキーコード以外の文字は、自分で変換する必要がある。
・自作のプログラムでLCD1602に文字を表示するにはサンプルプログラムを移植した方が早い。
です。
極力ブラックボックスになっているところを無くしたかったのですが、
やっぱり対応したデータシートが無いので少し消化不良感が残りました。
サンプルプログラムが4ビットバスモードになっていたので、
それを前提にしましたが、時間があれば8ビットバスモードでできるかやってみたいと思います。
またI2Cについては、ユーザー空間からI2Cを使用する場合に、
ライブラリを使っているだけなのでそれ以上は調査していません。
5.最後に
この記事内容は、私がサンプルプログラムをもとに調査して理解した内容なので、
参考までに見て頂けるとありがたいです。
<関連・おすすめ記事>
I2Cの通信フォーマットや波形の読み方の解説 - 水瓶座列車
Bluetoothでマルチペアリング(複数台接続)できるキーボードのおすすめランキングベスト5 - 水瓶座列車
Bluetoothでマルチペアリング(複数台接続)できるマウスのおすすめランキングベスト5 - 水瓶座列車
RaspberryPi (ラズパイ)の購入時に最低限必要なものとおすすめセット - 水瓶座列車
Raspberry Pi 3B+ のGPIOピン割り当ての解説 - 水瓶座列車
Raspberry Pi 3B+ でI2CキャラクタLCD(1602) の動作確認 - 水瓶座列車
Linuxローダブルカーネルモジュールの作り方とアクセス手順 - 水瓶座列車