(画像をクリックするとサンプルプログラムの動画を表示します。)
LCDのキャラクタディスプレイとして不動の地位を得ているHD44780コントローラー 互換のSC1602ディスプレイをPICで制御する方法について纏めたページです。過去に 似たようなページを作っていましたが、 情報が 古かったり不充分な点があったので、備忘録としての意味もあって改めて作成しました。
ライブラリおよびサンプルプログラムのソースはこちら
Pin No | Pin Out | Description | 備考 |
---|---|---|---|
1 | VDD | 電源(+5V) | 互換品はVDD,VSSは逆転している場合がある。 ノイズ対策のため、VDD-VSS間に10uF程度のコンデンサを接続する事が推奨されます。 |
2 | VSS | GND | |
3 | Vo | Contrast Adj | 20kΩ程度のVRでVDD-VSS間で電圧調整出来るよう接続 |
4 | RS | Register Select | コマンド発行の際0,データ転送の際1にセット |
5 | R/W | Read/Write | 読出:Hi, 書込:Low |
6 | E | Enable Signal | 通常はLowにしておき、送受信の際Positive pulseを与える。 |
7 | DB0 | Data Bit0 | 4bitモードではBD0:3はオープン |
8 | DB1 | Data Bit1 | |
9 | DB2 | Data Bit2 | |
10 | DB3 | Data Bit3 | |
11 | DB4 | Data Bit4 | |
12 | DB5 | Data Bit5 | |
13 | DB6 | Data Bit6 | |
14 | DB7 | Data Bit7 |
モジュールの桁数や行数、表示モードにより、アドレッシングが異なります。
基本的に80文字分のメモりがあり、そのうち表示可能な範囲を表示しています。表示されているかに関らず、任意の位置にWrite可能です。
1 | 2 | 3 | ... | 39 | 40 | 41 | ... | 78 | 79 | 80 |
---|---|---|---|---|---|---|---|---|---|---|
00h | 01h | 02h | ... | 26h | 27h | 28h | ... | 4Dh | 4Eh | 4Fh |
1 | 2 | 3 | ... | 38 | 39 | 40 |
---|---|---|---|---|---|---|
00h | 01h | 02h | ... | 25h | 26h | 27h |
40h | 41h | 42h | ... | 65h | 66h | 67h |
キャラクタコード0x0から0x7の8個はCG RAM(後述)に割当られています。
0x8-0xFのキャラクタコードは0x0-0x7と同一のキャラクタが重複して読み出されます。
CG RAMはユーザーがキャラクタパターンを定義する事ができるエリアです。キャラクタジェネレータが備えていない文字を定義して利用することができます。
CG RAMアドレスは6 bitなので、上位3 bitでキャラクタを指定、残りの3 bitでキャラクタパターンの行を指定します。各行毎のパターンはCG RAMデータとして与えます。キャラクタパターンが5x7 bitで表現されているので、データビット7:5は使用しません。
Instruction | RS | R/W | DB7 | DB6 | DB5 | DB4 | DB3 | DB2 | DB1 | DB0 | Description | 実行時間 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Clear Display | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 全表示クリア後カーソルをホーム位置(0x00)へ戻す。 | 1.52ms(1.62ms) |
Return Home | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | x | カーソルをホーム位置へ戻す。ディスプレイシフトも初期位置に戻ります。 | |
Entry Mode Set | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S | カーソルのインクリメント方向、表示シフトを設定します。 I/D=1:右,I/D=0:左 S=1:表示シフトON,S=0:表示シフトOFF |
37us(40us) |
Display ON/OFF | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B | 表示、カーソルON/OFF D=1:ディスプレイON C=1:ブロックカーソルON B=1:ブリンクON |
|
Corsor or Display Shift | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | x | x | カーソル移動/表示シフト S/C=1:表示シフト,S/C=0:カーソル移動 R/L=1:右,R/L=0:左 |
|
Function Set | 0 | 0 | 0 | 0 | 1 | DL | N | F | x | x | 通信モード、行数、Font sizeの設定 DL=1:8bit,DL=0:4bit N=1:2line,N=0:1line F=1:5x10dot,F=0:5x7dot |
|
Set CGRAM address | 0 | 0 | 0 | 1 | AC5 | AC4 | AC3 | AC2 | AC1 | AC0 | CG RAMのアドレスをセットします。以後CG RAMへのデータアクセスとなる。 | |
Set DDRAM address | 0 | 0 | 1 | AC6 | AC5 | AC4 | AC3 | AC2 | AC1 | AC0 | DD RAMのアドレス(カーソル位置)をセットします。以後DD RAMへのデータアクセスとなる。 | |
Write data to RAM | 1 | 0 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | CG RAM, DD RAMへのデータWrite | |
Read data from RAM | 1 | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | CG RAM, DD RAMからのデータ読出し | |
Read Busy flag and address | 0 | 1 | BF | AC6 | AC5 | AC4 | AC3 | AC2 | AC1 | AC0 | Busy flag, カレントDD ROM/CG ROMアドレスの読出し BF=1:Busy,BF=0:Idle |
0us |
xは未使用ビットを示す。
(実行時間)はFosc=250KHzの時の値。三共社製、セイコー製がこのタイプのようです。
どのメーカーも同様のようです。三共社のものが解りやすいので、以下に示します。
キャラクター | 記号 | Min | Typ | Max | 単位 |
---|---|---|---|---|---|
Eサイクル時間 | to | 1200 | - | - | ns |
E立上り/立下り時間 | tr,tf | - | - | 25 | |
Eパルス幅(High,Low) | tw | 140 | - | - | |
R/WとRSセットアップ時間 | tsu1 | 0 | - | - | |
R/WとRSホールド時間 | th1 | 10 | - | - | |
データセットアップ時間 | tsu2 | 40 | - | - | |
データホールド時間 | th2 | 10 | - | - |
キャラクター | 記号 | Min | Typ | Max | 単位 |
---|---|---|---|---|---|
Eサイクル時間 | to | 1200 | - | - | ns |
E立上り/立下り時間 | tr,tf | - | - | 25 | |
Eパルス幅(High,Low) | tw | 140 | - | - | |
R/WとRSセットアップ時間 | tsu | 0 | - | - | |
R/WとRSホールド時間 | th | 10 | - | - | |
データ遅延時間 | tD | - | - | 100 | |
データホールド時間 | tDH | 10 | - | - |
BFが0になった後、アドレスカウンタの自動インクリメントには6us程度の遅延時間(TAdd)があるので、直ちに次の書込を行う場合は注意が必要です。
以下にインストラクションによる初期可処理を示します。
HD44780のマニュアルによると電源条件を満せば自動初期化が可能な ようですが、三共社以外マニュアルに記載が見付かりません。外付け回路に依存するため、 SUNLIKEや他の互換品で利用できるか不明です。
最初のFunction setの後の待ち時間を忘れがちなので注意しましょう。
Display offについては、on/off何れでもよいようです。
4bitモードと8bitモードが選択できます。4bitモードでは接続ピン数が少くなる一方で、 1 byte送るのに2回にわけなければならないので、転送に要する時間やプログラムの ステップ数は増加します。元々、高速に転送出来るデバイスではないので、ピン数の節約 の方が優先されるケースが殆どのようです。
空きピンは特に必要がない限り、オープンにしておきます。このあたりはマニュアルに 記載されてなかったりしますが、HD44780のマニュアルではopenとなっています。
このページで示したH/W、S/Wの何れも、4bitモードを想定して作成していますが、8bit モードの方が制御は簡単なので、応用は容易だと思います。
メリットとしては、BFをチェックする事で、待時間を幾らか短くしたり、別の処理を
行ってからチェックすることで時間を有効に使う事ができます。
ただし、最大命令実行時間に対し、劇的に短くなるとは思えませんし、予め時間が判って
いる別の処理ならば、待時間に行わせる事は可能なので、大きなアドバンテージはなさ
そうです。
一方、デメリットとしては、処理が複雑になることがあげられます。
また、LCDモジュール側の故障でBFが0にならないケースで、処理系のデッドロックを防止
するためにはタイムアウトを設ける必要があります。
BFをチェックしない場合は、waitを入れるだけでよいので、処理時間が重要視される 処理で無い場合は処理が簡単になります。さらに、もし一切Readを行わないのであれば、 マイコンとの接続数を減らすこともできます。
上記でのべたとおり、Readを行わない場合、プルダウンする事により、接続ピン数を 減らす事ができるが、改行や画面スクロールなどを実装する場合、ソフトウェアで カーソル位置を管理するより、LCDモジュールのアドレスカウンタを利用する方が簡単で 確実です。EやRSの分を考えると、1 Port(8 Pin)全てをLCD用に割当ててしまうケースが 多いので、R/Wを用いて自動改行などを実装するのは、悪い考えではないと思います。
他社製品との互換牲を考えると、実行時間の長いほうに合せておけばよいので、Display
clearとReturn Homeが1.62ms、それ以外は40us以上掛ると想定しておくのが良いでしょう。
仕様書をみると、FsocのMINは190kHzとなっているので、個体差や環境によっては1.4倍位
の実行時間になる可能性も無いとは言いきれませんが、特に問題が出たことがないので、
可能性を知っておけば十分でしょう。
インストラクションの処理時間が入るため、Writeサイクル(tc)が1.2usを切ってしまうことはあまりないと思います。
EのPositive Pulse幅(tw)を140ns以上確保する為には、4 clock cycleのPICでは28.5MHzを超えるとwaitを入れる必要があるかもしれません。
その他の100ns以下のdelayは2 clock sycleで20MBを超えるなど、よほど高速なPICでない限り気にする必要はないはずです。
Busy flag を用いたWrite場合はアドレスカウンタのインクリメントについては配慮する必要があります。
典型的な構成です。R/W pinはGNDに落し、Write専用としています。
XC8用にライブラリも書き直したので、合せて公開します(サンプルソースに同梱しています)。変更して使っていただいてもよいですし、実装やサンプルプログラムが参考になれば幸いです。
lcd4.hに若干の変更が必要です。
周波数とポートの設定です。bit操作が必要部分をうまい事自動で設定されると良いのですが、旨い方法が見付かりませんでした。
// CONFIG #define _XTAL_FREQ 10000000 // clock frequency in Hz #define LCD4_PORT PORTB // output port #define LCD4_CONFIGREG TRISB // config register for the output port #define LCD4_E PORTBbits.RB0 // output port which is connected E #define LCD4_RS PORTBbits.RB1 // output port which is connected RS
LCDをコマンドを用いて4bit modeに初期化します。引数は不要です。
カーソルをホームポジションへ移動します。0x02を書き込んだ後、2ms waitします。
キャラクタを出力します。引数にキャラクタコードを指定します。
任意のコマンドをWriteします。引数にコマンドを指定します。実行後40us waitします。
代表的なコマンドはlcd4.hに定義してあるので、マクロ変数で引数を指定するとわかりやすいです。
文字列を出力します。引数に文字列の開始ポインタを指定します。文字はNULLでターミネートされている必要があります。よって、CG RAM(0)は含めることができません。
表示範囲を左/右に1文字、あるいはn文字シフトします。
カーソルを左/右に1文字、あるいはn文字移動します。
カーソルを任意の位置に移動します。引数にDD RAMアドレスを指定します。以降のアクセスは指定したDD RAMアドレスに行われます。
CG RAMアドレスを設定します。以降のアクセスは指定したCG RAMアドレスに行われます。
メモリ上のデータを用いてCG RAMにユーザー定義文字をセットします。引数には、キャラクタコードとデータの開始アドレスを指定します。データは8bytesの連続領域に置かれている必要があります。
EEPROM上のデータを用いてCG RAMにユーザー定義文字をセットします。引数には、キャラクタコードとデータの開始EEPROMアドレスを指定します。データはあらかじめ8bytesの連続EEPROM領域に書き込んでおく必要があります。
文字列の出力、shiftによる表示範囲の移動、CG RAMへのキャラクタパターンのWriteとそれを用いた表示を行います。
putch()にキャラクタ出力関数を定義することで、printf()などの標準出力関数が使用できるようになりますので、printfを用いて文字列をDDRAMに書き込んでいます。
printfは便利な関数ですが、プログラムメモリを食うので、メモリが小さいPICでは厳しいものがあります。
表示範囲を1文字ずつ左右にシフトさせることにより、表示をスクロールさせています。
サンプルプログラムでは、EEPROMに保存されているデータから、CGRAMへキャラクタをセットしています。バーグラフを表示するために、5種類のキャラクタをセットしています。
80までの数値と横に80 dotのバーグラフを表示します。全て黒で塗りつぶされているキャラクタは、0xffが使えるので、5の倍数で余りが出る場合のみユーザーキャラクタを表示します。数値の表示にprintfを使うとプログラムメモリに収まりきらなかったので、数値を文字列に変換するサブルーチンを使っています。
多くの場合、必要な待ち時間が確保されていないなど、タイミングissueが多いと思われます、シュミレーター等でタイミングを確認することをお勧めします。
初期化に失敗した場合でも、文字化けした出力が出る場合があるので、そのような場合は初期化の失敗を疑って下さい。
電源の逆接、ピン番号が逆になっている場合、コントラスト調整の不具合が疑われます。